1
0
Fork 0

🎨 Updated prettier config

This commit is contained in:
Joost De Cock 2019-08-03 15:03:33 +02:00
parent b8e632998b
commit 6710d76b08
401 changed files with 13193 additions and 15620 deletions

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,4 +1,4 @@
import { dimensions } from "./shared";
import { dimensions } from './shared'
export default function(part) {
let {
@ -14,23 +14,23 @@ export default function(part) {
macro,
utils,
units
} = part.shorthand();
} = part.shorthand()
points.strapLeftCp2 = utils.beamsIntersect(
points.strapLeft,
points.strapCenter.rotate(90, points.strapLeft),
points.cbNeck,
points.cbNeck.shift(0, 10)
);
)
points.armholeCp2 = points.aaronArmhole.shiftFractionTowards(
points.armholeCorner,
options.backlineBend
);
)
points.strapRightCp1 = points.strapRight.shiftFractionTowards(
points.armholeCorner,
options.backlineBend
);
)
// Seamline
paths.seam = new Path()
@ -43,7 +43,7 @@ export default function(part) {
.line(points.strapLeft)
.curve(points.strapLeftCp2, points.cbNeck, points.cbNeck)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Complete pattern?
if (complete) {
@ -51,57 +51,54 @@ export default function(part) {
new Path()
.move(points.strapLeft)
.curve(points.strapLeftCp2, points.cbNeck, points.cbNeck)
.length() + store.get("frontNeckOpeningLength");
.length() + store.get('frontNeckOpeningLength')
let armholeLength =
new Path()
.move(points.aaronArmhole)
.curve(points.armholeCp2, points.strapRightCp1, points.strapRight)
.length() + store.get("frontArmholeLength");
points.bindinAnchor = new Point(
points.aaronArmhole.x / 4,
points.aaronArmhole.y
)
.attr("data-text", "cutTwoStripsToFinishTheArmholes")
.attr("data-text", ":\n")
.attr("data-text", "width")
.attr("data-text", ":")
.attr("data-text", units(sa * 6))
.attr("data-text", "\n")
.attr("data-text", "length")
.attr("data-text", ":")
.attr("data-text", units(armholeLength * 0.95 + 2 * sa))
.attr("data-text", "\n&#160;\n")
.attr("data-text", "cutOneStripToFinishTheNeckOpening")
.attr("data-text", ":\n")
.attr("data-text", "width")
.attr("data-text", ":")
.attr("data-text", units(sa * 6))
.attr("data-text", "\n")
.attr("data-text", "length")
.attr("data-text", ":")
.attr("data-text", units(neckOpeningLength * 0.95 + 2 * sa))
.attr("data-text-lineheight", 6);
.length() + store.get('frontArmholeLength')
points.bindinAnchor = new Point(points.aaronArmhole.x / 4, points.aaronArmhole.y)
.attr('data-text', 'cutTwoStripsToFinishTheArmholes')
.attr('data-text', ':\n')
.attr('data-text', 'width')
.attr('data-text', ':')
.attr('data-text', units(sa * 6))
.attr('data-text', '\n')
.attr('data-text', 'length')
.attr('data-text', ':')
.attr('data-text', units(armholeLength * 0.95 + 2 * sa))
.attr('data-text', '\n&#160;\n')
.attr('data-text', 'cutOneStripToFinishTheNeckOpening')
.attr('data-text', ':\n')
.attr('data-text', 'width')
.attr('data-text', ':')
.attr('data-text', units(sa * 6))
.attr('data-text', '\n')
.attr('data-text', 'length')
.attr('data-text', ':')
.attr('data-text', units(neckOpeningLength * 0.95 + 2 * sa))
.attr('data-text-lineheight', 6)
macro("cutonfold", {
macro('cutonfold', {
from: points.cfNeck,
to: points.cfHem,
grainline: true
});
})
macro("title", { at: points.title, nr: 2, title: "back" });
points.scaleboxAnchor = points.scalebox = points.title.shift(90, 100);
macro("scalebox", { at: points.scalebox });
macro('title', { at: points.title, nr: 2, title: 'back' })
points.scaleboxAnchor = points.scalebox = points.title.shift(90, 100)
macro('scalebox', { at: points.scalebox })
}
// Paperless?
if (paperless) {
dimensions(macro, points, sa);
macro("vd", {
dimensions(macro, points, sa)
macro('vd', {
from: points.cbHem,
to: points.cbNeck,
x: points.cbHem.x - sa - 15
});
})
}
return part;
return part
}

View file

@ -1,4 +1,4 @@
import { dimensions } from "./shared";
import { dimensions } from './shared'
export default function(part) {
let {
@ -16,75 +16,67 @@ export default function(part) {
complete,
paperless,
macro
} = part.shorthand();
} = part.shorthand()
// Hide Brian paths
for (let key of Object.keys(paths)) paths[key].render = false;
for (let key of Object.keys(paths)) paths[key].render = false
// Handle stretch
for (let i in points) points[i].x = points[i].x * (1 - options.stretchFactor);
for (let i in points) points[i].x = points[i].x * (1 - options.stretchFactor)
// Rename cb (center back) to cf (center front)
for (let key of ["Neck", "Shoulder", "Armhole", "Waist", "Hips", "Hem"]) {
points[`cf${key}`] = new Point(points[`cb${key}`].x, points[`cb${key}`].y);
for (let key of ['Neck', 'Shoulder', 'Armhole', 'Waist', 'Hips', 'Hem']) {
points[`cf${key}`] = new Point(points[`cb${key}`].x, points[`cb${key}`].y)
//delete points[`cb${key}`];
}
// Neckline
points.cfNeck = points.cfNeck.shift(
-90,
options.necklineDrop *
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip)
);
options.necklineDrop * (measurements.centerBackNeckToWaist + measurements.naturalWaistToHip)
)
// Strap
points.strapCenter = points.neck.shiftFractionTowards(
points.shoulder,
options.shoulderStrapPlacement
);
)
points.strapLeft = points.strapCenter.shiftTowards(
points.neck,
points.neck.dist(points.shoulder) * options.shoulderStrapWidth
);
points.strapRight = points.strapLeft.rotate(180, points.strapCenter);
)
points.strapRight = points.strapLeft.rotate(180, points.strapCenter)
points.necklineCorner = utils.beamsIntersect(
points.strapLeft,
points.strapRight.rotate(-90, points.strapLeft),
points.cfNeck.shift(0, points.armholePitch.x / 4),
points.cfNeck
);
)
points.strapLeftCp2 = points.strapLeft.shiftFractionTowards(
points.necklineCorner,
options.necklineBend
);
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(
points.necklineCorner,
options.necklineBend
);
)
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(points.necklineCorner, options.necklineBend)
// Hips
points.hips.x =
((measurements.hipsCircumference +
options.hipsEase * measurements.hipsCircumference) /
4) *
(1 - options.stretchFactor);
points.waist.x = points.hips.x; // Because stretch
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist) / 2);
((measurements.hipsCircumference + options.hipsEase * measurements.hipsCircumference) / 4) *
(1 - options.stretchFactor)
points.waist.x = points.hips.x // Because stretch
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist) / 2)
// Hem
points.hem.x = points.hips.x;
points.hem.x = points.hips.x
// Armhole drop
let side = new Path()
.move(points.hem)
.line(points.waist)
.curve(points.waistCp2, points.armhole, points.armhole);
let split = side
.intersectsY(points.armhole.y * (1 + options.armholeDrop))
.pop();
paths.side = side.split(split)[0];
paths.side.render = false;
points.aaronArmhole = split;
.curve(points.waistCp2, points.armhole, points.armhole)
let split = side.intersectsY(points.armhole.y * (1 + options.armholeDrop)).pop()
paths.side = side.split(split)[0]
paths.side.render = false
points.aaronArmhole = split
// Armhole
points.armholeCorner = utils.beamsIntersect(
@ -92,15 +84,9 @@ export default function(part) {
points.aaronArmhole.shift(180, 10),
points.strapRight,
points.strapLeft.rotate(90, points.strapRight)
);
points.armholeCp2 = points.aaronArmhole.shiftFractionTowards(
points.armholeCorner,
0.8
);
points.strapRightCp1 = points.strapRight.shiftFractionTowards(
points.armholeCorner,
0.6
);
)
points.armholeCp2 = points.aaronArmhole.shiftFractionTowards(points.armholeCorner, 0.8)
points.strapRightCp1 = points.strapRight.shiftFractionTowards(points.armholeCorner, 0.6)
// Seamline
paths.seam = new Path()
@ -113,35 +99,35 @@ export default function(part) {
.line(points.strapLeft)
.curve(points.strapLeftCp2, points.cfNeckCp1, points.cfNeck)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Store length of armhole and neck opening
store.set(
"frontArmholeLength",
'frontArmholeLength',
new Path()
.move(points.aaronArmhole)
.curve(points.armholeCp2, points.strapRightCp1, points.strapRight)
.length()
);
)
store.set(
"frontNeckOpeningLength",
'frontNeckOpeningLength',
new Path()
.move(points.strapLeft)
.curve(points.cfNeckCp1, points.cfNeckCp1, points.cfNeck)
.length()
);
)
// Complete pattern?
if (complete) {
macro("cutonfold", {
macro('cutonfold', {
from: points.cfNeck,
to: points.cfHem,
grainline: true
});
points.title = new Point(points.waist.x / 2, points.waist.y);
macro("title", { at: points.title, nr: 1, title: "front" });
points.logo = points.title.shift(-90, 75);
snippets.logo = new Snippet("logo", points.logo);
})
points.title = new Point(points.waist.x / 2, points.waist.y)
macro('title', { at: points.title, nr: 1, title: 'front' })
points.logo = points.title.shift(-90, 75)
snippets.logo = new Snippet('logo', points.logo)
if (sa) {
paths.saShoulder = new Path()
@ -149,31 +135,31 @@ export default function(part) {
.line(points.strapLeft)
.offset(sa)
.line(points.strapLeft)
.attr("class", "fabric sa");
paths.saShoulder.move(points.strapRight).line(paths.saShoulder.start());
.attr('class', 'fabric sa')
paths.saShoulder.move(points.strapRight).line(paths.saShoulder.start())
paths.saSide = paths.side
.offset(sa)
.line(points.aaronArmhole)
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
paths.saHem = new Path()
.move(points.cfHem)
.line(points.hem)
.offset(sa * 2.5)
.attr("class", "fabric sa")
.line(paths.saSide.start());
paths.saHem.move(points.cfHem).line(paths.saHem.start());
.attr('class', 'fabric sa')
.line(paths.saSide.start())
paths.saHem.move(points.cfHem).line(paths.saHem.start())
}
}
// Paperless?
if (paperless) {
dimensions(macro, points, sa);
macro("vd", {
dimensions(macro, points, sa)
macro('vd', {
from: points.cfHem,
to: points.cfNeck,
x: points.cfHem.x - sa - 15
});
})
}
return part;
return part
}

View file

@ -1,20 +1,20 @@
import freesewing from "@freesewing/core";
import Brian from "@freesewing/brian";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
import freesewing from '@freesewing/core'
import Brian from '@freesewing/brian'
import plugins from '@freesewing/plugin-bundle'
import config from '../config'
// Parts
import draftBack from "./back";
import draftFront from "./front";
import draftBack from './back'
import draftFront from './front'
// Create design
const Pattern = new freesewing.Design(config, plugins);
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
Pattern.prototype.draftBase = function(part) {
// Getting the base part from Brian
return new Brian(this.settings).draftBase(part);
};
Pattern.prototype.draftFront = part => draftFront(part);
Pattern.prototype.draftBack = part => draftBack(part);
return new Brian(this.settings).draftBase(part)
}
Pattern.prototype.draftFront = part => draftFront(part)
Pattern.prototype.draftBack = part => draftBack(part)
export default Pattern;
export default Pattern

View file

@ -1,37 +1,37 @@
export function dimensions(macro, points, sa) {
macro("hd", {
macro('hd', {
from: points.cfHem,
to: points.hem,
y: points.hem.y + sa * 2.5 + 15
});
macro("hd", {
})
macro('hd', {
from: points.cfNeck,
to: points.strapLeft,
y: points.neck.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.cfNeck,
to: points.strapRight,
y: points.neck.y - sa - 30
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.aaronArmhole,
x: points.aaronArmhole.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.strapRight,
x: points.aaronArmhole.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.strapLeft,
x: points.aaronArmhole.x + sa + 45
});
macro("hd", {
})
macro('hd', {
from: points.cfNeck,
to: points.aaronArmhole,
y: points.neck.y - sa - 45
});
})
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -13,122 +13,114 @@ export default function(part) {
complete,
paperless,
macro
} = part.shorthand();
} = part.shorthand()
if (options.bowStyle === "square") options.tipWidth = options.knotWidth;
if (options.bowStyle === 'square') options.tipWidth = options.knotWidth
for (let option of [
"ribbonWidth",
"bandLength",
"tipWidth",
"knotWidth",
"bowLength",
"collarEase"
'ribbonWidth',
'bandLength',
'tipWidth',
'knotWidth',
'bowLength',
'collarEase'
])
store.set(option, measurements.neckCircumference * options[option]);
store.set(option, measurements.neckCircumference * options[option])
// For easy access
const knot = store.get("knotWidth");
const ribbon = store.get("ribbonWidth");
const tip = store.get("tipWidth");
const band = store.get("bandLength");
const transition = band * options.transitionLength;
const bow = store.get("bowLength");
const knot = store.get('knotWidth')
const ribbon = store.get('ribbonWidth')
const tip = store.get('tipWidth')
const band = store.get('bandLength')
const transition = band * options.transitionLength
const bow = store.get('bowLength')
// Points
points.bandBottomLeft = new Point(0, ribbon / 2);
points.bandTopLeft = points.bandBottomLeft.flipY();
points.bandBottomRight = points.bandBottomLeft.shift(0, band);
points.bandTopRight = points.bandBottomRight.flipY();
points.bandBottomLeft = new Point(0, ribbon / 2)
points.bandTopLeft = points.bandBottomLeft.flipY()
points.bandBottomRight = points.bandBottomLeft.shift(0, band)
points.bandTopRight = points.bandBottomRight.flipY()
points.transitionBottomRight = new Point(band + transition, knot / 2);
points.transitionTopRight = points.transitionBottomRight.flipY();
points.transitionBottomRight = new Point(band + transition, knot / 2)
points.transitionTopRight = points.transitionBottomRight.flipY()
points.tip1Bottom = new Point(band + transition + 0.5 * bow, tip / 2);
points.tip1Top = points.tip1Bottom.flipY();
points.tip2Bottom = new Point(band + transition + 1.5 * bow, tip / 2);
points.tip2Top = points.tip2Bottom.flipY();
points.knotBottom = new Point(band + transition + bow, knot / 2);
points.knotTop = points.knotBottom.flipY();
points.tip1Bottom = new Point(band + transition + 0.5 * bow, tip / 2)
points.tip1Top = points.tip1Bottom.flipY()
points.tip2Bottom = new Point(band + transition + 1.5 * bow, tip / 2)
points.tip2Top = points.tip2Bottom.flipY()
points.knotBottom = new Point(band + transition + bow, knot / 2)
points.knotTop = points.knotBottom.flipY()
if (options.endStyle === "pointed" || options.endStyle === "rounded") {
points.tip = new Point(points.tip2Bottom.x + points.tip2Bottom.y, 0);
} else points.tip = new Point(points.tip2Bottom.x, 0);
if (options.endStyle === 'pointed' || options.endStyle === 'rounded') {
points.tip = new Point(points.tip2Bottom.x + points.tip2Bottom.y, 0)
} else points.tip = new Point(points.tip2Bottom.x, 0)
points.grainlineStart = new Point(0, 0);
points.titleAnchor = new Point(points.tip1Top.x, 0);
points.grainlineStart = new Point(0, 0)
points.titleAnchor = new Point(points.tip1Top.x, 0)
// Paths
paths.cap = new Path().move(points.tip2Bottom);
if (options.endStyle === "straight") {
paths.cap = new Path().move(points.tip2Bottom).line(points.tip2Top);
} else if (options.endStyle === "pointed") {
paths.cap = new Path().move(points.tip2Bottom)
if (options.endStyle === 'straight') {
paths.cap = new Path().move(points.tip2Bottom).line(points.tip2Top)
} else if (options.endStyle === 'pointed') {
paths.cap = new Path()
.move(points.tip2Bottom)
.line(points.tip)
.line(points.tip2Top);
.line(points.tip2Top)
} else {
points.roundBottom = new Point(points.tip.x, points.tip2Bottom.y);
points.roundTop = points.roundBottom.flipY();
macro("round", {
points.roundBottom = new Point(points.tip.x, points.tip2Bottom.y)
points.roundTop = points.roundBottom.flipY()
macro('round', {
from: points.tip2Bottom,
to: points.tip,
via: points.roundBottom,
prefix: "bottom"
});
macro("round", {
prefix: 'bottom'
})
macro('round', {
from: points.tip,
to: points.tip2Top,
via: points.roundTop,
prefix: "top"
});
paths.cap = paths.bottomRounded.join(paths.topRounded);
prefix: 'top'
})
paths.cap = paths.bottomRounded.join(paths.topRounded)
}
paths.cap.render = false;
paths.cap.render = false
if (options.bowStyle === "diamond" || options.bowStyle === "butterfly") {
const cpl = options.bowStyle === "diamond" ? bow / 10 : bow / 4;
if (options.bowStyle === 'diamond' || options.bowStyle === 'butterfly') {
const cpl = options.bowStyle === 'diamond' ? bow / 10 : bow / 4
points.transitionBottomRightCp2 = points.bandBottomRight.shiftOutwards(
points.transitionBottomRight,
cpl
);
points.transitionTopRightCp1 = points.transitionBottomRightCp2.flipY();
points.tip1TopCp2 = points.tip1Top.shift(180, cpl);
points.tip1TopCp1 = points.tip1Top.shift(0, cpl);
points.tip1BottomCp1 = points.tip1Bottom.shift(180, cpl);
points.tip1BottomCp2 = points.tip1Bottom.shift(0, cpl);
points.knotTopCp2 = points.knotTop.shift(180, cpl);
points.knotTopCp1 = points.knotTop.shift(0, cpl);
points.knotBottomCp2 = points.knotBottom.shift(0, cpl);
points.knotBottomCp1 = points.knotBottom.shift(180, cpl);
points.tip2TopCp2 = points.tip2Top.shift(180, cpl);
points.tip2BottomCp1 = points.tip2Bottom.shift(180, cpl);
)
points.transitionTopRightCp1 = points.transitionBottomRightCp2.flipY()
points.tip1TopCp2 = points.tip1Top.shift(180, cpl)
points.tip1TopCp1 = points.tip1Top.shift(0, cpl)
points.tip1BottomCp1 = points.tip1Bottom.shift(180, cpl)
points.tip1BottomCp2 = points.tip1Bottom.shift(0, cpl)
points.knotTopCp2 = points.knotTop.shift(180, cpl)
points.knotTopCp1 = points.knotTop.shift(0, cpl)
points.knotBottomCp2 = points.knotBottom.shift(0, cpl)
points.knotBottomCp1 = points.knotBottom.shift(180, cpl)
points.tip2TopCp2 = points.tip2Top.shift(180, cpl)
points.tip2BottomCp1 = points.tip2Bottom.shift(180, cpl)
paths.seam = new Path()
.move(points.bandTopLeft)
.line(points.bandBottomLeft)
.line(points.bandBottomRight)
.line(points.transitionBottomRight)
.curve(
points.transitionBottomRightCp2,
points.tip1BottomCp1,
points.tip1Bottom
)
.curve(points.transitionBottomRightCp2, points.tip1BottomCp1, points.tip1Bottom)
.curve(points.tip1BottomCp2, points.knotBottomCp1, points.knotBottom)
.curve(points.knotBottomCp2, points.tip2BottomCp1, points.tip2Bottom)
.join(paths.cap)
.line(points.tip2Top)
.curve(points.tip2TopCp2, points.knotTopCp1, points.knotTop)
.curve(points.knotTopCp2, points.tip1TopCp1, points.tip1Top)
.curve(
points.tip1TopCp2,
points.transitionTopRightCp1,
points.transitionTopRight
)
.curve(points.tip1TopCp2, points.transitionTopRightCp1, points.transitionTopRight)
.line(points.bandTopRight)
.line(points.bandTopLeft)
.close();
.close()
} else {
paths.seam = new Path()
.move(points.bandTopLeft)
@ -141,85 +133,82 @@ export default function(part) {
.line(points.transitionTopRight)
.line(points.bandTopRight)
.line(points.bandTopLeft)
.close();
.close()
}
paths.seam.attr("class", "fabric");
paths.seam.attr('class', 'fabric')
// Complete?
if (complete) {
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
macro("grainline", {
macro('grainline', {
from: points.grainlineStart,
to: points.tip
});
points.logoAnchor = points.tip.shift(180, 20);
snippets.logo = new Snippet("logo", points.logoAnchor).attr(
"data-scale",
0.5
);
})
points.logoAnchor = points.tip.shift(180, 20)
snippets.logo = new Snippet('logo', points.logoAnchor).attr('data-scale', 0.5)
// Paperless?
if (paperless) {
let baseY = points.tip2Bottom.y + 15 + sa;
if (options.bowStyle === "butterfly" || options.bowStyle === "diamond") {
macro("hd", {
let baseY = points.tip2Bottom.y + 15 + sa
if (options.bowStyle === 'butterfly' || options.bowStyle === 'diamond') {
macro('hd', {
from: points.knotBottom,
to: points.tip2Bottom,
y: baseY
});
baseY += 15;
macro("hd", {
})
baseY += 15
macro('hd', {
from: points.tip1Bottom,
to: points.tip2Bottom,
y: baseY
});
baseY += 15;
macro("vd", {
})
baseY += 15
macro('vd', {
from: points.tip1Bottom,
to: points.tip1Top
});
})
}
macro("hd", {
macro('hd', {
from: points.transitionBottomRight,
to: points.tip2Bottom,
y: baseY
});
baseY += 15;
macro("hd", {
})
baseY += 15
macro('hd', {
from: points.bandBottomRight,
to: points.tip2Bottom,
y: baseY
});
baseY += 15;
macro("hd", {
})
baseY += 15
macro('hd', {
from: points.bandBottomLeft,
to: points.tip2Bottom,
y: baseY
});
macro("vd", {
})
macro('vd', {
from: points.bandBottomRight,
to: points.bandTopRight
});
macro("vd", {
})
macro('vd', {
from: points.transitionBottomRight,
to: points.transitionTopRight
});
macro("vd", {
})
macro('vd', {
from: points.tip2Bottom,
to: points.tip2Top,
x: points.tip.x + 15 + sa
});
if (options.endStyle !== "straight") {
macro("hd", {
})
if (options.endStyle !== 'straight') {
macro('hd', {
from: points.tip2Bottom,
to: points.tip,
y: points.tip2Bottom.y + 15 + sa
});
})
}
}
}
return part;
return part
}

View file

@ -1,19 +1,19 @@
export default function(part) {
let { complete, macro, points, paths, sa } = part.shorthand();
let { complete, macro, points, paths, sa } = part.shorthand()
paths.seam.render = true;
paths.seam.render = true
if (complete) {
if (sa) paths.sa.render = true;
macro("title", {
if (sa) paths.sa.render = true
macro('title', {
at: points.titleAnchor,
nr: 1,
title: "bowTie",
title: 'bowTie',
scale: 0.8
});
points.scaleboxAnchor = points.bandTopLeft.shift(30, 80);
macro("scalebox", { at: points.scaleboxAnchor });
})
points.scaleboxAnchor = points.bandTopLeft.shift(30, 80)
macro('scalebox', { at: points.scaleboxAnchor })
}
return part;
return part
}

View file

@ -1,22 +1,22 @@
export default function(part) {
let { options, points, paths, complete, macro, sa } = part.shorthand();
let { options, points, paths, complete, macro, sa } = part.shorthand()
if (options.adjustmentRibbon) {
part.render = false;
return part;
part.render = false
return part
}
paths.seam.render = true;
paths.seam.render = true
if (complete) {
if (sa) paths.sa.render = true;
macro("title", {
if (sa) paths.sa.render = true
macro('title', {
at: points.titleAnchor,
nr: 2,
title: "bowTie",
title: 'bowTie',
scale: 0.8
});
})
}
return part;
return part
}

View file

@ -1,20 +1,20 @@
export default function(part) {
let { options, points, paths, complete, macro, sa } = part.shorthand();
let { options, points, paths, complete, macro, sa } = part.shorthand()
if (options.adjustmentRibbon) {
part.render = false;
return part;
part.render = false
return part
}
if (complete) {
if (sa) paths.sa.render = true;
macro("title", {
if (sa) paths.sa.render = true
macro('title', {
at: points.titleAnchor,
nr: 3,
title: "bowTie",
title: 'bowTie',
scale: 0.8
});
})
}
return part;
return part
}

View file

@ -1,21 +1,21 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import config from '../config'
// Parts
import draftBase from "./base";
import draftBow1 from "./bow1";
import draftBow2 from "./bow2";
import draftBow3 from "./bow3";
import draftRibbon from "./ribbon";
import draftBase from './base'
import draftBow1 from './bow1'
import draftBow2 from './bow2'
import draftBow3 from './bow3'
import draftRibbon from './ribbon'
// Create new design
const benjamin = new freesewing.Design(config, plugins);
const benjamin = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
benjamin.prototype.draftBase = draftBase;
benjamin.prototype.draftBow1 = draftBow1;
benjamin.prototype.draftBow2 = draftBow2;
benjamin.prototype.draftBow3 = draftBow3;
benjamin.prototype.draftRibbon = draftRibbon;
benjamin.prototype.draftBase = draftBase
benjamin.prototype.draftBow1 = draftBow1
benjamin.prototype.draftBow2 = draftBow2
benjamin.prototype.draftBow3 = draftBow3
benjamin.prototype.draftRibbon = draftRibbon
export default benjamin;
export default benjamin

View file

@ -11,26 +11,20 @@ export default function(part) {
paths,
sa,
paperless
} = part.shorthand();
} = part.shorthand()
if (!options.adjustmentRibbon) {
part.render = false;
return part;
part.render = false
return part
}
// Points
points.bottomLeft = new Point(0, 0.5 * store.get("ribbonWidth"));
points.topLeft = points.bottomLeft.flipY();
points.bottomLeft = new Point(0, 0.5 * store.get('ribbonWidth'))
points.topLeft = points.bottomLeft.flipY()
// FIXME: How long should this adjustment ribbon be?
points.bottomRight = points.bottomLeft.shift(
0,
measurements.neckCircumference
);
points.topRight = points.bottomRight.flipY();
points.titleAnchor = points.topLeft.shiftFractionTowards(
points.bottomRight,
0.5
);
points.bottomRight = points.bottomLeft.shift(0, measurements.neckCircumference)
points.topRight = points.bottomRight.flipY()
points.titleAnchor = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
// Paths
paths.seam = new Path()
@ -40,30 +34,30 @@ export default function(part) {
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
macro("title", {
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
macro('title', {
at: points.titleAnchor,
nr: 4,
title: "ribbon",
title: 'ribbon',
scale: 0.5
});
})
if (paperless) {
macro("hd", {
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + 15 + sa
});
})
}
}
return part;
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,29 +1,29 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import Brian from "@freesewing/brian";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import Brian from '@freesewing/brian'
import config from '../config'
// Parts
import draftSleeve from "./sleeve";
import draftTopSleeve from "./topsleeve";
import draftUnderSleeve from "./undersleeve";
import draftSleeve from './sleeve'
import draftTopSleeve from './topsleeve'
import draftUnderSleeve from './undersleeve'
// Create new design
const Pattern = new freesewing.Design(config, plugins);
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods from Brian to prototype
Pattern.prototype.draftBase = function(part) {
return new Brian(this.settings).draftBase(part);
};
return new Brian(this.settings).draftBase(part)
}
Pattern.prototype.draftFront = function(part) {
return new Brian(this.settings).draftFront(part);
};
return new Brian(this.settings).draftFront(part)
}
Pattern.prototype.draftBack = function(part) {
return new Brian(this.settings).draftBack(part);
};
return new Brian(this.settings).draftBack(part)
}
// Attach own draft methods to prototype
Pattern.prototype.draftSleeve = draftSleeve;
Pattern.prototype.draftTopSleeve = draftTopSleeve;
Pattern.prototype.draftUnderSleeve = draftUnderSleeve;
Pattern.prototype.draftSleeve = draftSleeve
Pattern.prototype.draftTopSleeve = draftTopSleeve
Pattern.prototype.draftUnderSleeve = draftUnderSleeve
export default Pattern;
export default Pattern

View file

@ -1,52 +1,52 @@
export default function(part, s) {
let { macro, points, sa } = part.shorthand();
let { macro, points, sa } = part.shorthand()
macro("ld", {
from: points[s + "WristLeft"],
to: points[s + "WristRight"],
macro('ld', {
from: points[s + 'WristLeft'],
to: points[s + 'WristRight'],
d: 15
});
macro("ld", {
from: points[s + "ElbowLeft"],
})
macro('ld', {
from: points[s + 'ElbowLeft'],
to: points.elbowRight
});
macro("ld", {
from: points[s + "LeftEdge"],
to: points[s + "RightEdge"]
});
macro("hd", {
from: points[s + "LeftEdge"],
to: points[s + "ElbowLeft"],
y: points[s + "WristRight"].y + 3 * sa + 15
});
macro("hd", {
from: points[s + "LeftEdge"],
to: points[s + "WristLeft"],
y: points[s + "WristRight"].y + 3 * sa + 30
});
macro("hd", {
from: points[s + "LeftEdge"],
to: points[s + "WristRight"],
y: points[s + "WristRight"].y + 3 * sa + 45
});
macro("hd", {
from: points[s + "LeftEdge"],
})
macro('ld', {
from: points[s + 'LeftEdge'],
to: points[s + 'RightEdge']
})
macro('hd', {
from: points[s + 'LeftEdge'],
to: points[s + 'ElbowLeft'],
y: points[s + 'WristRight'].y + 3 * sa + 15
})
macro('hd', {
from: points[s + 'LeftEdge'],
to: points[s + 'WristLeft'],
y: points[s + 'WristRight'].y + 3 * sa + 30
})
macro('hd', {
from: points[s + 'LeftEdge'],
to: points[s + 'WristRight'],
y: points[s + 'WristRight'].y + 3 * sa + 45
})
macro('hd', {
from: points[s + 'LeftEdge'],
to: points.elbowRight,
y: points[s + "WristRight"].y + 3 * sa + 60
});
macro("vd", {
from: points[s + "ElbowLeft"],
to: points[s + "LeftEdge"],
x: points[s + "LeftEdge"].x - sa - 15
});
macro("vd", {
from: points[s + "WristLeft"],
to: points[s + "LeftEdge"],
x: points[s + "LeftEdge"].x - sa - 30
});
macro("vd", {
from: points[s + "WristRight"],
to: points[s + "LeftEdge"],
x: points[s + "LeftEdge"].x - sa - 45
});
y: points[s + 'WristRight'].y + 3 * sa + 60
})
macro('vd', {
from: points[s + 'ElbowLeft'],
to: points[s + 'LeftEdge'],
x: points[s + 'LeftEdge'].x - sa - 15
})
macro('vd', {
from: points[s + 'WristLeft'],
to: points[s + 'LeftEdge'],
x: points[s + 'LeftEdge'].x - sa - 30
})
macro('vd', {
from: points[s + 'WristRight'],
to: points[s + 'LeftEdge'],
x: points[s + 'LeftEdge'].x - sa - 45
})
}

View file

@ -1,59 +1,41 @@
export default function(part) {
let { Path, paths, points, store, options } = part.shorthand();
let { Path, paths, points, store, options } = part.shorthand()
function draftSleeve(part, tweak) {
let {
Point,
Path,
points,
paths,
store,
options,
measurements,
utils
} = part.shorthand();
let { Point, Path, points, paths, store, options, measurements, utils } = part.shorthand()
// Sleeve frame
points.top = new Point(0, 0);
points.boxTopRight = points.top.shift(
0,
(store.get("sleevecapTarget") / 5.8) * tweak
);
points.boxTopLeft = points.boxTopRight.flipX();
points.top = new Point(0, 0)
points.boxTopRight = points.top.shift(0, (store.get('sleevecapTarget') / 5.8) * tweak)
points.boxTopLeft = points.boxTopRight.flipX()
points.boxBottom = points.top.shift(
-90,
measurements.shoulderToWrist * (1 + options.sleeveLengthBonus)
);
points.boxBottomRight = points.boxBottom.shift(0, points.boxTopRight.x);
points.boxBottomLeft = points.boxBottomRight.flipX();
)
points.boxBottomRight = points.boxBottom.shift(0, points.boxTopRight.x)
points.boxBottomLeft = points.boxBottomRight.flipX()
points.armCenter = points.top.shift(
-90,
measurements.bicepsCircumference *
(1 + options.bicepsEase) *
options.sleevecapHeight *
tweak
);
points.armRight = points.armCenter.shift(0, points.boxTopRight.x);
points.armLeft = points.armRight.flipX();
points.elbowCenter = points.top.shift(-90, measurements.shoulderToElbow);
points.elbowRight = points.elbowCenter.shift(0, points.boxTopRight.x);
points.elbowLeft = points.elbowRight.flipX();
measurements.bicepsCircumference * (1 + options.bicepsEase) * options.sleevecapHeight * tweak
)
points.armRight = points.armCenter.shift(0, points.boxTopRight.x)
points.armLeft = points.armRight.flipX()
points.elbowCenter = points.top.shift(-90, measurements.shoulderToElbow)
points.elbowRight = points.elbowCenter.shift(0, points.boxTopRight.x)
points.elbowLeft = points.elbowRight.flipX()
// Using sleeve width to adapt other values
let factor = points.boxTopRight.x;
let factor = points.boxTopRight.x
// Note: us = undersleeve, ts = topsleeve
points.backPitchPoint = new Point(factor, points.armCenter.y / 3);
points.usTip = points.backPitchPoint.shift(180, factor / 4);
points.tsLeftEdge = points.armLeft.shift(180, factor / 4);
points.usLeftEdge = points.armLeft.shift(0, factor / 4);
points.tsRightEdge = points.armRight.shift(0, factor / 9);
points.usRightEdge = points.armRight.shift(180, factor / 9);
points.frontPitchPoint = new Point(
points.boxTopLeft.x,
points.armCenter.y * 0.6
);
points.tsElbowLeft = points.elbowLeft.shift(180, factor / 9);
points.usElbowLeft = points.elbowLeft.shift(0, factor / 2.4);
points.backPitchPoint = new Point(factor, points.armCenter.y / 3)
points.usTip = points.backPitchPoint.shift(180, factor / 4)
points.tsLeftEdge = points.armLeft.shift(180, factor / 4)
points.usLeftEdge = points.armLeft.shift(0, factor / 4)
points.tsRightEdge = points.armRight.shift(0, factor / 9)
points.usRightEdge = points.armRight.shift(180, factor / 9)
points.frontPitchPoint = new Point(points.boxTopLeft.x, points.armCenter.y * 0.6)
points.tsElbowLeft = points.elbowLeft.shift(180, factor / 9)
points.usElbowLeft = points.elbowLeft.shift(0, factor / 2.4)
// Different approach to sleeve bend, wrist right first
points.tsWristRight = utils.beamsIntersect(
@ -61,206 +43,130 @@ export default function(part) {
points.boxBottomRight.rotate(options.sleeveBend * -1, points.elbowRight),
points.boxBottomLeft,
points.boxBottomRight
);
points.usWristRight = points.tsWristRight.clone();
)
points.usWristRight = points.tsWristRight.clone()
// Shift wrist left to the exact wrist width
let wristWidth = measurements.wristCircumference * (1 + options.cuffEase);
let topWrist = wristWidth / 2 + factor / 5;
let underWrist = wristWidth / 2 - factor / 5;
points.tsWristLeftHelperBottom = points.tsWristRight.shift(
180,
topWrist / 2
);
points.usWristLeftHelperBottom = points.usWristRight.shift(
180,
underWrist / 2
);
points.tsWristLeftHelperTop = points.tsElbowLeft.shiftFractionTowards(
points.elbowRight,
0.5
);
points.usWristLeftHelperTop = points.usElbowLeft.shiftFractionTowards(
points.elbowRight,
0.5
);
let tsWristAngle = points.tsWristLeftHelperBottom.angle(
points.tsWristLeftHelperTop
);
let usWristAngle = points.usWristLeftHelperBottom.angle(
points.usWristLeftHelperTop
);
points.tsWristLeft = points.tsWristRight.shift(
tsWristAngle - 90,
topWrist * -1
);
points.usWristLeft = points.usWristRight.shift(
usWristAngle - 90,
underWrist * -1
);
let wristWidth = measurements.wristCircumference * (1 + options.cuffEase)
let topWrist = wristWidth / 2 + factor / 5
let underWrist = wristWidth / 2 - factor / 5
points.tsWristLeftHelperBottom = points.tsWristRight.shift(180, topWrist / 2)
points.usWristLeftHelperBottom = points.usWristRight.shift(180, underWrist / 2)
points.tsWristLeftHelperTop = points.tsElbowLeft.shiftFractionTowards(points.elbowRight, 0.5)
points.usWristLeftHelperTop = points.usElbowLeft.shiftFractionTowards(points.elbowRight, 0.5)
let tsWristAngle = points.tsWristLeftHelperBottom.angle(points.tsWristLeftHelperTop)
let usWristAngle = points.usWristLeftHelperBottom.angle(points.usWristLeftHelperTop)
points.tsWristLeft = points.tsWristRight.shift(tsWristAngle - 90, topWrist * -1)
points.usWristLeft = points.usWristRight.shift(usWristAngle - 90, underWrist * -1)
// Control points ts
points.tsRightEdgeCpTop = points.tsRightEdge.shift(
90,
points.backPitchPoint.dy(points.tsRightEdge) / 2
);
points.tsRightEdgeCpBottom = points.tsRightEdgeCpTop.flipY(
points.tsRightEdge
);
points.elbowRightCpTop = points.tsWristRight.shiftFractionTowards(
points.elbowRight,
1.15
);
points.topCpRight = points.top.shift(0, factor / 1.6);
points.topCpLeft = points.topCpRight.flipX();
)
points.tsRightEdgeCpBottom = points.tsRightEdgeCpTop.flipY(points.tsRightEdge)
points.elbowRightCpTop = points.tsWristRight.shiftFractionTowards(points.elbowRight, 1.15)
points.topCpRight = points.top.shift(0, factor / 1.6)
points.topCpLeft = points.topCpRight.flipX()
points.tsLeftEdgeCpRight = points.tsLeftEdge.shift(
0,
points.tsLeftEdge.dist(points.armLeft) / 2
);
)
points.frontPitchPointCpBottom = points.frontPitchPoint.shiftFractionTowards(
points.tsLeftEdgeCpRight,
0.666
);
points.frontPitchPointCpTop = points.frontPitchPointCpBottom.rotate(
180,
points.frontPitchPoint
);
points.tsElbowLeftCpTop = points.tsWristLeft.shiftFractionTowards(
points.tsElbowLeft,
1.2
);
)
points.frontPitchPointCpTop = points.frontPitchPointCpBottom.rotate(180, points.frontPitchPoint)
points.tsElbowLeftCpTop = points.tsWristLeft.shiftFractionTowards(points.tsElbowLeft, 1.2)
// Control points us
points.usRightEdgeCpBottom = points.usRightEdge.shift(
points.usTip.angle(points.elbowRight),
points.usTip.dy(points.usRightEdge) / 2
);
points.usRightEdgeCpTop = points.usRightEdgeCpBottom.rotate(
180,
points.usRightEdge
);
)
points.usRightEdgeCpTop = points.usRightEdgeCpBottom.rotate(180, points.usRightEdge)
points._helper1 = new Path()
.move(points.backPitchPoint)
._curve(points.topCpRight, points.top)
.shiftAlong(5);
.shiftAlong(5)
points._helper2 = new Path()
.move(points.backPitchPoint)
._curve(points.tsRightEdgeCpTop, points.tsRightEdge)
.shiftAlong(5);
.shiftAlong(5)
points.usLeftEdgeRight = points.usLeftEdge.shift(
0,
points.usLeftEdge.dist(points.armCenter) / 3
);
)
points.usLeftEdgeCpRight = points.usLeftEdge.shift(
0,
points.usLeftEdge.dist(points.armCenter) / 1.2
);
)
// Angle of the usTip
let angle =
points._helper1.angle(points.backPitchPoint) -
points.backPitchPoint.angle(points._helper2);
points.usTipCpBottom = points.usRightEdgeCpTop.rotate(
angle * -1,
points.usTip
);
points.usElbowLeftCpTop = points.usWristLeft.shiftFractionTowards(
points.usElbowLeft,
1.2
);
points._helper1.angle(points.backPitchPoint) - points.backPitchPoint.angle(points._helper2)
points.usTipCpBottom = points.usRightEdgeCpTop.rotate(angle * -1, points.usTip)
points.usElbowLeftCpTop = points.usWristLeft.shiftFractionTowards(points.usElbowLeft, 1.2)
// Calculate length of the sleevecap seam
let lenTop = new Path()
.move(points.backPitchPoint)
.curve(points.backPitchPoint, points.topCpRight, points.top)
.curve(
points.topCpLeft,
points.frontPitchPointCpTop,
points.frontPitchPoint
)
.curve(
points.frontPitchPointCpBottom,
points.tsLeftEdgeCpRight,
points.tsLeftEdge
)
.length();
.curve(points.topCpLeft, points.frontPitchPointCpTop, points.frontPitchPoint)
.curve(points.frontPitchPointCpBottom, points.tsLeftEdgeCpRight, points.tsLeftEdge)
.length()
let lenUnder = new Path()
.move(points.usTip)
.curve(
points.usTipCpBottom,
points.usLeftEdgeCpRight,
points.usLeftEdgeRight
)
.curve(points.usTipCpBottom, points.usLeftEdgeCpRight, points.usLeftEdgeRight)
.line(points.usLeftEdge)
.length();
store.set("sleevecapLength", lenTop + lenUnder);
.length()
store.set('sleevecapLength', lenTop + lenUnder)
}
let armholeLength =
store.get("frontArmholeLength") + store.get("backArmholeLength");
let sleevecapEase = armholeLength * options.sleevecapEase;
store.set("sleevecapEase", sleevecapEase);
store.set("sleevecapTarget", armholeLength + sleevecapEase);
let armholeLength = store.get('frontArmholeLength') + store.get('backArmholeLength')
let sleevecapEase = armholeLength * options.sleevecapEase
store.set('sleevecapEase', sleevecapEase)
store.set('sleevecapTarget', armholeLength + sleevecapEase)
let delta = 0;
let runs = 0;
let tweak = 1;
let target = store.get("sleevecapTarget");
let delta = 0
let runs = 0
let tweak = 1
let target = store.get('sleevecapTarget')
do {
draftSleeve(part, tweak);
runs++;
delta = store.get("sleevecapLength") - target;
if (delta > 0) tweak = tweak * 0.99;
else tweak = tweak * 1.02;
} while (Math.abs(delta) > 2 && runs < 25);
draftSleeve(part, tweak)
runs++
delta = store.get('sleevecapLength') - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 2 && runs < 25)
// Paths
paths.ts = new Path()
.move(points.tsWristRight)
.line(points.elbowRight)
.curve(
points.elbowRightCpTop,
points.tsRightEdgeCpBottom,
points.tsRightEdge
)
.curve(points.elbowRightCpTop, points.tsRightEdgeCpBottom, points.tsRightEdge)
.curve_(points.tsRightEdgeCpTop, points.backPitchPoint)
.curve(points.backPitchPoint, points.topCpRight, points.top)
.curve(
points.topCpLeft,
points.frontPitchPointCpTop,
points.frontPitchPoint
)
.curve(
points.frontPitchPointCpBottom,
points.tsLeftEdgeCpRight,
points.tsLeftEdge
)
.curve(points.topCpLeft, points.frontPitchPointCpTop, points.frontPitchPoint)
.curve(points.frontPitchPointCpBottom, points.tsLeftEdgeCpRight, points.tsLeftEdge)
.curve(points.tsLeftEdge, points.tsElbowLeftCpTop, points.tsElbowLeft)
.line(points.tsWristLeft)
.line(points.tsWristRight)
.close()
.attr("class", "lining");
.attr('class', 'lining')
paths.us = new Path()
.move(points.usWristRight)
.line(points.elbowRight)
.curve(
points.elbowRightCpTop,
points.usRightEdgeCpBottom,
points.usRightEdge
)
.curve(points.elbowRightCpTop, points.usRightEdgeCpBottom, points.usRightEdge)
.curve_(points.usRightEdgeCpTop, points.usTip)
.curve(
points.usTipCpBottom,
points.usLeftEdgeCpRight,
points.usLeftEdgeRight
)
.curve(points.usTipCpBottom, points.usLeftEdgeCpRight, points.usLeftEdgeRight)
.line(points.usLeftEdge)
.curve(points.usLeftEdge, points.usElbowLeftCpTop, points.usElbowLeft)
.line(points.usWristLeft)
.line(points.usWristRight)
.close()
.attr("class", "stroke-xl interfacing");
.attr('class', 'stroke-xl interfacing')
return part;
return part
}

View file

@ -1,36 +1,26 @@
import dimensions from "./shared";
import dimensions from './shared'
export default function(part) {
let {
macro,
Path,
points,
paths,
complete,
paperless,
snippets,
Snippet,
sa
} = part.shorthand();
let { macro, Path, points, paths, complete, paperless, snippets, Snippet, sa } = part.shorthand()
// Extract seamline from sleeve
delete paths.us;
paths.seam = paths.ts.clone().attr("class", "fabric", true);
delete paths.ts;
delete paths.us
paths.seam = paths.ts.clone().attr('class', 'fabric', true)
delete paths.ts
// Complete?
if (complete) {
snippets.logo = new Snippet("logo", points.elbowCenter);
macro("title", {
snippets.logo = new Snippet('logo', points.elbowCenter)
macro('title', {
at: points.armCenter,
nr: 3,
title: "topsleeve"
});
title: 'topsleeve'
})
if (sa) {
paths.sa = paths.seam.clone();
paths.sa = paths.seam.clone()
// Remove hem
paths.sa.ops.splice(-2);
paths.sa.ops.splice(-2)
paths.sa = paths.sa
.offset(sa)
.join(
@ -40,39 +30,39 @@ export default function(part) {
.offset(sa * 3)
)
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
}
// Paperless?
if (paperless) {
dimensions(part, "ts");
macro("vd", {
dimensions(part, 'ts')
macro('vd', {
from: points.tsLeftEdge,
to: points.top,
x: points.tsLeftEdge.x - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.top,
y: points.top.x - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.backPitchPoint,
y: points.top.x - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.tsRightEdge,
y: points.top.x - sa - 45
});
macro("vd", {
})
macro('vd', {
from: points.tsRightEdge,
to: points.backPitchPoint,
x: points.tsRightEdge.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,36 +1,26 @@
import dimensions from "./shared";
import dimensions from './shared'
export default function(part) {
let {
macro,
Path,
points,
paths,
complete,
paperless,
snippets,
Snippet,
sa
} = part.shorthand();
let { macro, Path, points, paths, complete, paperless, snippets, Snippet, sa } = part.shorthand()
// Extract seamline from sleeve
delete paths.ts;
paths.seam = paths.us.clone().attr("class", "fabric", true);
delete paths.us;
delete paths.ts
paths.seam = paths.us.clone().attr('class', 'fabric', true)
delete paths.us
// Complete?
if (complete) {
snippets.logo = new Snippet("logo", points.elbowCenter);
macro("title", {
snippets.logo = new Snippet('logo', points.elbowCenter)
macro('title', {
at: points.armCenter,
nr: 4,
title: "undersleeve"
});
title: 'undersleeve'
})
if (sa) {
paths.sa = paths.seam.clone();
paths.sa = paths.seam.clone()
// Remove hem
paths.sa.ops.splice(-2);
paths.sa.ops.splice(-2)
paths.sa = paths.sa
.offset(sa)
.join(
@ -40,24 +30,24 @@ export default function(part) {
.offset(sa * 3)
)
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
}
// Paperless?
if (paperless) {
dimensions(part, "us");
macro("hd", {
dimensions(part, 'us')
macro('hd', {
from: points.usLeftEdge,
to: points.usTip,
y: points.usTip.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.tsRightEdge,
to: points.usTip,
x: points.tsRightEdge.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,4 +1,4 @@
import * as shared from "./shared";
import * as shared from './shared'
export default part => {
let {
@ -12,67 +12,64 @@ export default part => {
complete,
paperless,
macro
} = part.shorthand();
} = part.shorthand()
// Seamline
paths.saBase = shared.saBase("back", points, Path);
paths.saBase = shared.saBase('back', points, Path)
paths.seam = new Path()
.move(points.cbNeck)
.line(points.cbHips)
.join(paths.saBase)
.attr("class", "fabric");
.attr('class', 'fabric')
// Store lengths to fit sleeve
store.set("backArmholeLength", shared.armholeLength(points, Path));
store.set(
"backShoulderToArmholePitch",
shared.shoulderToArmholePitch(points, Path)
);
store.set('backArmholeLength', shared.armholeLength(points, Path))
store.set('backShoulderToArmholePitch', shared.shoulderToArmholePitch(points, Path))
// Complete pattern?
if (complete) {
macro("cutonfold", {
macro('cutonfold', {
from: points.cbNeck,
to: points.cbHips,
grainline: true
});
})
macro("title", { at: points.title, nr: 2, title: "back" });
snippets.armholePitchNotch = new Snippet("bnotch", points.armholePitch);
macro('title', { at: points.title, nr: 2, title: 'back' })
snippets.armholePitchNotch = new Snippet('bnotch', points.armholePitch)
if (sa) {
paths.sa = paths.saBase
.offset(sa)
.attr("class", "fabric sa")
.attr('class', 'fabric sa')
.line(points.cbNeck)
.move(points.cbHips);
paths.sa.line(paths.sa.start());
.move(points.cbHips)
paths.sa.line(paths.sa.start())
}
}
// Paperless?
if (paperless) {
shared.dimensions(macro, points, Path, sa);
macro("hd", {
shared.dimensions(macro, points, Path, sa)
macro('hd', {
from: points.cbHips,
to: points.hips,
y: points.hips.y + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.cbHips,
to: points.cbNeck,
x: points.cbHips.x - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.neck,
y: points.neck.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.shoulder,
y: points.neck.y - sa - 30
});
})
}
return part;
};
return part
}

View file

@ -1,4 +1,4 @@
import * as shared from "./shared";
import * as shared from './shared'
export default part => {
let {
@ -15,179 +15,146 @@ export default part => {
paths,
utils,
complete
} = part.shorthand();
} = part.shorthand()
store.set(
"shoulderEase",
(measurements.shoulderToShoulder * options.shoulderEase) / 2
);
store.set('shoulderEase', (measurements.shoulderToShoulder * options.shoulderEase) / 2)
// Center back (cb) vertical axis
points.cbNeck = new Point(
0,
options.backNeckCutout * measurements.neckCircumference
);
points.cbNeck = new Point(0, options.backNeckCutout * measurements.neckCircumference)
points.cbShoulder = new Point(
0,
(measurements.shoulderSlope -
measurements.shoulderToShoulder * options.shoulderSlopeReduction) /
2
);
)
points.cbArmhole = new Point(
0,
points.cbShoulder.y +
(measurements.shoulderToShoulder * options.shoulderSlopeReduction) / 2 +
measurements.bicepsCircumference *
(1 + options.bicepsEase) *
options.armholeDepthFactor
);
points.cbWaist = new Point(
0,
points.cbNeck.y + measurements.centerBackNeckToWaist
);
points.cbHips = new Point(
0,
points.cbWaist.y + measurements.naturalWaistToHip
);
measurements.bicepsCircumference * (1 + options.bicepsEase) * options.armholeDepthFactor
)
points.cbWaist = new Point(0, points.cbNeck.y + measurements.centerBackNeckToWaist)
points.cbHips = new Point(0, points.cbWaist.y + measurements.naturalWaistToHip)
points.cbHem = new Point(
0,
points.cbWaist.y +
measurements.naturalWaistToHip +
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) *
options.lengthBonus
);
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) * options.lengthBonus
)
// Side back (cb) vertical axis
points.armhole = new Point(
(measurements.chestCircumference * (1 + options.chestEase)) / 4,
points.cbArmhole.y
);
points.waist = new Point(points.armhole.x, points.cbWaist.y);
points.hips = new Point(points.armhole.x, points.cbHips.y);
points.hem = new Point(points.armhole.x, points.cbHem.y);
)
points.waist = new Point(points.armhole.x, points.cbWaist.y)
points.hips = new Point(points.armhole.x, points.cbHips.y)
points.hem = new Point(points.armhole.x, points.cbHem.y)
// Shoulder line
points.neck = new Point(
(measurements.neckCircumference * (1 + options.collarEase)) /
options.collarFactor,
(measurements.neckCircumference * (1 + options.collarEase)) / options.collarFactor,
0
);
)
points.shoulder = new Point(
measurements.shoulderToShoulder / 2 + store.get("shoulderEase"),
measurements.shoulderToShoulder / 2 + store.get('shoulderEase'),
points.cbShoulder.y
);
)
// Armhhole
points.armholePitch = new Point(
(measurements.shoulderToShoulder * options.acrossBackFactor) / 2 +
store.get("shoulderEase") / 2,
store.get('shoulderEase') / 2,
points.shoulder.y + points.shoulder.dy(points.armhole) / 2
);
points._tmp1 = new Point(points.armholePitch.x, points.armhole.y);
points._tmp2 = points._tmp1.shift(45, 10);
)
points._tmp1 = new Point(points.armholePitch.x, points.armhole.y)
points._tmp2 = points._tmp1.shift(45, 10)
points._tmp3 = utils.beamsIntersect(
points._tmp1,
points._tmp2,
points.armhole,
points.armholePitch
);
points.armholeHollow = points._tmp1.shiftFractionTowards(points._tmp3, 0.5);
points.armholeCp2 = points.armhole.shift(
180,
points._tmp1.dx(points.armhole) / 4
);
)
points.armholeHollow = points._tmp1.shiftFractionTowards(points._tmp3, 0.5)
points.armholeCp2 = points.armhole.shift(180, points._tmp1.dx(points.armhole) / 4)
points.armholeHollowCp1 = points.armholeHollow.shift(
-45,
points.armholeHollow.dy(points.armhole) / 2
);
)
points.armholeHollowCp2 = points.armholeHollow.shift(
135,
points.armholePitch.dx(points.armholeHollow)
);
)
points.armholePitchCp1 = points.armholePitch.shift(
-90,
points.armholePitch.dy(points.armholeHollow) / 2
);
)
points.armholePitchCp2 = points.armholePitch.shift(
90,
points.shoulder.dy(points.armholePitch) / 2
);
)
points.shoulderCp1 = points.shoulder
.shiftTowards(points.neck, points.shoulder.dy(points.armholePitch) / 5)
.rotate(90, points.shoulder);
.rotate(90, points.shoulder)
// Neck opening (back)
points._tmp4 = points.neck
.shiftTowards(points.shoulder, 10)
.rotate(-90, points.neck);
points.neckCp2 = utils.beamIntersectsY(
points.neck,
points._tmp4,
points.cbNeck.y
);
points._tmp4 = points.neck.shiftTowards(points.shoulder, 10).rotate(-90, points.neck)
points.neckCp2 = utils.beamIntersectsY(points.neck, points._tmp4, points.cbNeck.y)
// Fit collar
points.cfNeck = points.neck.rotate(-90, new Point(0, 0));
let target = measurements.neckCircumference * (1 + options.collarEase);
let delta = 0;
let run = 0;
points.cfNeck = points.neck.rotate(-90, new Point(0, 0))
let target = measurements.neckCircumference * (1 + options.collarEase)
let delta = 0
let run = 0
do {
run++;
points.cfNeck = points.cfNeck.shift(90, delta / 3);
run++
points.cfNeck = points.cfNeck.shift(90, delta / 3)
points.frontNeckCpEdge = utils.beamsIntersect(
points.neck,
points.neckCp2,
points.cfNeck,
new Point(20, points.cfNeck.y)
);
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(
points.frontNeckCpEdge,
0.55
);
points.neckCp2Front = points.neck.shiftFractionTowards(
points.frontNeckCpEdge,
0.65
);
)
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(points.frontNeckCpEdge, 0.55)
points.neckCp2Front = points.neck.shiftFractionTowards(points.frontNeckCpEdge, 0.65)
paths.neckOpening = new Path()
.move(points.cfNeck)
.curve(points.cfNeckCp1, points.neckCp2Front, points.neck)
.curve(points.neckCp2, points.cbNeck, points.cbNeck)
.attr("class", "dashed stroke-xl various");
delta = paths.neckOpening.length() * 2 - target;
} while (Math.abs(delta) > 1 && options.brianFitCollar && run < 10);
delete paths.neckOpening;
.attr('class', 'dashed stroke-xl various')
delta = paths.neckOpening.length() * 2 - target
} while (Math.abs(delta) > 1 && options.brianFitCollar && run < 10)
delete paths.neckOpening
if (options.brianFitCollar) {
debug({
style: "success",
label: "🏁 Collar fitted",
msg: `Target was ${units(target)}, delta of ${units(
delta
)} reached in ${run} attempts.`
});
style: 'success',
label: '🏁 Collar fitted',
msg: `Target was ${units(target)}, delta of ${units(delta)} reached in ${run} attempts.`
})
} else
debug({
style: "warning",
label: "🚫 Not fittingcollar",
msg: "(in Brian)"
});
style: 'warning',
label: '🚫 Not fittingcollar',
msg: '(in Brian)'
})
// Anchor point for sampling
points.gridAnchor = points.cbHem;
points.gridAnchor = points.cbHem
// Seamline
paths.saBase = shared.saBase("back", points, Path);
paths.saBase = shared.saBase('back', points, Path)
paths.seam = new Path()
.move(points.cbNeck)
.line(points.cbHem)
.join(paths.saBase)
.attr("class", "fabric");
.attr('class', 'fabric')
// Complete pattern?
if (complete) {
points.title = new Point(points.armholePitch.x / 2, points.armholePitch.y);
points.logo = points.title.shift(-90, 100);
snippets.logo = new Snippet("logo", points.logo);
points.title = new Point(points.armholePitch.x / 2, points.armholePitch.y)
points.logo = points.title.shift(-90, 100)
snippets.logo = new Snippet('logo', points.logo)
}
return part;
};
return part
}

View file

@ -1,4 +1,4 @@
import * as shared from "./shared";
import * as shared from './shared'
export default part => {
let {
@ -15,80 +15,77 @@ export default part => {
complete,
paperless,
macro
} = part.shorthand();
} = part.shorthand()
// Cut arm a bit deeper at the front
let deeper = measurements.chestCircumference * options.frontArmholeDeeper;
points.armholePitchCp1.x -= deeper;
points.armholePitch.x -= deeper;
points.armholePitchCp2.x -= deeper;
let deeper = measurements.chestCircumference * options.frontArmholeDeeper
points.armholePitchCp1.x -= deeper
points.armholePitch.x -= deeper
points.armholePitchCp2.x -= deeper
// Rename cb (center back) to cf (center front)
for (let key of ["Shoulder", "Armhole", "Waist", "Hips", "Hem"]) {
points[`cf${key}`] = new Point(points[`cb${key}`].x, points[`cb${key}`].y);
delete points[`cb${key}`];
for (let key of ['Shoulder', 'Armhole', 'Waist', 'Hips', 'Hem']) {
points[`cf${key}`] = new Point(points[`cb${key}`].x, points[`cb${key}`].y)
delete points[`cb${key}`]
}
// Front neckline points
points.neckCp2 = new Point(points.neckCp2Front.x, points.neckCp2Front.y);
points.neckCp2 = new Point(points.neckCp2Front.x, points.neckCp2Front.y)
// Seamline
paths.saBase = shared.saBase("front", points, Path);
paths.saBase = shared.saBase('front', points, Path)
paths.seam = new Path()
.move(points.cfNeck)
.line(points.cfHem)
.join(paths.saBase)
.attr("class", "fabric");
.attr('class', 'fabric')
// Store lengths to fit sleeve
store.set("frontArmholeLength", shared.armholeLength(points, Path));
store.set(
"frontShoulderToArmholePitch",
shared.shoulderToArmholePitch(points, Path)
);
store.set('frontArmholeLength', shared.armholeLength(points, Path))
store.set('frontShoulderToArmholePitch', shared.shoulderToArmholePitch(points, Path))
// Complete pattern?
if (complete) {
macro("cutonfold", {
macro('cutonfold', {
from: points.cfNeck,
to: points.cfHips,
grainline: true
});
macro("title", { at: points.title, nr: 1, title: "front" });
snippets.armholePitchNotch = new Snippet("notch", points.armholePitch);
})
macro('title', { at: points.title, nr: 1, title: 'front' })
snippets.armholePitchNotch = new Snippet('notch', points.armholePitch)
if (sa) {
paths.sa = paths.saBase
.offset(sa)
.attr("class", "fabric sa")
.attr('class', 'fabric sa')
.line(points.cfNeck)
.move(points.cfHips);
paths.sa.line(paths.sa.start());
.move(points.cfHips)
paths.sa.line(paths.sa.start())
}
}
// Paperless?
if (paperless) {
shared.dimensions(macro, points, Path, sa);
macro("hd", {
shared.dimensions(macro, points, Path, sa)
macro('hd', {
from: points.cfHips,
to: points.hips,
y: points.hips.y + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.cfHips,
to: points.cfNeck,
x: points.cfHips.x - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.cfNeck,
to: points.neck,
y: points.neck.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.cfNeck,
to: points.shoulder,
y: points.neck.y - sa - 30
});
})
}
return part;
};
return part
}

View file

@ -1,21 +1,21 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import config from '../config'
// Parts
import draftBase from "./base";
import draftBack from "./back";
import draftFront from "./front";
import draftSleevecap from "./sleevecap";
import draftSleeve from "./sleeve";
import draftBase from './base'
import draftBack from './back'
import draftFront from './front'
import draftSleevecap from './sleevecap'
import draftSleeve from './sleeve'
// Create design
const Pattern = new freesewing.Design(config, plugins);
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
Pattern.prototype.draftBase = draftBase;
Pattern.prototype.draftBack = draftBack;
Pattern.prototype.draftFront = draftFront;
Pattern.prototype.draftSleevecap = draftSleevecap;
Pattern.prototype.draftSleeve = draftSleeve;
Pattern.prototype.draftBase = draftBase
Pattern.prototype.draftBack = draftBack
Pattern.prototype.draftFront = draftFront
Pattern.prototype.draftSleevecap = draftSleevecap
Pattern.prototype.draftSleeve = draftSleeve
export default Pattern;
export default Pattern

View file

@ -1,21 +1,21 @@
export function saBase(side, points, Path) {
let path = new Path();
if (side === "back") path.move(points.cbHem);
else path.move(points.cfHem);
let path = new Path()
if (side === 'back') path.move(points.cbHem)
else path.move(points.cfHem)
path
.line(points.hem)
.line(points.armhole)
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
.line(points.neck);
if (side === "back") {
path.curve(points.neckCp2, points.cbNeck, points.cbNeck);
.line(points.neck)
if (side === 'back') {
path.curve(points.neckCp2, points.cbNeck, points.cbNeck)
} else {
path.curve(points.neckCp2, points.cfNeckCp1, points.cfNeck);
path.curve(points.neckCp2, points.cfNeckCp1, points.cfNeck)
}
return path;
return path
}
export function armholeLength(points, Path) {
@ -24,54 +24,50 @@ export function armholeLength(points, Path) {
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
.length();
.length()
}
export function shoulderToArmholePitch(points, Path) {
return new Path()
.move(points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
.length();
.length()
}
export function dimensions(macro, points, Path, sa) {
macro("pd", {
macro('pd', {
path: new Path()
.move(points.armhole)
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.curve(
points.armholeHollowCp2,
points.armholePitchCp1,
points.armholePitch
)
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
d: sa + 15
});
macro("pd", {
})
macro('pd', {
path: new Path()
.move(points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
d: -15
});
macro("vd", {
})
macro('vd', {
from: points.hips,
to: points.armhole,
x: points.hips.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.hips,
to: points.armholePitch,
x: points.hips.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.hips,
to: points.shoulder,
x: points.hips.x + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.hips,
to: points.neck,
x: points.hips.x + sa + 60
});
macro("ld", { from: points.neck, to: points.shoulder, d: sa + 15 });
})
macro('ld', { from: points.neck, to: points.shoulder, d: sa + 15 })
}

View file

@ -15,33 +15,33 @@ export default part => {
complete,
paperless,
macro
} = part.shorthand();
} = part.shorthand()
// Wrist
let top = paths.sleevecap.bbox().topLeft.y;
let top = paths.sleevecap.bbox().topLeft.y
debug({
style: "info",
label: "🗸 Sleevecap height",
style: 'info',
label: '🗸 Sleevecap height',
msg: units(Math.abs(top))
});
})
debug({
style: "info",
label: "🗸 Sleevecap width",
style: 'info',
label: '🗸 Sleevecap width',
msg: units(points.bicepsRight.x * 2)
});
})
points.centerWrist = new Point(
0,
top + measurements.shoulderToWrist * (1 + options.sleeveLengthBonus)
);
)
points.wristRight = points.centerWrist.shift(
0,
(measurements.wristCircumference * (1 + options.cuffEase)) / 2
);
points.wristLeft = points.wristRight.rotate(180, points.centerWrist);
points.sleeveTip = paths.sleevecap.shiftFractionAlong(0.5);
)
points.wristLeft = points.wristRight.rotate(180, points.centerWrist)
points.sleeveTip = paths.sleevecap.shiftFractionAlong(0.5)
// Paths
paths.sleevecap.render = false;
paths.sleevecap.render = false
paths.seam = new Path()
.move(points.bicepsLeft)
.move(points.wristLeft)
@ -49,67 +49,64 @@ export default part => {
.line(points.bicepsRight)
.join(paths.sleevecap)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Anchor point for sampling
points.gridAnchor = new Point(0, 0);
points.gridAnchor = new Point(0, 0)
// Complete pattern?
if (complete) {
points.logo = points.centerBiceps.shiftFractionTowards(
points.centerWrist,
0.3
);
snippets.logo = new Snippet("logo", points.logo);
macro("title", { at: points.centerBiceps, nr: 3, title: "sleeve" });
macro("grainline", { from: points.centerWrist, to: points.centerBiceps });
points.logo = points.centerBiceps.shiftFractionTowards(points.centerWrist, 0.3)
snippets.logo = new Snippet('logo', points.logo)
macro('title', { at: points.centerBiceps, nr: 3, title: 'sleeve' })
macro('grainline', { from: points.centerWrist, to: points.centerBiceps })
points.scaleboxAnchor = points.scalebox = points.centerBiceps.shiftFractionTowards(
points.centerWrist,
0.5
);
macro("scalebox", { at: points.scalebox });
)
macro('scalebox', { at: points.scalebox })
points.frontNotch = paths.sleevecap.shiftAlong(
paths.sleevecap.length() / 2 -
store.get("frontShoulderToArmholePitch") -
store.get("sleevecapEase") / 2
);
store.get('frontShoulderToArmholePitch') -
store.get('sleevecapEase') / 2
)
points.backNotch = paths.sleevecap.shiftAlong(
paths.sleevecap.length() / 2 +
store.get("backShoulderToArmholePitch") +
store.get("sleevecapEase") / 2
);
snippets.frontNotch = new Snippet("notch", points.frontNotch);
snippets.backNotch = new Snippet("bnotch", points.backNotch);
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
store.get('backShoulderToArmholePitch') +
store.get('sleevecapEase') / 2
)
snippets.frontNotch = new Snippet('notch', points.frontNotch)
snippets.backNotch = new Snippet('bnotch', points.backNotch)
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("vd", {
macro('vd', {
from: points.wristLeft,
to: points.bicepsLeft,
x: points.bicepsLeft.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.wristLeft,
to: points.sleeveTip,
x: points.bicepsLeft.x - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.bicepsLeft,
to: points.bicepsRight,
y: points.sleeveTip.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.wristLeft,
to: points.wristRight,
y: points.wristLeft.y + sa + 30
});
macro("pd", {
})
macro('pd', {
path: paths.sleevecap.reverse(),
d: -1 * sa - 15
});
})
}
return part;
};
return part
}

View file

@ -2,139 +2,116 @@
* Positive values mean sleevecap is longer than armhole
*/
function sleevecapDelta(store) {
return store.get("sleevecapLength") - store.get("sleevecapTarget");
return store.get('sleevecapLength') - store.get('sleevecapTarget')
}
function sleevecapAdjust(store) {
let delta = sleevecapDelta(store);
let factor = store.get("sleeveFactor");
if (delta > 0) factor = factor * 0.98;
else factor = factor * 1.02;
store.set("sleeveFactor", factor);
let delta = sleevecapDelta(store)
let factor = store.get('sleeveFactor')
if (delta > 0) factor = factor * 0.98
else factor = factor * 1.02
store.set('sleeveFactor', factor)
}
function draftSleevecap(part, run) {
let {
debug,
units,
store,
measurements,
options,
Point,
points,
Path,
paths
} = part.shorthand();
let { debug, units, store, measurements, options, Point, points, Path, paths } = part.shorthand()
// Sleeve center axis
points.centerBiceps = new Point(0, 0);
points.centerBiceps = new Point(0, 0)
points.centerCap = points.centerBiceps.shift(
90,
options.sleevecapTopFactorY *
(measurements.bicepsCircumference *
(1 + options.bicepsEase) *
options.armholeDepthFactor *
store.get("sleeveFactor"))
);
store.get('sleeveFactor'))
)
// Left and right biceps points, limit impact of sleeveFactor to 25%
let halfWidth =
(measurements.bicepsCircumference * (1 + options.bicepsEase)) / 2;
let halfWidth = (measurements.bicepsCircumference * (1 + options.bicepsEase)) / 2
points.bicepsLeft = points.centerBiceps.shift(
180,
halfWidth * options.sleeveWidthGuarantee +
halfWidth * (1 - options.sleeveWidthGuarantee) * store.get("sleeveFactor")
);
points.bicepsRight = points.bicepsLeft.flipX(points.centerBiceps);
halfWidth * (1 - options.sleeveWidthGuarantee) * store.get('sleeveFactor')
)
points.bicepsRight = points.bicepsLeft.flipX(points.centerBiceps)
// Adapt sleeve center axis
points.capLeft = new Point(points.bicepsLeft.x, points.centerCap.y);
points.capRight = points.capLeft.flipX();
points.capLeft = new Point(points.bicepsLeft.x, points.centerCap.y)
points.capRight = points.capLeft.flipX()
points.centerCap = points.capLeft.shiftFractionTowards(
points.capRight,
options.sleevecapTopFactorX
);
)
// Pitch points
let width = points.bicepsRight.x;
let height = points.centerCap.y;
let width = points.bicepsRight.x
let height = points.centerCap.y
points.backPitch = new Point(
-1 * width * options.sleevecapBackFactorX,
height * options.sleevecapBackFactorY
);
)
points.frontPitch = new Point(
width * options.sleevecapFrontFactorX,
height * options.sleevecapFrontFactorY
);
)
// 4 sleevecap quadrants
// Base points
points.capQ1Base = points.frontPitch.shiftFractionTowards(
points.bicepsRight,
0.5
);
points.capQ2Base = points.frontPitch.shiftFractionTowards(
points.centerCap,
0.5
);
points.capQ3Base = points.backPitch.shiftFractionTowards(
points.centerCap,
0.5
);
points.capQ4Base = points.backPitch.shiftFractionTowards(
points.bicepsLeft,
0.5
);
points.capQ1Base = points.frontPitch.shiftFractionTowards(points.bicepsRight, 0.5)
points.capQ2Base = points.frontPitch.shiftFractionTowards(points.centerCap, 0.5)
points.capQ3Base = points.backPitch.shiftFractionTowards(points.centerCap, 0.5)
points.capQ4Base = points.backPitch.shiftFractionTowards(points.bicepsLeft, 0.5)
// Offset points
let baseOffset = measurements.bicepsCircumference * (1 + options.bicepsEase);
let baseOffset = measurements.bicepsCircumference * (1 + options.bicepsEase)
points.capQ1 = points.capQ1Base.shift(
points.bicepsRight.angle(points.frontPitch) + 90,
baseOffset * options.sleevecapQ1Offset
);
)
points.capQ2 = points.capQ2Base.shift(
points.centerCap.angle(points.frontPitch) + 90,
baseOffset * options.sleevecapQ2Offset
);
)
points.capQ3 = points.capQ3Base.shift(
points.centerCap.angle(points.backPitch) - 90,
baseOffset * options.sleevecapQ3Offset
);
)
points.capQ4 = points.capQ4Base.shift(
points.bicepsLeft.angle(points.backPitch) - 90,
baseOffset * options.sleevecapQ4Offset
);
)
// Control points
points.capQ1Cp1 = points.capQ1.shift(
points.frontPitch.angle(points.bicepsRight),
baseOffset * options.sleevecapQ1Spread1
);
)
points.capQ1Cp2 = points.capQ1.shift(
points.frontPitch.angle(points.bicepsRight),
baseOffset * options.sleevecapQ1Spread2 * -1
);
)
points.capQ2Cp1 = points.capQ2.shift(
points.centerCap.angle(points.frontPitch),
baseOffset * options.sleevecapQ2Spread1
);
)
points.capQ2Cp2 = points.capQ2.shift(
points.centerCap.angle(points.frontPitch),
baseOffset * options.sleevecapQ2Spread2 * -1
);
)
points.capQ3Cp1 = points.capQ3.shift(
points.backPitch.angle(points.centerCap),
baseOffset * options.sleevecapQ3Spread1
);
)
points.capQ3Cp2 = points.capQ3.shift(
points.backPitch.angle(points.centerCap),
baseOffset * options.sleevecapQ3Spread2 * -1
);
)
points.capQ4Cp1 = points.capQ4.shift(
points.bicepsLeft.angle(points.backPitch),
baseOffset * options.sleevecapQ4Spread1
);
)
points.capQ4Cp2 = points.capQ4.shift(
points.bicepsLeft.angle(points.backPitch),
baseOffset * options.sleevecapQ4Spread2 * -1
);
)
// Sleevecap seamline
paths.sleevecap = new Path()
@ -143,21 +120,20 @@ function draftSleevecap(part, run) {
.curve(points.capQ1Cp2, points.capQ2Cp1, points.capQ2)
.curve(points.capQ2Cp2, points.capQ3Cp1, points.capQ3)
.curve(points.capQ3Cp2, points.capQ4Cp1, points.capQ4)
.curve(points.capQ4Cp2, points.bicepsLeft, points.bicepsLeft);
.curve(points.capQ4Cp2, points.bicepsLeft, points.bicepsLeft)
// Store sleevecap length
store.set("sleevecapLength", paths.sleevecap.length());
store.set('sleevecapLength', paths.sleevecap.length())
if (run === 0) {
let armholeLength =
store.get("frontArmholeLength") + store.get("backArmholeLength");
let sleevecapEase = armholeLength * options.sleevecapEase;
store.set("sleevecapEase", sleevecapEase);
store.set("sleevecapTarget", armholeLength + sleevecapEase);
let armholeLength = store.get('frontArmholeLength') + store.get('backArmholeLength')
let sleevecapEase = armholeLength * options.sleevecapEase
store.set('sleevecapEase', sleevecapEase)
store.set('sleevecapTarget', armholeLength + sleevecapEase)
debug({
style: "info",
label: "🗸 Sleevecap ease",
style: 'info',
label: '🗸 Sleevecap ease',
msg: units(sleevecapEase)
});
})
// Uncomment this line to see all sleevecap iterations
//paths[run] = paths.sleevecap;
@ -165,41 +141,37 @@ function draftSleevecap(part, run) {
}
export default part => {
let { debug, store, units, options, Point, points, paths } = part.shorthand();
let { debug, store, units, options, Point, points, paths } = part.shorthand()
store.set("sleeveFactor", 1);
let run = 0;
let delta = 0;
store.set('sleeveFactor', 1)
let run = 0
let delta = 0
do {
draftSleevecap(part, run);
delta = sleevecapDelta(store);
sleevecapAdjust(store);
run++;
} while (
options.brianFitSleeve === true &&
run < 30 &&
Math.abs(sleevecapDelta(store)) > 2
);
draftSleevecap(part, run)
delta = sleevecapDelta(store)
sleevecapAdjust(store)
run++
} while (options.brianFitSleeve === true && run < 30 && Math.abs(sleevecapDelta(store)) > 2)
if (options.brianFitSleeve) {
debug({
style: "success",
label: "🏁 Sleevecap fitted",
msg: `Target was ${units(store.get("sleevecapTarget"))}, delta of ${units(
style: 'success',
label: '🏁 Sleevecap fitted',
msg: `Target was ${units(store.get('sleevecapTarget'))}, delta of ${units(
delta
)} reached in ${run} attempts.`
});
})
} else
debug({
style: "warning",
label: "🚫 Not fittingsleevecap",
msg: "(in Brian)"
});
style: 'warning',
label: '🚫 Not fittingsleevecap',
msg: '(in Brian)'
})
// Paths
paths.sleevecap.attr("class", "fabric");
paths.sleevecap.attr('class', 'fabric')
// Anchor point for sampling
points.gridAnchor = new Point(0, 0);
points.gridAnchor = new Point(0, 0)
return part;
};
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,4 +1,4 @@
import init from "./init";
import init from './init'
export default function(part) {
let {
@ -14,55 +14,49 @@ export default function(part) {
paperless,
macro,
utils
} = part.shorthand();
} = part.shorthand()
// Initialize
init(part);
init(part)
// Center back
points.zero = new Point(0, 0);
points.center = points.zero.shift(90, store.get("rise"));
points.zero = new Point(0, 0)
points.center = points.zero.shift(90, store.get('rise'))
// Side top
points.sideRight = new Point(store.get("hipsBack") / 2, points.center.y);
points.sideRight = new Point(store.get('hipsBack') / 2, points.center.y)
// Gusset
points.gussetTop = points.center.shift(-90, store.get("riseLength"));
points.gussetBottom = points.gussetTop.shift(
-90,
store.get("gusset") + store.get("legBonus")
);
points.gussetRight = points.gussetBottom.shift(
0,
(store.get("gusset") * store.get("xScale")) / 2
);
points.gussetCpRight = new Point(points.gussetRight.x, points.gussetTop.y);
points.gussetTop = points.center.shift(-90, store.get('riseLength'))
points.gussetBottom = points.gussetTop.shift(-90, store.get('gusset') + store.get('legBonus'))
points.gussetRight = points.gussetBottom.shift(0, (store.get('gusset') * store.get('xScale')) / 2)
points.gussetCpRight = new Point(points.gussetRight.x, points.gussetTop.y)
// Find leg edge
let isect = utils.circlesIntersect(
points.gussetRight,
store.get("legBack"),
store.get('legBack'),
points.sideRight,
store.get("fullLength")
);
points.legRight = isect[1];
points.legLeft = points.legRight.flipX(points.center);
store.get('fullLength')
)
points.legRight = isect[1]
points.legLeft = points.legRight.flipX(points.center)
// Store back seam length and (half of the) crotch seam length
store.set("backSeamLength", points.sideRight.dist(points.legRight));
store.set('backSeamLength', points.sideRight.dist(points.legRight))
store.set(
"crotchSeamLength",
'crotchSeamLength',
new Path()
.move(points.gussetTop)
.curve(points.gussetCpRight, points.gussetRight, points.gussetRight)
.length()
);
)
// Handle back rise
points.center = points.center.shift(90, store.get("backRise"));
points.sideRight = points.sideRight.shift(90, store.get("sideRise"));
points.centerCpRight = new Point(points.sideRight.x / 2, points.center.y);
points.centerCpLeft = points.centerCpRight.flipX();
points.center = points.center.shift(90, store.get('backRise'))
points.sideRight = points.sideRight.shift(90, store.get('sideRise'))
points.centerCpRight = new Point(points.sideRight.x / 2, points.center.y)
points.centerCpLeft = points.centerCpRight.flipX()
paths.seam = new Path()
.move(points.gussetTop)
@ -72,7 +66,7 @@ export default function(part) {
.curve(points.sideRight, points.centerCpRight, points.center)
.line(points.gussetTop)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Complete pattern?
if (complete) {
@ -81,15 +75,15 @@ export default function(part) {
.move(points.legRight)
.line(points.sideRight)
.curve(points.sideRight, points.centerCpRight, points.center)
.offset(sa);
.offset(sa)
let sa2 = new Path()
.move(points.gussetTop)
.curve(points.gussetCpRight, points.gussetRight, points.gussetRight)
.offset(sa);
.offset(sa)
let hemSa = new Path()
.move(points.gussetRight)
.line(points.legRight)
.offset(sa * 2);
.offset(sa * 2)
paths.sa = new Path()
.move(points.gussetTop)
.line(sa2.start())
@ -97,68 +91,65 @@ export default function(part) {
.join(hemSa)
.join(sa1)
.line(points.center)
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
points.title = new Point(
points.sideRight.x * 0.6,
points.gussetTop.y * 0.6
);
macro("title", {
points.title = new Point(points.sideRight.x * 0.6, points.gussetTop.y * 0.6)
macro('title', {
at: points.title,
nr: 1,
title: "back"
});
macro("cutonfold", {
title: 'back'
})
macro('cutonfold', {
from: points.center,
to: points.gussetTop,
grainline: true
});
snippets.logo = new Snippet("logo", points.title.shift(90, 50));
})
snippets.logo = new Snippet('logo', points.title.shift(90, 50))
}
// Paperless?
if (paperless) {
macro("vd", {
macro('vd', {
from: points.gussetTop,
to: points.center,
x: points.center.x - 15
});
macro("vd", {
})
macro('vd', {
from: points.gussetRight,
to: points.center,
x: points.center.x - 30
});
macro("vd", {
})
macro('vd', {
from: points.legRight,
to: points.sideRight,
x: points.legRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.legRight,
to: points.center,
x: points.legRight.x + 30 + sa
});
macro("hd", {
})
macro('hd', {
from: points.center,
to: points.sideRight,
y: points.center.y - 15 - sa
});
macro("hd", {
})
macro('hd', {
from: points.gussetTop,
to: points.gussetRight,
y: points.gussetRight.y + 15 + sa * 2
});
macro("hd", {
})
macro('hd', {
from: points.gussetTop,
to: points.legRight,
y: points.gussetRight.y + 30 + sa * 2
});
macro("ld", {
})
macro('ld', {
from: points.gussetRight,
to: points.legRight,
d: -15 - sa * 2
});
})
}
return part;
return part
}

View file

@ -1,32 +1,25 @@
import init from "./init";
import init from './init'
function tuskDelta(part) {
let { Path, points, store } = part.shorthand();
let { Path, points, store } = part.shorthand()
let len = new Path()
.move(points.midRight)
.curve(
points.curveRightCpTop,
points.curveRightCpBottom,
points.rightTuskRight
)
.length();
.curve(points.curveRightCpTop, points.curveRightCpBottom, points.rightTuskRight)
.length()
return len - store.get("curve");
return len - store.get('curve')
}
function tweakTusk(delta, part) {
let { points } = part.shorthand();
let { points } = part.shorthand()
let factor;
if (Math.abs(delta) > 2) factor = 3;
else factor = 5;
let factor
if (Math.abs(delta) > 2) factor = 3
else factor = 5
points.rightTuskRight = points.rightTuskRight.shift(90, delta / factor);
points.rightTuskLeft = points.rightTuskLeft.shift(90, delta / factor);
points.curveRightCpBottom = points.curveRightCpBottom.shift(
90,
delta / factor
);
points.rightTuskRight = points.rightTuskRight.shift(90, delta / factor)
points.rightTuskLeft = points.rightTuskLeft.shift(90, delta / factor)
points.curveRightCpBottom = points.curveRightCpBottom.shift(90, delta / factor)
}
export default function(part) {
@ -43,133 +36,108 @@ export default function(part) {
macro,
utils,
debug
} = part.shorthand();
} = part.shorthand()
// Initialize
init(part);
init(part)
points.topRight = new Point(store.get("hipsFront") / 2, 0);
points.topLeft = points.topRight.flipX();
points.midMid = new Point(0, store.get("heightFront"));
points.midRight = new Point(
points.topRight.x + store.get("heightFront") * 0.05,
points.midMid.y
);
points.midLeft = points.midRight.flipX();
points.topRight = new Point(store.get('hipsFront') / 2, 0)
points.topLeft = points.topRight.flipX()
points.midMid = new Point(0, store.get('heightFront'))
points.midRight = new Point(points.topRight.x + store.get('heightFront') * 0.05, points.midMid.y)
points.midLeft = points.midRight.flipX()
// Store this length for a notch on the side part
store.set("frontNotch", points.topRight.dist(points.midRight));
store.set('frontNotch', points.topRight.dist(points.midRight))
points.bottomMid = new Point(0, store.get("riseLength"));
points.bottomMid = new Point(0, store.get('riseLength'))
points.rightTuskRight = new Point(
store.get("gusset") *
store.get("xScale") *
(1 - store.get("gussetInsetRatio")),
store.get('gusset') * store.get('xScale') * (1 - store.get('gussetInsetRatio')),
points.bottomMid.y
);
points.rightTuskLeft = points.bottomMid.clone();
)
points.rightTuskLeft = points.bottomMid.clone()
points.curveRightCpTop = new Point(
points.midRight.x - store.get("gusset") * 1.3,
points.midRight.x - store.get('gusset') * 1.3,
points.midRight.y
);
)
points.curveRightCpBottom = new Point(
points.rightTuskRight.x,
points.rightTuskRight.y - store.get("gusset") * 1.3
);
points.rightTuskRight.y - store.get('gusset') * 1.3
)
// Adjust tusk length to fit inset curve
let delta = tuskDelta(part);
let count = 0;
let delta = tuskDelta(part)
let count = 0
while (Math.abs(delta) > 1) {
// Below 1mm is good enough
tweakTusk(delta, part);
delta = tuskDelta(part);
count++;
tweakTusk(delta, part)
delta = tuskDelta(part)
count++
if (count > 150)
throw "We got stuck trying to calculate an optimal tusk length. Please report this.";
throw 'We got stuck trying to calculate an optimal tusk length. Please report this.'
}
debug(
`After ${count} iterations, tusk curve length is ${utils.round(
delta
)}mm off.`
);
debug(`After ${count} iterations, tusk curve length is ${utils.round(delta)}mm off.`)
// Adjust midMid to new length
points.bottomMid = new Point(0, points.rightTuskLeft.y);
points.bottomMid = new Point(0, points.rightTuskLeft.y)
// Front dart only if bulge > 0
if (options.bulge > 0) {
// Rotate tusk according to bulge option
for (let pid of [
"curveRightCpTop",
"curveRightCpBottom",
"rightTuskRight",
"rightTuskLeft"
]) {
points[pid] = points[pid].rotate(options.bulge, points.midRight);
for (let pid of ['curveRightCpTop', 'curveRightCpBottom', 'rightTuskRight', 'rightTuskLeft']) {
points[pid] = points[pid].rotate(options.bulge, points.midRight)
}
// Dart join point
points.dartJoin = new Point(
0,
points.midMid.y + 0.65 * points.midMid.dist(points.bottomMid)
);
points.dartJoin = new Point(0, points.midMid.y + 0.65 * points.midMid.dist(points.bottomMid))
// Dart control point
points.dartCpRight = new Point(
0,
points.dartJoin.y +
points.dartJoin.dist(points.bottomMid) * (options.bulge / 30)
);
points.dartCpRight = points.dartCpRight.rotate(
options.bulge,
points.dartJoin
);
points.dartJoin.y + points.dartJoin.dist(points.bottomMid) * (options.bulge / 30)
)
points.dartCpRight = points.dartCpRight.rotate(options.bulge, points.dartJoin)
// Flip control point to left side
points.dartCpLeft = points.dartCpRight.flipX();
points.dartCpLeft = points.dartCpRight.flipX()
} else {
points.dartJoin = points.rightTuskLeft;
points.dartJoin = points.rightTuskLeft
}
// Flip points to left side
points.leftTuskRight = points.rightTuskLeft.flipX();
points.leftTuskLeft = points.rightTuskRight.flipX();
points.curveLeftCpBottom = points.curveRightCpBottom.flipX();
points.curveLeftCpTop = points.curveRightCpTop.flipX();
points.leftTuskRight = points.rightTuskLeft.flipX()
points.leftTuskLeft = points.rightTuskRight.flipX()
points.curveLeftCpBottom = points.curveRightCpBottom.flipX()
points.curveLeftCpTop = points.curveRightCpTop.flipX()
// Handle back rise
points.topMid = new Point(0, points.topLeft.y);
points.topLeft = points.topLeft.shift(90, store.get("frontRise"));
points.topRight = points.topRight.shift(90, store.get("frontRise"));
points.topMidCpRight = new Point(points.topRight.x / 2, points.topMid.y);
points.topMidCpLeft = points.topMidCpRight.flipX();
points.topMid = new Point(0, points.topLeft.y)
points.topLeft = points.topLeft.shift(90, store.get('frontRise'))
points.topRight = points.topRight.shift(90, store.get('frontRise'))
points.topMidCpRight = new Point(points.topRight.x / 2, points.topMid.y)
points.topMidCpLeft = points.topMidCpRight.flipX()
if (options.bulge > 0) {
paths.trimBase = new Path()
.move(points.rightTuskLeft)
.curve(points.rightTuskLeft, points.dartCpRight, points.dartJoin)
.curve(points.dartCpLeft, points.leftTuskRight, points.leftTuskRight);
.curve(points.dartCpLeft, points.leftTuskRight, points.leftTuskRight)
paths.seamStart = new Path()
.move(points.midLeft)
.line(points.topLeft)
.curve(points.topLeft, points.topMidCpLeft, points.topMid)
.curve(points.topMidCpRight, points.topRight, points.topRight)
.line(points.midRight)
.curve(
points.curveRightCpTop,
points.curveRightCpBottom,
points.rightTuskRight
)
.line(points.rightTuskLeft);
.curve(points.curveRightCpTop, points.curveRightCpBottom, points.rightTuskRight)
.line(points.rightTuskLeft)
paths.seamEnd = new Path()
.move(points.leftTuskRight)
.line(points.leftTuskLeft)
.curve(points.curveLeftCpBottom, points.curveLeftCpTop, points.midLeft);
paths.seamStart.render = false;
paths.trimBase.render = false;
paths.seamEnd.render = false;
paths.seam = paths.seamStart.join(paths.trimBase).join(paths.seamEnd);
.curve(points.curveLeftCpBottom, points.curveLeftCpTop, points.midLeft)
paths.seamStart.render = false
paths.trimBase.render = false
paths.seamEnd.render = false
paths.seam = paths.seamStart.join(paths.trimBase).join(paths.seamEnd)
} else {
paths.seam = new Path()
.move(points.midLeft)
@ -177,140 +145,128 @@ export default function(part) {
.curve(points.topLeft, points.topMidCpLeft, points.topMid)
.curve(points.topMidCpRight, points.topRight, points.topRight)
.line(points.midRight)
.curve(
points.curveRightCpTop,
points.curveRightCpBottom,
points.rightTuskRight
)
.curve(points.curveRightCpTop, points.curveRightCpBottom, points.rightTuskRight)
.line(points.leftTuskLeft)
.curve(points.curveLeftCpBottom, points.curveLeftCpTop, points.midLeft);
.curve(points.curveLeftCpBottom, points.curveLeftCpTop, points.midLeft)
}
paths.seam.close().attr("class", "fabric");
paths.seam.close().attr('class', 'fabric')
// Complete pattern?
if (complete) {
if (sa) {
if (options.bulge > 0) {
let saStart = paths.seamStart.offset(sa * -1);
let saTrim = paths.trimBase.offset(sa * -1).trim();
let saEnd = paths.seamEnd.offset(sa * -1);
let saStart = paths.seamStart.offset(sa * -1)
let saTrim = paths.trimBase.offset(sa * -1).trim()
let saEnd = paths.seamEnd.offset(sa * -1)
paths.sa = saStart
.join(saTrim)
.join(saEnd)
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
} else {
paths.sa = paths.seam
.offset(sa * -1)
.trim()
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
}
macro("title", {
macro('title', {
at: points.midMid,
nr: 2,
title: "front"
});
macro("grainline", {
title: 'front'
})
macro('grainline', {
from: points.dartJoin,
to: points.topMid
});
})
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.topLeft,
to: points.topRight,
y: points.topLeft.y - 15 - sa
});
macro("hd", {
})
macro('hd', {
from: points.midLeft,
to: points.midRight,
y: points.topLeft.y - 30 - sa
});
macro("vd", {
})
macro('vd', {
from: points.midLeft,
to: points.topMid,
x: points.midLeft.x - 15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.midLeft,
to: points.topLeft,
x: points.midLeft.x - 30 - sa
});
})
if (options.bulge === 0) {
macro("hd", {
macro('hd', {
from: points.leftTuskLeft,
to: points.rightTuskRight,
y: points.leftTuskLeft.y + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.leftTuskLeft,
to: points.topLeft,
x: points.midLeft.x - 45 - sa
});
})
} else {
macro("vd", {
macro('vd', {
from: points.leftTuskLeft,
to: points.topLeft,
x: points.midLeft.x - 45 - sa
});
macro("vd", {
})
macro('vd', {
from: points.leftTuskRight,
to: points.topLeft,
x: points.midLeft.x - 60 - sa
});
})
points.narrowRight = new Path()
.move(points.midRight)
.curve(
points.curveRightCpTop,
points.curveRightCpBottom,
points.rightTuskRight
)
.edge("left");
.curve(points.curveRightCpTop, points.curveRightCpBottom, points.rightTuskRight)
.edge('left')
points.narrowLeft = new Path()
.move(points.midLeft)
.curve(
points.curveLeftCpTop,
points.curveLeftCpBottom,
points.leftTuskLeft
)
.attr("class", "various stroke-xl lashed")
.edge("right");
macro("hd", {
.curve(points.curveLeftCpTop, points.curveLeftCpBottom, points.leftTuskLeft)
.attr('class', 'various stroke-xl lashed')
.edge('right')
macro('hd', {
from: points.narrowLeft,
to: points.narrowRight,
y: points.narrowLeft.y
});
macro("hd", {
})
macro('hd', {
from: points.leftTuskRight,
to: points.rightTuskLeft,
y: points.rightTuskLeft.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.leftTuskLeft,
to: points.rightTuskRight,
y: points.rightTuskLeft.y + 30 + sa
});
macro("ld", {
})
macro('ld', {
from: points.rightTuskLeft,
to: points.rightTuskRight,
d: -15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.narrowRight,
to: points.topRight,
x: points.topRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.dartJoin,
to: points.topRight,
x: points.topRight.x + 30 + sa
});
})
}
}
return part;
return part
}

View file

@ -1,19 +1,19 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import config from '../config'
// Parts
import draftBack from "./back";
import draftSide from "./side";
import draftFront from "./front";
import draftInset from "./inset";
import draftBack from './back'
import draftSide from './side'
import draftFront from './front'
import draftInset from './inset'
// Create design
const Pattern = new freesewing.Design(config, plugins);
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
Pattern.prototype.draftBack = part => draftBack(part);
Pattern.prototype.draftSide = part => draftSide(part);
Pattern.prototype.draftInset = part => draftInset(part);
Pattern.prototype.draftFront = part => draftFront(part);
Pattern.prototype.draftBack = part => draftBack(part)
Pattern.prototype.draftSide = part => draftSide(part)
Pattern.prototype.draftInset = part => draftInset(part)
Pattern.prototype.draftFront = part => draftFront(part)
export default Pattern;
export default Pattern

View file

@ -1,50 +1,54 @@
export default function init(part) {
let {store, options, measurements, utils} = part.shorthand();
let { store, options, measurements, utils } = part.shorthand()
if(store.get('init') !== true) {
if (store.get('init') !== true) {
/* Set vertical scale to 1 (no stretch) */
store.set('yScale', 1);
store.set('yScale', 1)
/* Store rise, backRise and legBonus as absolute values */
store.set('rise', measurements.hipsToUpperLeg * options.rise * store.get('yScale'));
store.set('backRise', measurements.hipsToUpperLeg * options.backRise * store.get('yScale'));
store.set('sideRise', store.get('backRise') * 0.75);
store.set('frontRise', store.get('backRise') * 0.25);
store.set('legBonus', measurements.hipsToUpperLeg * options.legBonus * store.get('yScale'));
store.set('rise', measurements.hipsToUpperLeg * options.rise * store.get('yScale'))
store.set('backRise', measurements.hipsToUpperLeg * options.backRise * store.get('yScale'))
store.set('sideRise', store.get('backRise') * 0.75)
store.set('frontRise', store.get('backRise') * 0.25)
store.set('legBonus', measurements.hipsToUpperLeg * options.legBonus * store.get('yScale'))
/* Set horizontal scale based on stretch */
store.set('xScale', utils.stretchToScale(options.stretch));
store.set('xScaleLegs', utils.stretchToScale(options.legStretch));
store.set('xScale', utils.stretchToScale(options.stretch))
store.set('xScaleLegs', utils.stretchToScale(options.legStretch))
/* Ratio of parts at the hips*/
store.set('hips', measurements.hipsCircumference * store.get('xScale'));
store.set('hipsFront', store.get('hips') * options.hipRatioFront);
let hipRatioSide = (1 - (options.hipRatioFront + options.hipRatioBack)) / 2;
store.set('hipsSide', store.get('hips') * hipRatioSide);
store.set('hipsBack', store.get('hips') * options.hipRatioBack);
store.set('hips', measurements.hipsCircumference * store.get('xScale'))
store.set('hipsFront', store.get('hips') * options.hipRatioFront)
let hipRatioSide = (1 - (options.hipRatioFront + options.hipRatioBack)) / 2
store.set('hipsSide', store.get('hips') * hipRatioSide)
store.set('hipsBack', store.get('hips') * options.hipRatioBack)
/* Ratio of parts at the legs*/
store.set('leg', measurements.upperLegCircumference * store.get('xScaleLegs'));
store.set('legInset', store.get('leg') * options.legRatioInset);
let legRatioSide = 1 - options.legRatioInset - options.legRatioBack;
store.set('legSide', store.get('leg') * legRatioSide);
store.set('legBack', store.get('leg') * options.legRatioBack);
store.set('leg', measurements.upperLegCircumference * store.get('xScaleLegs'))
store.set('legInset', store.get('leg') * options.legRatioInset)
let legRatioSide = 1 - options.legRatioInset - options.legRatioBack
store.set('legSide', store.get('leg') * legRatioSide)
store.set('legBack', store.get('leg') * options.legRatioBack)
/* Gusset */
store.set('gusset', measurements.hipsCircumference * options.gussetRatio);
store.set('gussetInsetRatio', options.gussetInsetRatio);
store.set('gusset', measurements.hipsCircumference * options.gussetRatio)
store.set('gussetInsetRatio', options.gussetInsetRatio)
/* Length helper */
store.set('length', measurements.hipsToUpperLeg * store.get('yScale'));
store.set('riseLength', measurements.hipsToUpperLeg + store.get('rise'));
store.set('fullLength', store.get('riseLength') + store.get('legBonus') * store.get('yScale'));
store.set('length', measurements.hipsToUpperLeg * store.get('yScale'))
store.set('riseLength', measurements.hipsToUpperLeg + store.get('rise'))
store.set('fullLength', store.get('riseLength') + store.get('legBonus') * store.get('yScale'))
/* Height ratio front/inset */
store.set('heightInset', store.get('riseLength') * options.heightRatioInset + store.get('legBonus') * store.get('yScale'));
store.set('heightFront', store.get('riseLength') * (1 - options.heightRatioInset));
store.set(
'heightInset',
store.get('riseLength') * options.heightRatioInset +
store.get('legBonus') * store.get('yScale')
)
store.set('heightFront', store.get('riseLength') * (1 - options.heightRatioInset))
/* Absolute amount to raise the back */
store.set('init', true);
store.set('init', true)
}
}

View file

@ -1,48 +1,34 @@
import init from "./init";
import init from './init'
export default function(part) {
let {
store,
sa,
Point,
points,
Path,
paths,
complete,
paperless,
macro
} = part.shorthand();
let { store, sa, Point, points, Path, paths, complete, paperless, macro } = part.shorthand()
// Initialize
init(part);
init(part)
// height is 73.5%
points.topLeft = new Point(0, 0);
points.bottomLeft = points.topLeft.shift(-90, store.get("heightInset"));
points.bottomRight = new Point(store.get("legInset"), points.bottomLeft.y);
points.tip = new Point(
points.bottomRight.x * 1.111,
points.bottomRight.y - store.get("gusset")
);
points.topLeft = new Point(0, 0)
points.bottomLeft = points.topLeft.shift(-90, store.get('heightInset'))
points.bottomRight = new Point(store.get('legInset'), points.bottomLeft.y)
points.tip = new Point(points.bottomRight.x * 1.111, points.bottomRight.y - store.get('gusset'))
points.tip = points.bottomRight.shiftTowards(
points.tip,
store.get("crotchSeamLength") -
store.get("gusset") * (1 - store.get("gussetInsetRatio"))
);
points.tipCpTop = new Point(store.get("gusset") * 1.2, 0);
store.get('crotchSeamLength') - store.get('gusset') * (1 - store.get('gussetInsetRatio'))
)
points.tipCpTop = new Point(store.get('gusset') * 1.2, 0)
points.tipCpBottom = points.tip.shift(
points.bottomRight.angle(points.tip) + 90,
store.get("gusset") * 1.5
);
store.get('gusset') * 1.5
)
// Store cuve length
store.set(
"curve",
'curve',
new Path()
.move(points.tip)
.curve(points.tipCpBottom, points.tipCpTop, points.topLeft)
.length()
);
)
// Path
paths.seam = new Path()
@ -52,46 +38,46 @@ export default function(part) {
.line(points.tip)
.curve(points.tipCpBottom, points.tipCpTop, points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Complete pattern?
if (complete) {
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title.shift(-90, 15),
nr: 4,
title: "inset"
});
macro("grainline", {
title: 'inset'
})
macro('grainline', {
from: points.bottomLeft.shift(0, 15),
to: points.topLeft.shift(0, 15)
});
})
}
// Paperless?
if (paperless) {
macro("vd", {
macro('vd', {
from: points.bottomLeft,
to: points.topLeft,
x: points.topLeft.x - 15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.tip,
x: points.tip.x + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomRight.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.bottomLeft,
to: points.tip,
y: points.bottomRight.y + 30 + sa
});
})
}
return part;
return part
}

View file

@ -1,4 +1,4 @@
import init from "./init";
import init from './init'
export default function(part) {
let {
@ -12,36 +12,36 @@ export default function(part) {
paperless,
macro,
utils
} = part.shorthand();
} = part.shorthand()
// Initialize
init(part);
init(part)
// Top left
points.zero = new Point(0, 0);
points.topLeft = points.zero.shift(90, store.get("rise"));
points.zero = new Point(0, 0)
points.topLeft = points.zero.shift(90, store.get('rise'))
// Top right
points.topRight = new Point(store.get("hipsSide"), points.topLeft.y);
points.topRight = new Point(store.get('hipsSide'), points.topLeft.y)
// Bottom right
points.bottomRight = points.topRight.shift(-90, store.get("fullLength"));
points.bottomRight = points.topRight.shift(-90, store.get('fullLength'))
// Find bottom left
let isect = utils.circlesIntersect(
points.bottomRight,
store.get("legSide"),
store.get('legSide'),
points.topLeft,
store.get("backSeamLength")
);
points.bottomLeft = isect[0];
store.get('backSeamLength')
)
points.bottomLeft = isect[0]
// Store side seam length
store.set("sideSeamLength", points.topRight.dist(points.bottomRight));
store.set('sideSeamLength', points.topRight.dist(points.bottomRight))
// Handle back rise
points.topLeft = points.topLeft.shift(90, store.get("sideRise"));
points.topRight = points.topRight.shift(90, store.get("frontRise"));
points.topLeft = points.topLeft.shift(90, store.get('sideRise'))
points.topRight = points.topRight.shift(90, store.get('frontRise'))
// Path
paths.seam = new Path()
@ -51,51 +51,51 @@ export default function(part) {
.line(points.bottomLeft)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
// Anchor point for sampling
points.anchor = points.topLeft;
points.anchor = points.topLeft
// Complete pattern?
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title.shift(90, 30),
nr: 3,
title: "side"
});
title: 'side'
})
if (sa) {
paths.sa = paths.seam.offset(sa * -1).attr("class", "fabric sa");
paths.sa = paths.seam.offset(sa * -1).attr('class', 'fabric sa')
}
macro("grainline", {
macro('grainline', {
from: new Point(points.bottomRight.x / 2, points.bottomRight.y),
to: new Point(points.bottomRight.x / 2, points.topRight.y)
});
})
}
// Paperless?
if (paperless) {
macro("vd", {
macro('vd', {
from: points.bottomLeft,
to: points.topLeft,
x: points.topLeft.x - 15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.topLeft,
to: points.topRight,
y: points.topLeft.y - 15 - sa
});
macro("hd", {
})
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + 15 + sa
});
})
}
return part;
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -14,7 +14,7 @@ export default function(part) {
Point,
paths,
Path
} = part.shorthand();
} = part.shorthand()
/**
* we're adding half of the proportionate amount of chest east for the bust span
@ -24,14 +24,11 @@ export default function(part) {
measurements.bustSpan / 2 +
((measurements.bustSpan / measurements.bust) * options.chestEase) / 4,
points.neck.y + measurements.highPointShoulderToBust
);
)
// Draw the princess seam (ps)
points.psHem = new Point(points.bustPoint.x, points.hem.y);
points.bustPointCp1 = points.bustPoint.shift(
90,
points.armholePitch.dy(points.bustPoint) / 2
);
points.psHem = new Point(points.bustPoint.x, points.hem.y)
points.bustPointCp1 = points.bustPoint.shift(90, points.armholePitch.dy(points.bustPoint) / 2)
// Paths
paths.seam = new Path()
@ -46,15 +43,11 @@ export default function(part) {
.line(points.hemEdge)
.line(points.psHem)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.chestPiece = paths.chestPiece
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.curve(
points.armholeHollowCp2,
points.armholePitchCp1,
points.armholePitch
);
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
paths.chestPocket = new Path()
.move(points.chestPocketTopLeft)
@ -63,7 +56,7 @@ export default function(part) {
.line(points.chestPocketTopRight)
.line(points.chestPocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
/////////////////////////////////////////
@ -74,146 +67,135 @@ export default function(part) {
*/
let side = [
"bustPoint",
"bustPointCp1",
"psHem",
"hem",
"seat",
"seatCp2",
"waistCp1",
"waist",
"waistCp2",
"armhole",
"armholeCp2",
"armholeHollowCp1",
"armholeHollow",
"armholeHollowCp2",
"armholePitchCp1",
"armholePitch"
];
'bustPoint',
'bustPointCp1',
'psHem',
'hem',
'seat',
'seatCp2',
'waistCp1',
'waist',
'waistCp2',
'armhole',
'armholeCp2',
'armholeHollowCp1',
'armholeHollow',
'armholeHollowCp2',
'armholePitchCp1',
'armholePitch'
]
// Store these, we'll use them in the side part
store.set("side", side);
store.set('side', side)
// How much (horizontal) room do we need to create?
let extra = measurements.bust - measurements.highBust;
let extra = measurements.bust - measurements.highBust
/* Cut from armholePitch point to bustPoint and rotate
* entire side panel until we have created enough room */
let added = 0;
let delta = 10;
let count = 1;
let added = 0
let delta = 10
let count = 1
while (Math.abs(delta) > 0.5 && count < 50) {
for (let i of side)
points[i + "Rot1"] = points[i].rotate(delta / 5, points.armholePitch);
added = points.bustPoint.dx(points.bustPointRot1);
delta = extra - added;
count++;
for (let i of side) points[i + 'Rot1'] = points[i].rotate(delta / 5, points.armholePitch)
added = points.bustPoint.dx(points.bustPointRot1)
delta = extra - added
count++
}
/* Now cut from armhole to rotated bustpoint and rotate
* the lower part of the site until it's aligned vertically again
* We'll also rotate the top point, thus closing the bust dart */
let angle = -1 * (points.bustPointRot1.angle(points.psHemRot1) - 270);
for (let i of side)
points[i + "Rot2"] = points[i + "Rot1"].rotate(angle, points.bustPointRot1);
let angle = -1 * (points.bustPointRot1.angle(points.psHemRot1) - 270)
for (let i of side) points[i + 'Rot2'] = points[i + 'Rot1'].rotate(angle, points.bustPointRot1)
// Also rotate original bustPoint and bustPointCp1
points.bustPointRot2 = points.bustPoint.rotate(angle, points.bustPointRot1);
points.bustPointCp1Rot2 = points.bustPointCp1.rotate(
angle,
points.bustPointRot1
);
points.bustPointRot2 = points.bustPoint.rotate(angle, points.bustPointRot1)
points.bustPointCp1Rot2 = points.bustPointCp1.rotate(angle, points.bustPointRot1)
// Now construct the new curve
points.bustPointCp2 = points.bustPointCp1Rot2
.rotate(180, points.bustPointRot2)
.shiftFractionTowards(points.bustPointRot2, 0.5);
points.psWaist = new Point(points.psHemRot2.x, points.waistRot2.y);
.shiftFractionTowards(points.bustPointRot2, 0.5)
points.psWaist = new Point(points.psHemRot2.x, points.waistRot2.y)
points.psWaistCp1 = points.psWaist.shift(
90,
points.bustPointRot2.dy(points.psWaist) * options.contour
);
)
// Adapt lenght of the front part
let frontCurve = new Path()
.move(points.armholePitch)
._curve(points.bustPointCp1, points.bustPoint)
.line(new Point(points.psHem.x, points.waist.y))
.length();
.length()
let sideCurve = new Path()
.move(points.armholePitchRot2)
._curve(points.bustPointCp1Rot2, points.bustPointRot2)
.curve(points.bustPointCp2, points.psWaistCp1, points.psWaist)
.length();
let longer = sideCurve - frontCurve;
.length()
let longer = sideCurve - frontCurve
let belowBust = [
"button1Left",
"button2Left",
"button3Left",
"button1Right",
"button2Right",
"button3Right",
"rollLineStart",
"hemEdge",
"flbHem",
"psHem",
"pocketTopLeft",
"pocketTopRight",
"pocketBottomLeft",
"pocketBottomRight",
"pocketRoundLeftStart",
"pocketRoundLeftCp1",
"pocketRoundLeftCp2",
"pocketRoundLeftEnd",
"pocketRoundRightStart",
"pocketRoundRightCp1",
"pocketRoundRightCp2",
"pocketRoundRightEnd",
"pocketFlapTopLeft",
"pocketFlapTopRight",
"pocketFlapBottomLeft",
"pocketFlapBottomRight",
"pocketFlapRoundLeftStart",
"pocketFlapRoundLeftCp1",
"pocketFlapRoundLeftCp2",
"pocketFlapRoundLeftEnd",
"pocketFlapRoundRightStart",
"pocketFlapRoundRightCp1",
"pocketFlapRoundRightCp2",
"pocketFlapRoundRightEnd",
"innerPocketTopLeft",
"innerPocketTopRight",
"innerPocketBottomLeft",
"innerPocketBottomRight",
"chestPocketTopLeft",
"chestPocketTopRight",
"chestPocketBottomLeft",
"chestPocketBottomRight"
];
'button1Left',
'button2Left',
'button3Left',
'button1Right',
'button2Right',
'button3Right',
'rollLineStart',
'hemEdge',
'flbHem',
'psHem',
'pocketTopLeft',
'pocketTopRight',
'pocketBottomLeft',
'pocketBottomRight',
'pocketRoundLeftStart',
'pocketRoundLeftCp1',
'pocketRoundLeftCp2',
'pocketRoundLeftEnd',
'pocketRoundRightStart',
'pocketRoundRightCp1',
'pocketRoundRightCp2',
'pocketRoundRightEnd',
'pocketFlapTopLeft',
'pocketFlapTopRight',
'pocketFlapBottomLeft',
'pocketFlapBottomRight',
'pocketFlapRoundLeftStart',
'pocketFlapRoundLeftCp1',
'pocketFlapRoundLeftCp2',
'pocketFlapRoundLeftEnd',
'pocketFlapRoundRightStart',
'pocketFlapRoundRightCp1',
'pocketFlapRoundRightCp2',
'pocketFlapRoundRightEnd',
'innerPocketTopLeft',
'innerPocketTopRight',
'innerPocketBottomLeft',
'innerPocketBottomRight',
'chestPocketTopLeft',
'chestPocketTopRight',
'chestPocketBottomLeft',
'chestPocketBottomRight'
]
for (let i of belowBust) {
// Round points depend on options, so add a check
if (typeof points[i] !== "undefined") {
points[i] = points[i].shift(-90, longer);
} else console.log(i);
if (typeof points[i] !== 'undefined') {
points[i] = points[i].shift(-90, longer)
} else console.log(i)
}
// Move the map/chest pocket into the princess seam
points.chestPocketBottomLeft = new Point(
points.bustPoint.x,
points.button2Right.y - points.button3Right.dy(points.button2Right) / 10
);
points.chestPocketTopLeft = points.chestPocketBottomLeft.shift(
90,
store.get("chestPocketHeight")
);
points.chestPocketTopRight = points.chestPocketTopLeft.shift(
0,
store.get("chestPocketWidth")
);
)
points.chestPocketTopLeft = points.chestPocketBottomLeft.shift(90, store.get('chestPocketHeight'))
points.chestPocketTopRight = points.chestPocketTopLeft.shift(0, store.get('chestPocketWidth'))
points.chestPocketBottomRight = points.chestPocketBottomLeft.shift(
0,
store.get("chestPocketWidth")
);
store.get('chestPocketWidth')
)
// Uncomment these to better understand the FBA
/*
@ -256,8 +238,8 @@ export default function(part) {
*/
// Clean up
for (let i in paths) delete paths[i];
for (let i in snippets) delete snippets[i];
for (let i in paths) delete paths[i]
for (let i in snippets) delete snippets[i]
// Paths
paths.saBase = new Path()
@ -270,22 +252,22 @@ export default function(part) {
.line(points.collarTip)
._curve(points.lapelStraightEndCp1, points.lapelStraightEnd)
.line(points.hemEdge)
.line(points.flbHem);
.line(points.flbHem)
paths.seam = paths.saBase
.clone()
.line(points.psHem)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.rollLine = new Path()
.move(points.rollLineStart)
.line(points.rollLineEnd)
.attr("class", "lashed");
.attr('class', 'lashed')
paths.flb = new Path()
.move(points.flbHem)
.line(points.flbTop)
.attr("class", "lining lashed");
.attr('class', 'lining lashed')
paths.pocket = new Path()
.move(
@ -297,15 +279,11 @@ export default function(part) {
)
)
.line(points.pocketTopLeft)
.attr("class", "fabric help");
.attr('class', 'fabric help')
if (options.pocketRadius > 0) {
paths.pocket = paths.pocket
.line(points.pocketRoundLeftStart)
.curve(
points.pocketRoundLeftCp1,
points.pocketRoundLeftCp2,
points.pocketRoundLeftEnd
);
.curve(points.pocketRoundLeftCp1, points.pocketRoundLeftCp2, points.pocketRoundLeftEnd)
} else {
paths.pocket = paths.pocket
.line(points.pocketBottomLeft)
@ -316,7 +294,7 @@ export default function(part) {
points.bustPoint,
points.psHem
)
);
)
}
paths.pocketFlap = new Path()
@ -329,7 +307,7 @@ export default function(part) {
)
)
.line(points.pocketFlapTopLeft)
.attr("class", "fabric help");
.attr('class', 'fabric help')
if (options.pocketFlapRadius > 0) {
paths.pocketFlap = paths.pocketFlap
.line(points.pocketFlapRoundLeftStart)
@ -337,7 +315,7 @@ export default function(part) {
points.pocketFlapRoundLeftCp1,
points.pocketFlapRoundLeftCp2,
points.pocketFlapRoundLeftEnd
);
)
} else {
paths.pocketFlap = paths.pocketFlap
.line(points.pocketFlapBottomLeft)
@ -348,7 +326,7 @@ export default function(part) {
points.bustPoint,
points.psHem
)
);
)
}
paths.chestPocket = new Path()
@ -358,7 +336,7 @@ export default function(part) {
.line(points.chestPocketTopRight)
.line(points.chestPocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
paths.innerPocket = new Path()
.move(points.innerPocketTopLeft)
@ -367,180 +345,156 @@ export default function(part) {
.line(points.innerPocketTopRight)
.line(points.innerPocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
if (complete) {
snippets.button1Left = new Snippet("button", points.button1Left).attr(
"data-scale",
2
);
snippets.button1Right = new Snippet("button", points.button1Right).attr(
"data-scale",
2
);
snippets.button2Left = new Snippet("button", points.button2Left).attr(
"data-scale",
2
);
snippets.button2Right = new Snippet("button", points.button2Right).attr(
"data-scale",
2
);
snippets.button3Left = new Snippet("button", points.button3Left).attr(
"data-scale",
2
);
snippets.button3Right = new Snippet("button", points.button3Right).attr(
"data-scale",
2
);
macro("sprinkle", {
snippet: "notch",
on: [
"cfNeck",
"rollLineStart",
"bustPoint",
"chestPocketTopLeft",
"chestPocketBottomLeft"
]
});
points.logo = points.cfSeat.shiftFractionTowards(points.cfHem, 0.5);
snippets.logo = new Snippet("logo", points.logo);
macro("title", { at: points.title, nr: "1a", title: "front" });
macro("grainline", { from: points.cfHem, to: points.cfNeck });
snippets.button1Left = new Snippet('button', points.button1Left).attr('data-scale', 2)
snippets.button1Right = new Snippet('button', points.button1Right).attr('data-scale', 2)
snippets.button2Left = new Snippet('button', points.button2Left).attr('data-scale', 2)
snippets.button2Right = new Snippet('button', points.button2Right).attr('data-scale', 2)
snippets.button3Left = new Snippet('button', points.button3Left).attr('data-scale', 2)
snippets.button3Right = new Snippet('button', points.button3Right).attr('data-scale', 2)
macro('sprinkle', {
snippet: 'notch',
on: ['cfNeck', 'rollLineStart', 'bustPoint', 'chestPocketTopLeft', 'chestPocketBottomLeft']
})
points.logo = points.cfSeat.shiftFractionTowards(points.cfHem, 0.5)
snippets.logo = new Snippet('logo', points.logo)
macro('title', { at: points.title, nr: '1a', title: 'front' })
macro('grainline', { from: points.cfHem, to: points.cfNeck })
if (sa) {
let hemBase = new Path().move(points.flbHem).line(points.psHem);
let hemBase = new Path().move(points.flbHem).line(points.psHem)
paths.sa = paths.saBase
.offset(sa)
.join(hemBase.offset(3 * sa))
.line(points.psHem.shift(-90, 3 * sa).shift(0, sa))
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
if (paperless) {
macro("ld", {
macro('ld', {
from: points.hemEdge,
to: points.flbHem,
d: 15
});
macro("hd", {
})
macro('hd', {
from: points.hemEdge,
to: points.psHem,
y: points.psHem.y + 15 + 3 * sa
});
macro("hd", {
})
macro('hd', {
from: points.rollLineStart,
to: points.pocketTopLeft,
y: points.pocketFlapBottomLeft.y
});
macro("vd", {
})
macro('vd', {
from: points.pocketFlapTopLeft,
to: points.button3Right,
x: points.bustPoint.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.pocketTopLeft,
to: points.button3Right,
x: points.bustPoint.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.chestPocketBottomLeft,
to: points.button3Right,
x: points.bustPoint.x - 15
});
macro("hd", {
})
macro('hd', {
from: points.rollLineStart,
to: points.chestPocketBottomLeft,
y: points.chestPocketBottomLeft.y + 15
});
macro("hd", {
})
macro('hd', {
from: points.rollLineStart,
to: points.button3Left,
y: points.button3Left.y + 15
});
macro("hd", {
})
macro('hd', {
from: points.button3Left,
to: points.button3Right,
y: points.button3Left.y + 15
});
macro("vd", {
})
macro('vd', {
from: points.psHem,
to: points.bustPoint,
x: points.bustPoint.x + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.psHem,
to: points.armholePitch,
x: points.armholePitch.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.armholePitch,
to: points.shoulder,
x: points.shoulder.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.armholePitch,
to: points.neck,
x: points.shoulder.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.rollLineStart,
to: points.collarTip,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.button2Left,
to: points.rollLineStart,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.button1Left,
to: points.button2Left,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hemEdge,
to: points.collarTip,
x: points.rollLineStart.x - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.collarTip,
y: points.collarTip.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.cfNeck,
y: points.collarTip.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.rollLineEnd,
y: points.collarTip.y - sa - 45
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.neck,
y: points.neck.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.armholePitch,
y: points.neck.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.shoulder,
y: points.neck.y - sa - 45
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.armhole,
y: points.neck.y - sa - 60
});
})
}
}
return part;
return part
}

View file

@ -1,56 +1,56 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import buttons from "@freesewing/plugin-buttons";
import bust from "@freesewing/plugin-bust";
import Bent from "@freesewing/bent";
import Carlton from "@freesewing/carlton";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import buttons from '@freesewing/plugin-buttons'
import bust from '@freesewing/plugin-bust'
import Bent from '@freesewing/bent'
import Carlton from '@freesewing/carlton'
import config from '../config'
// Parts
import draftFront from "./front";
import draftSide from "./side";
import draftFront from './front'
import draftSide from './side'
// Create new design
const Pattern = new freesewing.Design(config, [plugins, buttons, bust]);
const Pattern = new freesewing.Design(config, [plugins, buttons, bust])
let fromBent = ["Base", "Front", "Back", "Sleeve", "TopSleeve", "UnderSleeve"];
let fromBent = ['Base', 'Front', 'Back', 'Sleeve', 'TopSleeve', 'UnderSleeve']
// Attach draft methods from Bent to prototype
for (let m of fromBent) {
Pattern.prototype["draftBent" + m] = function(part) {
return new Bent(this.settings)["draft" + m](part);
};
Pattern.prototype['draftBent' + m] = function(part) {
return new Bent(this.settings)['draft' + m](part)
}
}
// Attach draft methods from Carlton to prototype
for (let m of [
"draftBack",
"draftTail",
"draftTopSleeve",
"draftUnderSleeve",
"draftBelt",
"draftCollarStand",
"draftCollar",
"draftCuffFacing",
"draftPocket",
"draftPocketFlap",
"draftPocketLining",
"draftChestPocketWelt",
"draftChestPocketBag",
"draftInnerPocketWelt",
"draftInnerPocketBag",
"draftInnerPocketTab"
'draftBack',
'draftTail',
'draftTopSleeve',
'draftUnderSleeve',
'draftBelt',
'draftCollarStand',
'draftCollar',
'draftCuffFacing',
'draftPocket',
'draftPocketFlap',
'draftPocketLining',
'draftChestPocketWelt',
'draftChestPocketBag',
'draftInnerPocketWelt',
'draftInnerPocketBag',
'draftInnerPocketTab'
]) {
Pattern.prototype[m] = function(part) {
return new Carlton(this.settings)[m](part);
};
return new Carlton(this.settings)[m](part)
}
}
Pattern.prototype.draftCarltonFront = function(part) {
return new Carlton(this.settings).draftFront(part);
};
return new Carlton(this.settings).draftFront(part)
}
// Attach own draft methods to prototype
Pattern.prototype.draftFront = draftFront;
Pattern.prototype.draftSide = draftSide;
Pattern.prototype.draftFront = draftFront
Pattern.prototype.draftSide = draftSide
export default Pattern;
export default Pattern

View file

@ -11,14 +11,14 @@ export default function(part) {
Point,
paths,
Path
} = part.shorthand();
} = part.shorthand()
// Give points their original names
for (let i of store.get("side")) points[i] = points[i + "Rot2"].clone();
for (let i of store.get('side')) points[i] = points[i + 'Rot2'].clone()
// Clean up
for (let i in paths) delete paths[i];
for (let i in snippets) delete snippets[i];
for (let i in paths) delete paths[i]
for (let i in snippets) delete snippets[i]
paths.saBase = new Path()
.move(points.hem)
@ -29,34 +29,31 @@ export default function(part) {
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
._curve(points.bustPointCp1, points.bustPoint)
.curve(points.bustPointCp2, points.psWaistCp1, points.psWaist)
.line(points.psHem);
.line(points.psHem)
paths.seam = paths.saBase
.clone()
.line(points.hem)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
points.title = points.bustPoint.shiftFractionTowards(points.waist, 0.5);
macro("title", {
points.title = points.bustPoint.shiftFractionTowards(points.waist, 0.5)
macro('title', {
at: points.title,
nr: "1b",
title: "side"
});
nr: '1b',
title: 'side'
})
points.logo = points.psHem.shiftFractionTowards(points.seat, 0.5);
snippets.logo = new Snippet("logo", points.logo);
points.logo = points.psHem.shiftFractionTowards(points.seat, 0.5)
snippets.logo = new Snippet('logo', points.logo)
points.grainlineFrom = points.psHem.shiftFractionTowards(points.hem, 0.5);
points.grainlineTo = new Point(
points.grainlineFrom.x,
points.armholePitchCp1.y
);
macro("grainline", {
points.grainlineFrom = points.psHem.shiftFractionTowards(points.hem, 0.5)
points.grainlineTo = new Point(points.grainlineFrom.x, points.armholePitchCp1.y)
macro('grainline', {
from: points.grainlineFrom,
to: points.grainlineTo
});
snippets.bust = new Snippet("notch", points.bustPoint);
})
snippets.bust = new Snippet('notch', points.bustPoint)
if (sa) {
paths.sa = paths.saBase
@ -64,66 +61,66 @@ export default function(part) {
.line(points.psHem.shift(-90, 3 * sa).shift(180, sa))
.line(points.hem.shift(-90, 3 * sa).shift(0, sa))
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
if (paperless) {
macro("vd", {
macro('vd', {
from: points.psHem,
to: points.psWaist,
x: points.psWaist.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.psHem,
to: points.bustPoint,
x: points.bustPoint.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.seat,
x: points.hem.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.waist,
x: points.hem.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.armhole,
x: points.hem.x + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.armholePitch,
x: points.hem.x + sa + 60
});
macro("hd", {
})
macro('hd', {
from: points.psWaist,
to: points.waist
});
macro("hd", {
})
macro('hd', {
from: points.bustPoint,
to: points.waist,
y: points.bustPoint.y
});
macro("hd", {
})
macro('hd', {
from: points.bustPoint,
to: points.armholePitch,
y: points.armholePitch.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.bustPoint,
to: points.armhole,
y: points.armholePitch.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.psHem,
to: points.hem,
y: points.hem.y + 3 * sa + 15
});
})
}
}
return part;
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,57 +1,68 @@
import { calculateRatios } from "./shared";
import { calculateRatios } from './shared'
export default function(part) {
let { paperless, sa, snippets, Snippet, store, complete, points, measurements, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
snippets,
Snippet,
store,
complete,
points,
measurements,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
calculateRatios(part);
calculateRatios(part)
// Belt width
let bw = measurements.centerBackNeckToWaist * options.beltWidth;
store.set("beltWidth", bw);
let bw = measurements.centerBackNeckToWaist * options.beltWidth
store.set('beltWidth', bw)
// Box pleat (bp)
points.bpStart = new Point(0, points.armholePitch.y);
points.bpStart = new Point(0, points.armholePitch.y)
points.bpTop = new Point(
measurements.chestCircumference * options.backPleat * -1,
points.armholePitch.y
);
points.bpBottom = new Point(
points.bpTop.x,
points.cbWaist.y - bw/2
);
points.bpTriangleEdge = points.bpStart.shift(0, points.bpTop.dx(points.bpStart)*0.6);
points.bpTriangleTip = points.bpStart.shift(90, points.bpStart.dx(points.bpTriangleEdge));
)
points.bpBottom = new Point(points.bpTop.x, points.cbWaist.y - bw / 2)
points.bpTriangleEdge = points.bpStart.shift(0, points.bpTop.dx(points.bpStart) * 0.6)
points.bpTriangleTip = points.bpStart.shift(90, points.bpStart.dx(points.bpTriangleEdge))
// Waist shaping
points.waist = new Point(
store.get("chest")/4 - store.get("waistReduction") / 8,
store.get('chest') / 4 - store.get('waistReduction') / 8,
points.bpBottom.y
);
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist)/3);
points.cbWaist = new Point(0, points.bpBottom.y);
)
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist) / 3)
points.cbWaist = new Point(0, points.bpBottom.y)
// Dart
points.dartCenter = points.cbWaist.shiftFractionTowards(points.waist, 0.4);
points.dartTip = points.dartCenter.shift(90, points.armhole.dy(points.dartCenter)*0.85);
points.dartRight = points.dartCenter.shift(0, store.get("waistReduction")/8);
points.dartLeft = points.dartRight.flipX(points.dartCenter);
points.dartLeftCp = points.dartLeft.shift(90, points.dartTip.dy(points.dartCenter)*0.6);
points.dartRightCp = points.dartLeftCp.flipX(points.dartCenter);
points.dartCenter = points.cbWaist.shiftFractionTowards(points.waist, 0.4)
points.dartTip = points.dartCenter.shift(90, points.armhole.dy(points.dartCenter) * 0.85)
points.dartRight = points.dartCenter.shift(0, store.get('waistReduction') / 8)
points.dartLeft = points.dartRight.flipX(points.dartCenter)
points.dartLeftCp = points.dartLeft.shift(90, points.dartTip.dy(points.dartCenter) * 0.6)
points.dartRightCp = points.dartLeftCp.flipX(points.dartCenter)
store.set("cbToDart", points.dartLeft.x);
store.set("dartToSide", points.dartRight.dx(points.waist));
store.set('cbToDart', points.dartLeft.x)
store.set('dartToSide', points.dartRight.dx(points.waist))
// Back stay (bs)
points.bsCp1 = points.bpStart.shiftFractionTowards(points.armholePitch, 0.5);
points.bsCp2 = points.armhole.shiftFractionTowards(points.cbArmhole, 0.3);
points.bsCp1 = points.bpStart.shiftFractionTowards(points.armholePitch, 0.5)
points.bsCp2 = points.armhole.shiftFractionTowards(points.cbArmhole, 0.3)
// Store collar length
store.set(
"backCollarLength",
'backCollarLength',
new Path()
.move(points.cbNeck)
._curve(points.neckCp2, points.neck)
.length()
);
)
// Clean up
for (let i in paths) delete paths[i]
@ -79,154 +90,147 @@ export default function(part) {
.join(paths.dart)
.join(paths.seam2)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.backStay = new Path()
.move(points.bpStart)
.curve(points.bsCp1, points.bsCp2, points.armhole)
.attr("class", "canvas lashed");
.attr('class', 'canvas lashed')
paths.triangle = new Path()
.move(points.bpTriangleTip)
.line(points.bpTriangleEdge)
.line(points.bpStart)
.attr("class", "dashed");
.attr('class', 'dashed')
if (complete) {
macro("sprinkle", {
snippet: "notch",
on: [
"armholePitch",
"bpTriangleTip"
]
});
macro('sprinkle', {
snippet: 'notch',
on: ['armholePitch', 'bpTriangleTip']
})
macro("grainline", {
macro('grainline', {
from: points.cbWaist,
to: points.bpStart
});
})
points.logo = new Point(
points.armhole.x * 0.7,
points.dartTip.y
);
snippets.logo = new Snippet("logo", points.logo);
points.logo = new Point(points.armhole.x * 0.7, points.dartTip.y)
snippets.logo = new Snippet('logo', points.logo)
if (sa) {
paths.sa =
paths.seam1
paths.sa = paths.seam1
.line(points.waist)
.offset(sa)
.join(paths.seam2.offset(sa))
.close()
.trim()
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
if (paperless) {
macro("hd", {
macro('hd', {
from: points.bpBottom,
to: points.cbWaist,
y: points.cbWaist.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.cbWaist,
to: points.dartLeft,
y: points.cbWaist.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.dartLeft,
to: points.dartRight,
y: points.cbWaist.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.dartRight,
to: points.waist,
y: points.cbWaist.y + 15 + sa
});
macro("hd", {
})
macro('hd', {
from: points.cbWaist,
to: points.waist,
y: points.cbWaist.y + 30 + sa
});
macro("hd", {
})
macro('hd', {
from: points.bpBottom,
to: points.waist,
y: points.cbWaist.y + 45 + sa
});
macro("vd", {
})
macro('vd', {
from: points.waist,
to: points.armhole,
x: points.armhole.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.armhole,
to: points.armholePitch,
x: points.armhole.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.armhole,
to: points.shoulder,
x: points.armhole.x + 30 + sa
});
macro("vd", {
})
macro('vd', {
from: points.waist,
to: points.shoulder,
x: points.armhole.x + 45 + sa
});
macro("vd", {
})
macro('vd', {
from: points.dartRight,
to: points.dartTip,
x: points.dartRight.x + 15
});
macro("vd", {
})
macro('vd', {
from: points.bpBottom,
to: points.bpTop,
x: points.bpTop.x - 15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.bpTop,
to: points.cbNeck,
x: points.bpTop.x - 15 - sa
});
macro("vd", {
})
macro('vd', {
from: points.bpBottom,
to: points.neck,
x: points.bpTop.x - 30 - sa
});
macro("vd", {
})
macro('vd', {
from: points.bpStart,
to: points.bpTriangleTip,
x: points.bpTriangleEdge.x + 15
});
macro("hd", {
})
macro('hd', {
from: points.bpStart,
to: points.bpTriangleEdge,
y: points.bpTriangleEdge.y + 15
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.neck,
y: points.neck.y - 15 - sa
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.armholePitch,
y: points.neck.y - 30 - sa
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.shoulder,
y: points.neck.y - 45 - sa
});
macro("hd", {
})
macro('hd', {
from: points.cbNeck,
to: points.armhole,
y: points.neck.y - 60 - sa
});
})
}
}
return part;
return part
}

View file

@ -1,30 +1,44 @@
export default function(part) {
let { paperless, sa, snippets, Snippet, store, complete, points, measurements, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
snippets,
Snippet,
store,
complete,
points,
measurements,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
let length = 1.6 * (store.get("cbToDart") + store.get("dartToSide"));
let width = measurements.centerBackNeckToWaist * options.beltWidth;
let length = 1.6 * (store.get('cbToDart') + store.get('dartToSide'))
let width = measurements.centerBackNeckToWaist * options.beltWidth
points.topLeft = new Point(0, 0);
points.topRight = new Point(length, 0);
points.bottomLeft = new Point(0, width);
points.bottomRight = new Point(length, width);
points.button = new Point(width/2, width/2);
macro("round", {
points.topLeft = new Point(0, 0)
points.topRight = new Point(length, 0)
points.bottomLeft = new Point(0, width)
points.bottomRight = new Point(length, width)
points.button = new Point(width / 2, width / 2)
macro('round', {
from: points.topRight,
to: points.bottomLeft,
via: points.topLeft,
prefix: "roundTop",
radius: width/4,
prefix: 'roundTop',
radius: width / 4,
render: true
});
macro("round", {
})
macro('round', {
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
prefix: "roundBottom",
radius: width/4,
prefix: 'roundBottom',
radius: width / 4,
render: true
});
})
// Paths
paths.seam = new Path()
@ -36,50 +50,44 @@ export default function(part) {
.line(points.topRight)
.line(points.roundTopStart)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
snippets.button = new Snippet("button", points.button).attr("data-scale", 2);
points.title = new Point(
points.bottomRight.x/2,
points.bottomRight.y/2
);
macro("title", {
snippets.button = new Snippet('button', points.button).attr('data-scale', 2)
points.title = new Point(points.bottomRight.x / 2, points.bottomRight.y / 2)
macro('title', {
at: points.title,
nr: 6,
title: "belt"
});
points.logo = new Point(
points.bottomRight.x * 0.75,
points.bottomRight.y * 0.65
);
snippets.logo = new Snippet("logo", points.logo);
title: 'belt'
})
points.logo = new Point(points.bottomRight.x * 0.75, points.bottomRight.y * 0.65)
snippets.logo = new Snippet('logo', points.logo)
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("hd", {
macro('hd', {
from: points.roundBottomStart,
to: points.roundBottomEnd,
y: points.roundBottomEnd.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.roundBottomStart,
to: points.button,
y: points.roundBottomEnd.y + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.roundBottomStart,
to: points.bottomRight,
y: points.roundBottomEnd.y + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
})
}
}
return part;
return part
}

View file

@ -10,28 +10,19 @@ export default function(part) {
Point,
paths,
Path
} = part.shorthand();
} = part.shorthand()
points.topLeft = new Point(0, 0);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(
store.get("chestPocketHeight"),
store.get("chestPocketBagDepth") / 2
);
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y);
points.topRight = new Point(points.bottomRight.x, points.topLeft.y);
points.startLeft = points.topLeft.shiftFractionTowards(
points.bottomLeft,
0.33
);
points.endLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.66);
points.startRight = points.topRight.shiftFractionTowards(
points.bottomRight,
0.33
);
points.endRight = points.topRight.shiftFractionTowards(
points.bottomRight,
0.66
);
store.get('chestPocketHeight'),
store.get('chestPocketBagDepth') / 2
)
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
points.startLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.33)
points.endLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.66)
points.startRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.33)
points.endRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.66)
paths.seam = new Path()
.move(points.startRight)
@ -42,45 +33,45 @@ export default function(part) {
.line(points.bottomLeft)
.line(points.bottomRight)
.line(points.endRight)
.attr("class", "lining");
.attr('class', 'lining')
paths.hint = new Path()
.move(points.startLeft)
.line(points.endLeft)
.move(points.endRight)
.line(points.startRight)
.attr("class", "lining dashed");
.attr('class', 'lining dashed')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 17,
title: "chestPocketBag"
});
title: 'chestPocketBag'
})
macro("grainline", {
macro('grainline', {
from: points.bottomLeft.shift(0, 10),
to: points.topLeft.shift(0, 10)
});
})
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "lining sa");
paths.sa = paths.seam.offset(sa).attr('class', 'lining sa')
}
macro("ld", {
macro('ld', {
from: points.bottomRight.shift(180, 15),
to: points.topRight.shift(180, 15),
text: units(store.get("chestPocketBagDepth") * 2)
});
text: units(store.get('chestPocketBagDepth') * 2)
})
if (paperless) {
macro("hd", {
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + sa + 15
});
})
}
}
return part;
return part
}

View file

@ -1,27 +1,12 @@
export default function(part) {
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand();
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand()
points.topLeft = new Point(0, 0);
points.bottomRight = new Point(
store.get("chestPocketWidth") * 2,
store.get("chestPocketHeight")
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.topMid = new Point(
store.get("chestPocketWidth"),
points.topRight.y
);
points.bottomMid = new Point(
points.topMid.x,
points.bottomRight.y
);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(store.get('chestPocketWidth') * 2, store.get('chestPocketHeight'))
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
points.topMid = new Point(store.get('chestPocketWidth'), points.topRight.y)
points.bottomMid = new Point(points.topMid.x, points.bottomRight.y)
paths.seam = new Path()
.move(points.topLeft)
@ -30,39 +15,36 @@ export default function(part) {
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.fold = new Path()
.move(points.topMid)
.line(points.bottomMid)
.attr("class", "dashed");
.attr('class', 'dashed')
if (complete) {
points.title = new Point(
points.bottomRight.x/4,
points.bottomRight.y/2,
);
macro("title", {
points.title = new Point(points.bottomRight.x / 4, points.bottomRight.y / 2)
macro('title', {
at: points.title,
nr: 12,
title: "chestPocketWelt"
});
title: 'chestPocketWelt'
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("hd", {
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
})
}
}
return part;
return part
}

View file

@ -5,74 +5,72 @@
*/
export default function(part) {
let { paperless, sa, complete, points, options, macro, paths, Path } = part.shorthand();
let { paperless, sa, complete, points, options, macro, paths, Path } = part.shorthand()
// We're going to slash and spread this collar. Slashing first:
// Divide top in 5 parts
points.cutTop1 = points.topLeft.shiftFractionTowards(points.topRight, 0.2);
points.cutTop2 = points.topLeft.shiftFractionTowards(points.topRight, 0.4);
points.cutTop3 = points.topLeft.shiftFractionTowards(points.topRight, 0.6);
points.cutTop4 = points.topLeft.shiftFractionTowards(points.topRight, 0.8);
points.cutTop1 = points.topLeft.shiftFractionTowards(points.topRight, 0.2)
points.cutTop2 = points.topLeft.shiftFractionTowards(points.topRight, 0.4)
points.cutTop3 = points.topLeft.shiftFractionTowards(points.topRight, 0.6)
points.cutTop4 = points.topLeft.shiftFractionTowards(points.topRight, 0.8)
// Divide bottom in 4 parts
let bottom = new Path()
.move(points.standTop)
.curve_(points.standTopCp, points.standTip)
points.cutBottom1 = bottom.shiftFractionAlong(0.25);
points.cutBottom2 = bottom.shiftFractionAlong(0.5);
points.cutBottom3 = bottom.shiftFractionAlong(0.75);
let bottom = new Path().move(points.standTop).curve_(points.standTopCp, points.standTip)
points.cutBottom1 = bottom.shiftFractionAlong(0.25)
points.cutBottom2 = bottom.shiftFractionAlong(0.5)
points.cutBottom3 = bottom.shiftFractionAlong(0.75)
// Split curve, extract control points from ops
let halves = bottom.split(points.cutBottom2);
let quarters = [];
quarters.push(...halves[0].split(points.cutBottom1));
quarters.push(...halves[1].split(points.cutBottom3));
points.q1Cp1 = quarters[0].ops[1].cp1;
points.q1Cp2 = quarters[0].ops[1].cp2;
points.q2Cp1 = quarters[1].ops[1].cp1;
points.q2Cp2 = quarters[1].ops[1].cp2;
points.q3Cp1 = quarters[2].ops[1].cp1;
points.q3Cp2 = quarters[2].ops[1].cp2;
points.q4Cp1 = quarters[3].ops[1].cp1;
points.q4Cp2 = quarters[3].ops[1].cp2;
let halves = bottom.split(points.cutBottom2)
let quarters = []
quarters.push(...halves[0].split(points.cutBottom1))
quarters.push(...halves[1].split(points.cutBottom3))
points.q1Cp1 = quarters[0].ops[1].cp1
points.q1Cp2 = quarters[0].ops[1].cp2
points.q2Cp1 = quarters[1].ops[1].cp1
points.q2Cp2 = quarters[1].ops[1].cp2
points.q3Cp1 = quarters[2].ops[1].cp1
points.q3Cp2 = quarters[2].ops[1].cp2
points.q4Cp1 = quarters[3].ops[1].cp1
points.q4Cp2 = quarters[3].ops[1].cp2
// Collar slashed, not let's spread by rotating
let rotate = {
1: {
pivot: "cutBottom1",
points: ["cutBottom2", "cutTop1", "cutTop2", "q2Cp1", "q2Cp2"]
pivot: 'cutBottom1',
points: ['cutBottom2', 'cutTop1', 'cutTop2', 'q2Cp1', 'q2Cp2']
},
2: {
pivot: "cutBottom2",
points: ["cutBottom3", "cutTop2", "cutTop3", "q3Cp1", "q3Cp2"]
pivot: 'cutBottom2',
points: ['cutBottom3', 'cutTop2', 'cutTop3', 'q3Cp1', 'q3Cp2']
},
3: {
pivot: "cutBottom3",
points: ["standTip", "bottomRight", "cutTop4", "cutTop3", "q4Cp1"]
pivot: 'cutBottom3',
points: ['standTip', 'bottomRight', 'cutTop4', 'cutTop3', 'q4Cp1']
},
4: {
pivot: "standTip",
points: ["topRight", "bottomRight", "cutTop4"]
},
};
let angle = -1 * options.collarSpread;
let alsoRotate = [];
for (let nr of [4,3,2,1]) {
let step = rotate[nr];
let pivot = step.pivot;
let first = false;
for (let pnt of step.points) {
if(first === false) first = pnt;
let id = `rot${nr}${pnt}`;
points[id] = points[pnt].rotate(angle, points[pivot]);
alsoRotate.push(id);
pivot: 'standTip',
points: ['topRight', 'bottomRight', 'cutTop4']
}
if(nr <4) for (let pnt of alsoRotate) points[pnt] = points[pnt].rotate(angle, points[pivot]);
}
let angle = -1 * options.collarSpread
let alsoRotate = []
for (let nr of [4, 3, 2, 1]) {
let step = rotate[nr]
let pivot = step.pivot
let first = false
for (let pnt of step.points) {
if (first === false) first = pnt
let id = `rot${nr}${pnt}`
points[id] = points[pnt].rotate(angle, points[pivot])
alsoRotate.push(id)
}
if (nr < 4) for (let pnt of alsoRotate) points[pnt] = points[pnt].rotate(angle, points[pivot])
}
// Shift panel 2 in place
angle = points.cutBottom2.angle(points.rot1cutBottom2) + 180;
let distance = -1 * points.cutBottom2.dist(points.rot1cutBottom2);
angle = points.cutBottom2.angle(points.rot1cutBottom2) + 180
let distance = -1 * points.cutBottom2.dist(points.rot1cutBottom2)
for (let i of [
'cutBottom2',
'rot2cutTop2',
@ -80,31 +78,23 @@ export default function(part) {
'rot2cutBottom3',
'rot2q3Cp1',
'rot2q3Cp2'
]) points[i] = points[i].shift(angle, distance);
])
points[i] = points[i].shift(angle, distance)
// Shift panel 3 in place
angle = points.cutBottom3.angle(points.rot2cutBottom3) + 180;
distance = -1 * points.cutBottom3.dist(points.rot2cutBottom3);
for (let i of [
'cutBottom3',
'rot3cutTop3',
'rot3cutTop4',
'rot3standTip',
'rot3q4Cp1',
]) points[i] = points[i].shift(angle, distance);
angle = points.cutBottom3.angle(points.rot2cutBottom3) + 180
distance = -1 * points.cutBottom3.dist(points.rot2cutBottom3)
for (let i of ['cutBottom3', 'rot3cutTop3', 'rot3cutTop4', 'rot3standTip', 'rot3q4Cp1'])
points[i] = points[i].shift(angle, distance)
// Shift panel 4 in place
angle = points.standTip.angle(points.rot3standTip) + 180;
distance = -1 * points.standTip.dist(points.rot3standTip);
for (let i of [
'standTip',
'rot4cutTop4',
'rot4topRight',
'rot4bottomRight'
]) points[i] = points[i].shift(angle, distance);
angle = points.standTip.angle(points.rot3standTip) + 180
distance = -1 * points.standTip.dist(points.rot3standTip)
for (let i of ['standTip', 'rot4cutTop4', 'rot4topRight', 'rot4bottomRight'])
points[i] = points[i].shift(angle, distance)
// Top control point
points.topLeftCp = points.topLeft.shift(0, points.rot4topRight.x * 0.6);
points.topLeftCp = points.topLeft.shift(0, points.rot4topRight.x * 0.6)
// Paths
/* Uncomment these paths to gain insight into what's happening here
@ -159,7 +149,6 @@ export default function(part) {
.attr("class", "dashed");
*/
paths.saBase = new Path()
.move(points.standTop)
/** This is the non-slashed path. We use this instead of the slashed
@ -175,82 +164,83 @@ export default function(part) {
//.curve_(points.rot3q4Cp1, points.rot3standTip)
.line(points.rot4bottomRight)
.line(points.rot4topRight)
._curve(points.topLeftCp, points.topLeft);
paths.seam = paths.saBase.clone()
._curve(points.topLeftCp, points.topLeft)
paths.seam = paths.saBase
.clone()
.line(points.standTop)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
points.title = points.standTopCp.clone();
macro("title", {
points.title = points.standTopCp.clone()
macro('title', {
at: points.title,
nr: 8,
title: "collar"
});
title: 'collar'
})
macro("grainline", {
macro('grainline', {
from: points.standTop.shift(0, 10),
to: points.topLeft.shift(0, 10)
});
})
if (sa) {
paths.sa = paths.saBase.offset(sa);
paths.sa = paths.saBase.offset(sa)
paths.sa = paths.sa
.line(points.topLeft)
.move(points.standTop)
.line(paths.sa.start())
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
if (paperless) {
macro("hd", {
macro('hd', {
from: points.standTop,
to: points.rot3standTip,
y: points.rot4bottomRight.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.standTop,
to: points.rot4bottomRight,
y: points.rot4bottomRight.y + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.standTop,
to: points.rot4topRight,
y: points.rot4bottomRight.y + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.standTop,
to: points.topLeft,
x: points.topLeft.x - 15
});
macro("vd", {
})
macro('vd', {
from: points.rot3standTip,
to: points.topLeft,
x: points.topLeft.x - 30
});
macro("vd", {
})
macro('vd', {
from: points.rot4topRight,
to: points.topLeft,
x: points.rot4topRight.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.rot4bottomRight,
to: points.topLeft,
x: points.rot4topRight.x + sa + 30
});
macro("ld", {
})
macro('ld', {
from: points.rot4bottomRight,
to: points.rot4topRight,
d: -1*sa - 15
});
macro("ld", {
d: -1 * sa - 15
})
macro('ld', {
from: points.rot3standTip,
to: points.rot4bottomRight,
d: -1*sa - 15
});
d: -1 * sa - 15
})
}
}
return part;
return part
}

View file

@ -1,20 +1,35 @@
export default function(part) {
let { paperless, sa, store, complete, points, measurements, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
measurements,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
let height = measurements.chestCircumference * options.collarHeight;
let length = store.get("frontCollarLength") + store.get("backCollarLength");
points.topLeft = new Point(0, 0);
points.bottomLeft = new Point(0, height);
points.topRight = new Point(length, height * -1 * options.collarFlare);
let height = measurements.chestCircumference * options.collarHeight
let length = store.get('frontCollarLength') + store.get('backCollarLength')
points.topLeft = new Point(0, 0)
points.bottomLeft = new Point(0, height)
points.topRight = new Point(length, height * -1 * options.collarFlare)
points.bottomRight = new Point(length, height)
points.bottomLeftCp = points.bottomLeft.shift(0, points.bottomRight.x * 0.4);
points.standTop = points.bottomLeft.shiftFractionTowards(points.topLeft, 0.25);
points.standTip = new Point(points.topRight.x * 0.75, points.bottomLeft.y + points.topRight.x/8.5);
points.standTipCp = points.standTip.shift(180, points.standTop.dy(points.bottomLeft));
points.standTopCp = points.standTop.shift(0, points.standTip.x * 0.9);
points.bottomLeftCp = points.bottomLeft.shift(0, points.bottomRight.x * 0.4)
points.standTop = points.bottomLeft.shiftFractionTowards(points.topLeft, 0.25)
points.standTip = new Point(
points.topRight.x * 0.75,
points.bottomLeft.y + points.topRight.x / 8.5
)
points.standTipCp = points.standTip.shift(180, points.standTop.dy(points.bottomLeft))
points.standTopCp = points.standTop.shift(0, points.standTip.x * 0.9)
for (let i of ["standTopCp", "standTip", "standTipCp", "bottomLeftCp"]) {
points[i+"Left"] = points[i].flipX();
for (let i of ['standTopCp', 'standTip', 'standTipCp', 'bottomLeftCp']) {
points[i + 'Left'] = points[i].flipX()
}
paths.seam = new Path()
@ -24,41 +39,41 @@ export default function(part) {
.curve_(points.standTopCpLeft, points.standTipLeft)
.curve(points.standTipCpLeft, points.bottomLeftCpLeft, points.bottomLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
points.title = points.bottomLeftCp.clone();
macro("title", {
points.title = points.bottomLeftCp.clone()
macro('title', {
at: points.title,
nr: 7,
title: "collarStand"
});
title: 'collarStand'
})
macro("grainline", {
macro('grainline', {
from: points.bottomLeft,
to: points.standTop
});
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("hd", {
macro('hd', {
from: points.standTipLeft,
to: points.standTip,
y: points.standTip.y + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.bottomLeft,
to: points.standTop,
x: points.standTip.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.standTip,
to: points.standTop,
x: points.standTip.x + sa + 30
});
})
}
}
return part;
return part
}

View file

@ -1,33 +1,27 @@
export default function(part) {
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand();
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand()
points.topLeft = new Point(0, 0);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(
store.get("topCuffWidth") + store.get("underCuffWidth"),
store.get("cuffLength") * 1.5
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
macro("round", {
store.get('topCuffWidth') + store.get('underCuffWidth'),
store.get('cuffLength') * 1.5
)
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
macro('round', {
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: store.get("cuffRadius"),
prefix: "roundLeft"
});
macro("round", {
radius: store.get('cuffRadius'),
prefix: 'roundLeft'
})
macro('round', {
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: store.get("cuffRadius"),
prefix: "roundRight"
});
radius: store.get('cuffRadius'),
prefix: 'roundRight'
})
paths.seam = new Path()
.move(points.topLeft)
@ -38,47 +32,46 @@ export default function(part) {
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 9,
title: "cuffFacing"
});
title: 'cuffFacing'
})
macro("grainline", {
from: points.bottomLeft.shift(0, 10+store.get("cuffRadius")),
to: points.topLeft.shift(0, 10+store.get("cuffRadius")),
});
macro('grainline', {
from: points.bottomLeft.shift(0, 10 + store.get('cuffRadius')),
to: points.topLeft.shift(0, 10 + store.get('cuffRadius'))
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("vd", {
macro('vd', {
from: points.roundRightStart,
to: points.roundRightEnd,
x: points.topRight.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.roundRightStart,
to: points.topRight,
x: points.topRight.x + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.roundRightStart,
to: points.roundRightEnd,
y: points.bottomRight.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.roundLeftStart,
to: points.roundRightEnd,
y: points.bottomRight.y + sa + 30
});
})
}
}
return part;
return part
}

View file

@ -1,164 +1,170 @@
import { calculateRatios } from "./shared";
import { calculateRatios } from './shared'
export default function(part) {
let { paperless, sa, snippets, Snippet, utils, store, complete, points, measurements, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
snippets,
Snippet,
utils,
store,
complete,
points,
measurements,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
calculateRatios(part);
calculateRatios(part)
// Waist shaping
points.waist = points.cfWaist.shift(0, store.get("chest")/4 - store.get("waistReduction")/8);
points.waistCp1 = points.waist.shift(-90, points.waist.dy(points.hips)/2);
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist)/2);
points.waist = points.cfWaist.shift(0, store.get('chest') / 4 - store.get('waistReduction') / 8)
points.waistCp1 = points.waist.shift(-90, points.waist.dy(points.hips) / 2)
points.waistCp2 = points.waist.shift(90, points.armhole.dy(points.waist) / 2)
// Seat shaping
points.cfSeat = points.cfWaist.shift(-90, measurements.naturalWaistToSeat);
points.seat = points.cfSeat.shift(0, store.get("seat")/4);
points.seatCp2 = points.seat.shift(90, points.waist.dy(points.seat)/3);
points.cfSeat = points.cfWaist.shift(-90, measurements.naturalWaistToSeat)
points.seat = points.cfSeat.shift(0, store.get('seat') / 4)
points.seatCp2 = points.seat.shift(90, points.waist.dy(points.seat) / 3)
// Hem length
points.cfHem = points.cfWaist.shift(-90, measurements.naturalWaistToFloor * options.length);
points.hem = new Point(
points.seat.x,
points.cfHem.y
);
store.set("waistToHem", points.cfHem.y - points.waist.y);
points.cfHem = points.cfWaist.shift(-90, measurements.naturalWaistToFloor * options.length)
points.hem = new Point(points.seat.x, points.cfHem.y)
store.set('waistToHem', points.cfHem.y - points.waist.y)
// Buttonline
let buttonW = points.waist.x * options.buttonSpacingHorizontal;
let buttonH = points.waist.dy(points.hips) / 1.5;
points.button1Left = points.cfHips.shift(180, buttonW / 2);
points.button1Right = points.cfHips.shift(0, buttonW / 2);
points.button2Left = points.button1Left.shift(90, buttonH);
points.button2Right = points.button2Left.shift(0, buttonW);
points.button3Left = points.button2Left.shift(90, buttonH);
points.button3Right = points.button3Left.shift(0, buttonW);
let buttonW = points.waist.x * options.buttonSpacingHorizontal
let buttonH = points.waist.dy(points.hips) / 1.5
points.button1Left = points.cfHips.shift(180, buttonW / 2)
points.button1Right = points.cfHips.shift(0, buttonW / 2)
points.button2Left = points.button1Left.shift(90, buttonH)
points.button2Right = points.button2Left.shift(0, buttonW)
points.button3Left = points.button2Left.shift(90, buttonH)
points.button3Right = points.button3Left.shift(0, buttonW)
// Front closure edge
points.collarEdge = new Point(
points.button1Left.x - measurements.naturalWaist * options.frontOverlap,
points.cfNeck.y
);
points.hemEdge = new Point(
points.collarEdge.x,
points.hem.y
);
)
points.hemEdge = new Point(points.collarEdge.x, points.hem.y)
// Collar
points.collarTip = points.collarEdge.shiftFractionTowards(points.cfNeck, options.lapelReduction);
points.lapelStraightEnd = new Point(
points.collarEdge.x,
points.armhole.y
);
points.lapelStraightEndCp1 = points.lapelStraightEnd.shiftFractionTowards(points.collarEdge, 0.7);
points.collarTip = points.collarEdge.shiftFractionTowards(points.cfNeck, options.lapelReduction)
points.lapelStraightEnd = new Point(points.collarEdge.x, points.armhole.y)
points.lapelStraightEndCp1 = points.lapelStraightEnd.shiftFractionTowards(points.collarEdge, 0.7)
// Pocket
points.pocketTopLeft = new Point(
points.button1Right.x + points.button1Right.dx(points.hips) * options.pocketPlacementHorizontal,
points.button1Right.y + points.button1Right.dy(points.button3Right) * options.pocketPlacementVertical
);
let pocketWidth = points.button1Right.dx(points.hips) * options.pocketWidth;
let pocketHeight = pocketWidth * (1 + options.pocketHeight);
points.pocketTopRight = points.pocketTopLeft.shift(0, pocketWidth);
points.pocketBottomLeft = points.pocketTopLeft.shift(-90, pocketHeight);
points.pocketBottomRight = points.pocketTopRight.shift(-90, pocketHeight);
points.button1Right.y +
points.button1Right.dy(points.button3Right) * options.pocketPlacementVertical
)
let pocketWidth = points.button1Right.dx(points.hips) * options.pocketWidth
let pocketHeight = pocketWidth * (1 + options.pocketHeight)
points.pocketTopRight = points.pocketTopLeft.shift(0, pocketWidth)
points.pocketBottomLeft = points.pocketTopLeft.shift(-90, pocketHeight)
points.pocketBottomRight = points.pocketTopRight.shift(-90, pocketHeight)
if (options.pocketRadius > 0) {
let radius = pocketWidth * options.pocketRadius;
macro("round", {
let radius = pocketWidth * options.pocketRadius
macro('round', {
from: points.pocketTopLeft,
to: points.pocketBottomRight,
via: points.pocketBottomLeft,
prefix: "pocketRoundLeft",
prefix: 'pocketRoundLeft',
radius
});
macro("round", {
})
macro('round', {
from: points.pocketBottomLeft,
to: points.pocketTopRight,
via: points.pocketBottomRight,
prefix: "pocketRoundRight",
prefix: 'pocketRoundRight',
radius
});
store.set("pocketRadius", radius);
})
store.set('pocketRadius', radius)
}
store.set("pocketWidth", pocketWidth);
store.set("pocketHeight", pocketHeight);
store.set('pocketWidth', pocketWidth)
store.set('pocketHeight', pocketHeight)
// Pocket flap
points.pocketFlapMid = points.pocketTopLeft.shift(0, pocketWidth/2);
let pocketFlapHeight = pocketHeight * 0.3;
store.set("pocketFlapHeight", pocketFlapHeight);
points.pocketFlapMid = points.pocketTopLeft.shift(0, pocketWidth / 2)
let pocketFlapHeight = pocketHeight * 0.3
store.set('pocketFlapHeight', pocketFlapHeight)
points.pocketFlapTopLeft = new Point(
points.pocketTopLeft.x - pocketWidth * 0.005,
points.pocketTopLeft.y - pocketFlapHeight / 4
);
)
points.pocketFlapBottomLeft = new Point(
points.pocketFlapTopLeft.x,
points.pocketTopLeft.y + pocketFlapHeight * 0.75
);
points.pocketFlapTopRight = points.pocketFlapTopLeft.flipX(points.pocketFlapMid);
points.pocketFlapBottomRight = points.pocketFlapBottomLeft.flipX(points.pocketFlapMid);
)
points.pocketFlapTopRight = points.pocketFlapTopLeft.flipX(points.pocketFlapMid)
points.pocketFlapBottomRight = points.pocketFlapBottomLeft.flipX(points.pocketFlapMid)
if (options.pocketFlapRadius > 0) {
let radius = pocketWidth * options.pocketFlapRadius;
macro("round", {
let radius = pocketWidth * options.pocketFlapRadius
macro('round', {
from: points.pocketFlapTopLeft,
to: points.pocketFlapBottomRight,
via: points.pocketFlapBottomLeft,
prefix: "pocketFlapRoundLeft",
radius,
});
macro("round", {
prefix: 'pocketFlapRoundLeft',
radius
})
macro('round', {
from: points.pocketFlapBottomLeft,
to: points.pocketFlapTopRight,
via: points.pocketFlapBottomRight,
prefix: "pocketFlapRoundRight",
radius,
});
store.set("pocketFlapRadius", radius);
prefix: 'pocketFlapRoundRight',
radius
})
store.set('pocketFlapRadius', radius)
}
// Chest pocket
points.chestPocketAnchor = new Point(
points.waist.x * options.chestPocketPlacement,
points.button2Right.shiftFractionTowards(points.button3Right, 0.2).y
);
let chestPocketHeight = points.armhole.dy(points.chestPocketAnchor) * options.chestPocketHeight;
let chestPocketWidth = chestPocketHeight * options.chestPocketWidth;
store.set("chestPocketHeight", chestPocketHeight);
store.set("chestPocketWidth", chestPocketWidth);
points.chestPocketBottomLeft = points.chestPocketAnchor.shift(180, chestPocketWidth / 2);
points.chestPocketTopLeft = points.chestPocketBottomLeft.shift(90, chestPocketHeight);
points.chestPocketBottomRight = points.chestPocketBottomLeft.flipX(points.chestPocketAnchor);
points.chestPocketTopRight = points.chestPocketTopLeft.flipX(points.chestPocketAnchor);
)
let chestPocketHeight = points.armhole.dy(points.chestPocketAnchor) * options.chestPocketHeight
let chestPocketWidth = chestPocketHeight * options.chestPocketWidth
store.set('chestPocketHeight', chestPocketHeight)
store.set('chestPocketWidth', chestPocketWidth)
points.chestPocketBottomLeft = points.chestPocketAnchor.shift(180, chestPocketWidth / 2)
points.chestPocketTopLeft = points.chestPocketBottomLeft.shift(90, chestPocketHeight)
points.chestPocketBottomRight = points.chestPocketBottomLeft.flipX(points.chestPocketAnchor)
points.chestPocketTopRight = points.chestPocketTopLeft.flipX(points.chestPocketAnchor)
for (let i of [
"chestPocketTopLeft",
"chestPocketBottomLeft",
"chestPocketTopRight",
"chestPocketBottomRight"]) points[i] = points[i].rotate(options.chestPocketAngle, points.chestPocketAnchor);
store.set("chestPocketBagDepth", points.button3Left.dx(points.chestPocketBottomLeft));
'chestPocketTopLeft',
'chestPocketBottomLeft',
'chestPocketTopRight',
'chestPocketBottomRight'
])
points[i] = points[i].rotate(options.chestPocketAngle, points.chestPocketAnchor)
store.set('chestPocketBagDepth', points.button3Left.dx(points.chestPocketBottomLeft))
// Inner pocket
points.innerPocketAnchor = new Point(
points.waist.x * options.innerPocketPlacement,
points.button2Right.shiftFractionTowards(points.button3Right, 1.5).y
);
let innerPocketWidth = points.waist.x * options.innerPocketWidth;
let weltHeight = innerPocketWidth * options.innerPocketWeltHeight;
store.set("innerPocketWeltHeight", weltHeight);
store.set("innerPocketWidth", innerPocketWidth);
points.innerPocketTop = points.innerPocketAnchor.shift(90, weltHeight);
points.innerPocketBottom = points.innerPocketAnchor.shift(-90, weltHeight);
points.innerPocketLeft = points.innerPocketAnchor.shift(180, innerPocketWidth/2);
points.innerPocketRight = points.innerPocketLeft.flipX(points.innerPocketAnchor);
points.innerPocketTopLeft = points.innerPocketLeft.shift(90, weltHeight);
points.innerPocketTopRight = points.innerPocketTopLeft.flipX(points.innerPocketAnchor);
points.innerPocketBottomLeft = points.innerPocketLeft.shift(-90, weltHeight);
points.innerPocketBottomRight = points.innerPocketBottomLeft.flipX(points.innerPocketAnchor);
)
let innerPocketWidth = points.waist.x * options.innerPocketWidth
let weltHeight = innerPocketWidth * options.innerPocketWeltHeight
store.set('innerPocketWeltHeight', weltHeight)
store.set('innerPocketWidth', innerPocketWidth)
points.innerPocketTop = points.innerPocketAnchor.shift(90, weltHeight)
points.innerPocketBottom = points.innerPocketAnchor.shift(-90, weltHeight)
points.innerPocketLeft = points.innerPocketAnchor.shift(180, innerPocketWidth / 2)
points.innerPocketRight = points.innerPocketLeft.flipX(points.innerPocketAnchor)
points.innerPocketTopLeft = points.innerPocketLeft.shift(90, weltHeight)
points.innerPocketTopRight = points.innerPocketTopLeft.flipX(points.innerPocketAnchor)
points.innerPocketBottomLeft = points.innerPocketLeft.shift(-90, weltHeight)
points.innerPocketBottomRight = points.innerPocketBottomLeft.flipX(points.innerPocketAnchor)
// Roll line
points.rollLineEdge = points.shoulder.shiftFractionTowards(points.neck, 1.15);
points.rollLineStart = new Point(
points.collarEdge.x,
points.button3Left.y
);
points.rollLineEdge = points.shoulder.shiftFractionTowards(points.neck, 1.15)
points.rollLineStart = new Point(points.collarEdge.x, points.button3Left.y)
points.rollLineEnd = utils.lineIntersectsCurve(
points.rollLineStart,
points.rollLineEdge,
@ -166,39 +172,33 @@ export default function(part) {
points.cfNeckCp1,
points.neckCp2Front,
points.neck
);
)
// Facing/Lining border (flb)
points.flbX = points.button1Right.shift(0, points.button1Right.dx(points.pocketTopLeft)/2);
points.flbHem = new Point(points.flbX.x, points.hemEdge.y);
if (points.flbHem.x <= points.cfNeck.x)
points.flbTop = new Point(points.flbX.x, points.cfNeck.y);
points.flbX = points.button1Right.shift(0, points.button1Right.dx(points.pocketTopLeft) / 2)
points.flbHem = new Point(points.flbX.x, points.hemEdge.y)
if (points.flbHem.x <= points.cfNeck.x) points.flbTop = new Point(points.flbX.x, points.cfNeck.y)
else if (points.flbHem.x < points.neck.x)
points.flbTop = utils.lineIntersectsCurve(
points.flbHem,
points.flbX.shift(90,points.flbHem.y * 2),
points.flbX.shift(90, points.flbHem.y * 2),
points.cfNeck,
points.cfNeckCp1,
points.neckCp2Front,
points.neck
);
)
else if (points.flbHem.x < points.shoulder.x)
points.flbTop = utils.beamsIntersect(
points.flbHem,
points.flbX,
points.neck,
points.shoulder
);
else throw new Error("Could not find intersection of facing/lining boundary with neckline");
points.flbTop = utils.beamsIntersect(points.flbHem, points.flbX, points.neck, points.shoulder)
else throw new Error('Could not find intersection of facing/lining boundary with neckline')
// Store collar length
store.set(
"frontCollarLength",
'frontCollarLength',
new Path()
.move(points.cfNeck)
.curve(points.cfNeckCp1, points.neckCp2Front, points.neck)
.length()
);
)
// Clean up
for (let i in paths) delete paths[i]
@ -218,33 +218,31 @@ export default function(part) {
.line(points.collarTip)
._curve(points.lapelStraightEndCp1, points.lapelStraightEnd)
.line(points.hemEdge)
.line(points.flbHem);
paths.hemBase = new Path()
.move(points.flbHem)
.line(points.hem);
paths.saBase.render = false;
paths.hemBase.render = false;
.line(points.flbHem)
paths.hemBase = new Path().move(points.flbHem).line(points.hem)
paths.saBase.render = false
paths.hemBase.render = false
paths.seam = paths.saBase
.join(paths.hemBase)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.rollLine = new Path()
.move(points.rollLineStart)
.line(points.rollLineEnd)
.attr("class", "lashed");
.attr('class', 'lashed')
paths.chestPiece = new Path()
.move(points.rollLineStart)
.curve(points.button3Right, points.waistCp2, points.armhole)
.attr("class", "canvas lashed");
.attr('class', 'canvas lashed')
paths.flb = new Path()
.move(points.flbHem)
.line(points.flbTop)
.attr("class", "lining lashed");
.attr('class', 'lining lashed')
paths.pocket = new Path().move(points.pocketTopLeft);
paths.pocket = new Path().move(points.pocketTopLeft)
if (options.pocketRadius > 0) {
paths.pocket = paths.pocket
.line(points.pocketRoundLeftStart)
@ -252,33 +250,39 @@ export default function(part) {
.line(points.pocketRoundRightStart)
.curve(points.pocketRoundRightCp1, points.pocketRoundRightCp2, points.pocketRoundRightEnd)
} else {
paths.pocket = paths.pocket
.line(points.pocketBottomLeft)
.line(points.pocketBottomRight)
paths.pocket = paths.pocket.line(points.pocketBottomLeft).line(points.pocketBottomRight)
}
paths.pocket = paths.pocket
.line(points.pocketTopRight)
.line(points.pocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
paths.pocketFlap = new Path().move(points.pocketFlapTopLeft);
paths.pocketFlap = new Path().move(points.pocketFlapTopLeft)
if (options.pocketFlapRadius > 0) {
paths.pocketFlap = paths.pocketFlap
.line(points.pocketFlapRoundLeftStart)
.curve(points.pocketFlapRoundLeftCp1, points.pocketFlapRoundLeftCp2, points.pocketFlapRoundLeftEnd)
.curve(
points.pocketFlapRoundLeftCp1,
points.pocketFlapRoundLeftCp2,
points.pocketFlapRoundLeftEnd
)
.line(points.pocketFlapRoundRightStart)
.curve(points.pocketFlapRoundRightCp1, points.pocketFlapRoundRightCp2, points.pocketFlapRoundRightEnd)
.curve(
points.pocketFlapRoundRightCp1,
points.pocketFlapRoundRightCp2,
points.pocketFlapRoundRightEnd
)
} else {
paths.pocketFlap = paths.pocketFlap
.line(points.pocketFlapBottomLeft)
.line(points.pocketFlapBottomRight);
.line(points.pocketFlapBottomRight)
}
paths.pocketFlap = paths.pocketFlap
.line(points.pocketFlapTopRight)
.line(points.pocketFlapTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
paths.chestPocket = new Path()
.move(points.chestPocketTopLeft)
@ -287,7 +291,7 @@ export default function(part) {
.line(points.chestPocketTopRight)
.line(points.chestPocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
paths.innerPocket = new Path()
.move(points.innerPocketTopLeft)
@ -296,190 +300,180 @@ export default function(part) {
.line(points.innerPocketTopRight)
.line(points.innerPocketTopLeft)
.close()
.attr("class", "fabric help");
.attr('class', 'fabric help')
if (complete) {
snippets.button1Left = new Snippet("button", points.button1Left).attr("data-scale", 2);
snippets.button1Right = new Snippet("button", points.button1Right).attr("data-scale", 2);
snippets.button2Left = new Snippet("button", points.button2Left).attr("data-scale", 2);
snippets.button2Right = new Snippet("button", points.button2Right).attr("data-scale", 2);
snippets.button3Left = new Snippet("button", points.button3Left).attr("data-scale", 2);
snippets.button3Right = new Snippet("button", points.button3Right).attr("data-scale", 2);
snippets.button1Left = new Snippet('button', points.button1Left).attr('data-scale', 2)
snippets.button1Right = new Snippet('button', points.button1Right).attr('data-scale', 2)
snippets.button2Left = new Snippet('button', points.button2Left).attr('data-scale', 2)
snippets.button2Right = new Snippet('button', points.button2Right).attr('data-scale', 2)
snippets.button3Left = new Snippet('button', points.button3Left).attr('data-scale', 2)
snippets.button3Right = new Snippet('button', points.button3Right).attr('data-scale', 2)
macro("sprinkle", {
snippet: "notch",
on: [
"armholePitch",
"cfNeck",
"rollLineStart",
"waist",
"seat"
]
});
macro('sprinkle', {
snippet: 'notch',
on: ['armholePitch', 'cfNeck', 'rollLineStart', 'waist', 'seat']
})
points.logo = new Point(
points.chestPocketTopRight.x,
points.armhole.y
);
snippets.logo = new Snippet("logo", points.logo);
points.logo = new Point(points.chestPocketTopRight.x, points.armhole.y)
snippets.logo = new Snippet('logo', points.logo)
macro("grainline", {
macro('grainline', {
from: points.cfHem,
to: points.cfNeck
});
})
if (sa) {
paths.sa = paths.saBase
.offset(sa)
.join(paths.hemBase.offset(sa*3))
.join(paths.hemBase.offset(sa * 3))
.close()
.attr("class", "fabric sa");
.attr('class', 'fabric sa')
}
if (paperless) {
macro("ld", {
macro('ld', {
from: points.hemEdge,
to: points.flbHem,
d: 15
});
macro("ld", {
})
macro('ld', {
from: points.flbHem,
to: points.hem,
d: 15
});
macro("hd", {
})
macro('hd', {
from: points.hemEdge,
to: points.hem,
y: points.hem.y + 15 + 3*sa
});
macro("hd", {
y: points.hem.y + 15 + 3 * sa
})
macro('hd', {
from: points.rollLineStart,
to: points.pocketTopLeft,
y: points.pocketFlapBottomLeft.y
});
macro("vd", {
})
macro('vd', {
from: points.pocketFlapTopRight,
to: points.waist,
x: points.pocketTopRight.x - 15
});
macro("vd", {
})
macro('vd', {
from: points.pocketTopRight,
to: points.waist,
x: points.pocketTopRight.x - 30
});
macro("vd", {
})
macro('vd', {
from: points.chestPocketBottomLeft,
to: points.waist,
x: points.chestPocketBottomLeft.x - 15
});
macro("hd", {
})
macro('hd', {
from: points.rollLineStart,
to: points.chestPocketBottomLeft,
y: points.chestPocketBottomLeft.y + 15
});
macro("hd", {
})
macro('hd', {
from: points.rollLineStart,
to: points.button3Left,
y: points.button3Left.y + 15
});
macro("hd", {
})
macro('hd', {
from: points.button3Left,
to: points.button3Right,
y: points.button3Left.y + 15
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.seat,
x: points.hem.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.waist,
x: points.hem.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.hem,
to: points.armhole,
x: points.hem.x + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.armhole,
to: points.armholePitch,
x: points.armhole.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.armhole,
to: points.shoulder,
x: points.armhole.x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.armhole,
to: points.neck,
x: points.armhole.x + sa + 45
});
macro("vd", {
})
macro('vd', {
from: points.rollLineStart,
to: points.collarTip,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.button2Left,
to: points.rollLineStart,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.button1Left,
to: points.button2Left,
x: points.rollLineStart.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hemEdge,
to: points.collarTip,
x: points.rollLineStart.x - sa - 30
});
macro("vd", {
})
macro('vd', {
from: points.hemEdge,
to: points.neck,
x: points.rollLineStart.x - sa - 45
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.collarTip,
y: points.collarTip.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.cfNeck,
y: points.collarTip.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.rollLineEnd,
y: points.collarTip.y - sa - 45
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.neck,
y: points.neck.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.armholePitch,
y: points.neck.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.shoulder,
y: points.neck.y - sa - 45
});
macro("hd", {
})
macro('hd', {
from: points.lapelStraightEnd,
to: points.armhole,
y: points.neck.y - sa - 60
});
})
}
}
return part;
return part
}

View file

@ -1,67 +1,67 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import buttons from "@freesewing/plugin-buttons";
import Bent from "@freesewing/bent";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import buttons from '@freesewing/plugin-buttons'
import Bent from '@freesewing/bent'
import config from '../config'
// Parts
import draftFront from "./front";
import draftBack from "./back";
import draftTail from "./tail";
import draftTopSleeve from "./topsleeve";
import draftUnderSleeve from "./undersleeve";
import draftBelt from "./belt";
import draftCollarStand from "./collarstand";
import draftCollar from "./collar";
import draftCuffFacing from "./cufffacing";
import draftPocket from "./pocket";
import draftPocketFlap from "./pocketflap";
import draftPocketLining from "./pocketlining";
import draftChestPocketWelt from "./chestpocketwelt";
import draftChestPocketBag from "./chestpocketbag";
import draftInnerPocketWelt from "./innerpocketwelt";
import draftInnerPocketBag from "./innerpocketbag";
import draftInnerPocketTab from "./innerpockettab";
import draftFront from './front'
import draftBack from './back'
import draftTail from './tail'
import draftTopSleeve from './topsleeve'
import draftUnderSleeve from './undersleeve'
import draftBelt from './belt'
import draftCollarStand from './collarstand'
import draftCollar from './collar'
import draftCuffFacing from './cufffacing'
import draftPocket from './pocket'
import draftPocketFlap from './pocketflap'
import draftPocketLining from './pocketlining'
import draftChestPocketWelt from './chestpocketwelt'
import draftChestPocketBag from './chestpocketbag'
import draftInnerPocketWelt from './innerpocketwelt'
import draftInnerPocketBag from './innerpocketbag'
import draftInnerPocketTab from './innerpockettab'
// Create new design
const Pattern = new freesewing.Design(config, [plugins, buttons]);
const Pattern = new freesewing.Design(config, [plugins, buttons])
// Attach draft methods from Bent to prototype
Pattern.prototype.draftBentBase = function(part) {
return new Bent(this.settings).draftBase(part);
};
return new Bent(this.settings).draftBase(part)
}
Pattern.prototype.draftBentFront = function(part) {
return new Bent(this.settings).draftFront(part);
};
return new Bent(this.settings).draftFront(part)
}
Pattern.prototype.draftBentBack = function(part) {
return new Bent(this.settings).draftBack(part);
};
return new Bent(this.settings).draftBack(part)
}
Pattern.prototype.draftBentSleeve = function(part) {
return new Bent(this.settings).draftSleeve(part);
};
return new Bent(this.settings).draftSleeve(part)
}
Pattern.prototype.draftBentTopSleeve = function(part) {
return new Bent(this.settings).draftTopSleeve(part);
};
return new Bent(this.settings).draftTopSleeve(part)
}
Pattern.prototype.draftBentUnderSleeve = function(part) {
return new Bent(this.settings).draftUnderSleeve(part);
};
return new Bent(this.settings).draftUnderSleeve(part)
}
// Attach own draft methods to prototype
Pattern.prototype.draftFront = draftFront;
Pattern.prototype.draftBack = draftBack;
Pattern.prototype.draftTail = draftTail;
Pattern.prototype.draftTopSleeve = draftTopSleeve;
Pattern.prototype.draftUnderSleeve = draftUnderSleeve;
Pattern.prototype.draftBelt = draftBelt;
Pattern.prototype.draftCollarStand = draftCollarStand;
Pattern.prototype.draftCollar = draftCollar;
Pattern.prototype.draftCuffFacing = draftCuffFacing;
Pattern.prototype.draftPocket = draftPocket;
Pattern.prototype.draftPocketFlap = draftPocketFlap;
Pattern.prototype.draftPocketLining = draftPocketLining;
Pattern.prototype.draftChestPocketWelt = draftChestPocketWelt;
Pattern.prototype.draftChestPocketBag = draftChestPocketBag;
Pattern.prototype.draftInnerPocketWelt = draftInnerPocketWelt;
Pattern.prototype.draftInnerPocketBag = draftInnerPocketBag;
Pattern.prototype.draftInnerPocketTab = draftInnerPocketTab;
Pattern.prototype.draftFront = draftFront
Pattern.prototype.draftBack = draftBack
Pattern.prototype.draftTail = draftTail
Pattern.prototype.draftTopSleeve = draftTopSleeve
Pattern.prototype.draftUnderSleeve = draftUnderSleeve
Pattern.prototype.draftBelt = draftBelt
Pattern.prototype.draftCollarStand = draftCollarStand
Pattern.prototype.draftCollar = draftCollar
Pattern.prototype.draftCuffFacing = draftCuffFacing
Pattern.prototype.draftPocket = draftPocket
Pattern.prototype.draftPocketFlap = draftPocketFlap
Pattern.prototype.draftPocketLining = draftPocketLining
Pattern.prototype.draftChestPocketWelt = draftChestPocketWelt
Pattern.prototype.draftChestPocketBag = draftChestPocketBag
Pattern.prototype.draftInnerPocketWelt = draftInnerPocketWelt
Pattern.prototype.draftInnerPocketBag = draftInnerPocketBag
Pattern.prototype.draftInnerPocketTab = draftInnerPocketTab
export default Pattern;
export default Pattern

View file

@ -1,23 +1,29 @@
export default function(part) {
let { units, paperless, sa, store, complete, points, options, macro, Point, paths, Path } = part.shorthand();
let {
units,
paperless,
sa,
store,
complete,
points,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
points.topLeft = new Point(0, 0);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(
store.get("innerPocketWidth"),
store.get("innerPocketWidth") * options.innerPocketDepth / 2
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.startLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.33);
points.endLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.66);
points.startRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.33);
points.endRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.66);
store.get('innerPocketWidth'),
(store.get('innerPocketWidth') * options.innerPocketDepth) / 2
)
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
points.startLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.33)
points.endLeft = points.topLeft.shiftFractionTowards(points.bottomLeft, 0.66)
points.startRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.33)
points.endRight = points.topRight.shiftFractionTowards(points.bottomRight, 0.66)
paths.seam = new Path()
.move(points.startRight)
@ -28,46 +34,45 @@ export default function(part) {
.line(points.bottomLeft)
.line(points.bottomRight)
.line(points.endRight)
.attr("class", "lining");
.attr('class', 'lining')
paths.hint = new Path()
.move(points.startLeft)
.line(points.endLeft)
.move(points.endRight)
.line(points.startRight)
.attr("class", "lining dashed");
.attr('class', 'lining dashed')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 14,
title: "innerPocketBag"
});
title: 'innerPocketBag'
})
macro("grainline", {
macro('grainline', {
from: points.bottomLeft.shift(0, 10),
to: points.topLeft.shift(0, 10)
});
})
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "lining sa");
paths.sa = paths.seam.offset(sa).attr('class', 'lining sa')
}
macro("ld", {
macro('ld', {
from: points.bottomRight.shift(180, 15),
to: points.topRight.shift(180, 15),
text: units(store.get("innerPocketWidth") * options.innerPocketDepth * 2)
});
text: units(store.get('innerPocketWidth') * options.innerPocketDepth * 2)
})
if (paperless) {
macro("hd", {
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + sa + 15
});
})
}
}
return part;
return part
}

View file

@ -1,19 +1,13 @@
export default function(part) {
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand();
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand()
points.topLeft = new Point(0, 0);
points.topRight = new Point(
store.get("innerPocketWidth") * 1.2,
0
);
points.topLeft = new Point(0, 0)
points.topRight = new Point(store.get('innerPocketWidth') * 1.2, 0)
points.bottom = new Point(
store.get("innerPocketWidth") * 0.6,
store.get("innerPocketWidth") * 0.6,
);
points.top = new Point(
store.get("innerPocketWidth") * 0.6,
0
);
store.get('innerPocketWidth') * 0.6,
store.get('innerPocketWidth') * 0.6
)
points.top = new Point(store.get('innerPocketWidth') * 0.6, 0)
paths.seam = new Path()
.move(points.topLeft)
@ -21,46 +15,46 @@ export default function(part) {
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "lining");
.attr('class', 'lining')
paths.hint = new Path()
.move(points.top)
.line(points.bottom)
.attr("class", "lining dashed");
.attr('class', 'lining dashed')
if (complete) {
points.title = points.top.shiftFractionTowards(points.bottom, 0.5);
macro("title", {
points.title = points.top.shiftFractionTowards(points.bottom, 0.5)
macro('title', {
at: points.title,
nr: 15,
title: "innerPocketTab"
});
title: 'innerPocketTab'
})
macro("grainline", {
macro('grainline', {
from: points.top,
to: points.top.shift(-45, points.top.x*0.7)
});
to: points.top.shift(-45, points.top.x * 0.7)
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "lining sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'lining sa')
if (paperless) {
macro("hd", {
macro('hd', {
from: points.topLeft,
to: points.top,
y: points.topLeft.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.topLeft,
to: points.topRight,
y: points.topLeft.y - sa - 30
});
macro("vd", {
})
macro('vd', {
from: points.bottom,
to: points.topRight,
x: points.topRight.x + sa + 15
});
})
}
}
return part;
return part
}

View file

@ -1,37 +1,22 @@
export default function(part) {
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand();
let { paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand()
points.topLeft = new Point(0, 0);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(
store.get("innerPocketWidth") * 1.4,
store.get("innerPocketWeltHeight") * 6
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.leftMid = new Point(0, points.bottomRight.y / 2);
points.rightMid = new Point(points.bottomRight.x, points.bottomRight.y / 2);
store.get('innerPocketWidth') * 1.4,
store.get('innerPocketWeltHeight') * 6
)
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
points.leftMid = new Point(0, points.bottomRight.y / 2)
points.rightMid = new Point(points.bottomRight.x, points.bottomRight.y / 2)
points.realTopLeft = new Point(
store.get("innerPocketWidth") * 0.2,
store.get("innerPocketWeltHeight") * 2
);
points.realTopRight = new Point(
store.get("innerPocketWidth") * 1.2,
points.realTopLeft.y
);
points.realBottomLeft = new Point(
points.realTopLeft.x,
store.get("innerPocketWeltHeight") * 4
);
points.realBottomRight = new Point(
points.realTopRight.x,
points.realBottomLeft.y
);
store.get('innerPocketWidth') * 0.2,
store.get('innerPocketWeltHeight') * 2
)
points.realTopRight = new Point(store.get('innerPocketWidth') * 1.2, points.realTopLeft.y)
points.realBottomLeft = new Point(points.realTopLeft.x, store.get('innerPocketWeltHeight') * 4)
points.realBottomRight = new Point(points.realTopRight.x, points.realBottomLeft.y)
paths.seam = new Path()
.move(points.topLeft)
@ -40,12 +25,12 @@ export default function(part) {
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.fold = new Path()
.move(points.leftMid)
.line(points.rightMid)
.attr("class", "dashed");
.attr('class', 'dashed')
paths.welt = new Path()
.move(points.realTopLeft)
@ -54,45 +39,45 @@ export default function(part) {
.line(points.realTopRight)
.line(points.realTopLeft)
.close()
.attr("class", "lashed");
.attr('class', 'lashed')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 13,
title: "innerPocketWelt"
});
title: 'innerPocketWelt'
})
macro("grainline", {
macro('grainline', {
from: points.bottomLeft.shift(0, 10),
to: points.topLeft.shift(0, 10)
});
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("vd", {
macro('vd', {
from: points.realBottomRight,
to: points.realTopRight,
x: points.topRight.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.realBottomLeft,
to: points.realBottomRight,
y: points.bottomLeft.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomLeft.y + sa + 30
});
})
}
}
return part;
return part
}

View file

@ -1,39 +1,38 @@
export default function(part) {
let { paperless, sa, store, complete, points, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
points.topLeft = new Point(0, 0);
points.bottomRight = new Point(
store.get("pocketWidth"),
store.get("pocketHeight")
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.edgeLeft = points.bottomLeft.shiftFractionTowards(points.topLeft, 1.25);
points.edgeRight = new Point(
points.topRight.x,
points.edgeLeft.y
);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(store.get('pocketWidth'), store.get('pocketHeight'))
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
points.edgeLeft = points.bottomLeft.shiftFractionTowards(points.topLeft, 1.25)
points.edgeRight = new Point(points.topRight.x, points.edgeLeft.y)
if (options.pocketRadius > 0) {
macro("round", {
macro('round', {
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: store.get("pocketRadius"),
prefix: "roundLeft"
});
macro("round", {
radius: store.get('pocketRadius'),
prefix: 'roundLeft'
})
macro('round', {
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: store.get("pocketRadius"),
prefix: "roundRight"
});
radius: store.get('pocketRadius'),
prefix: 'roundRight'
})
paths.seam = new Path()
.move(points.edgeLeft)
@ -45,60 +44,60 @@ export default function(part) {
paths.seam = new Path()
.move(points.edgeLeft)
.line(points.bottomLeft)
.line(points.bottomRight);
.line(points.bottomRight)
}
paths.seam = paths.seam
.line(points.edgeRight)
.line(points.edgeLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.fold = new Path()
.move(points.topLeft)
.line(points.topRight)
.attr("class", "fabric dashed");
.attr('class', 'fabric dashed')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 10,
title: "pocket"
});
title: 'pocket'
})
macro("grainline", {
from: points.bottomLeft.shift(0, 10+ (store.get("pocketRadius") || 0)),
to: points.edgeLeft.shift(0, 10+ (store.get("pocketRadius") || 0)),
});
macro('grainline', {
from: points.bottomLeft.shift(0, 10 + (store.get('pocketRadius') || 0)),
to: points.edgeLeft.shift(0, 10 + (store.get('pocketRadius') || 0))
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
if (paperless) {
macro("vd", {
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.bottomRight,
to: points.edgeRight,
x: points.topRight.x + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.edgeLeft,
to: points.edgeRight,
y: points.edgeRight.y - sa - 15
});
})
if (options.pocketRadius > 0) {
macro("hd", {
macro('hd', {
from: points.roundRightStart,
to: points.roundRightEnd,
y: points.bottomRight.y + sa + 15
});
})
}
}
}
return part;
return part
}

View file

@ -1,34 +1,36 @@
export default function(part) {
let { paperless, sa, store, complete, points, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
points.topLeft = new Point(0, 0);
points.bottomRight = new Point(
store.get("pocketWidth"),
store.get("pocketFlapHeight")
);
points.bottomLeft = new Point(
points.topLeft.x,
points.bottomRight.y
);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.topLeft = new Point(0, 0)
points.bottomRight = new Point(store.get('pocketWidth'), store.get('pocketFlapHeight'))
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
if (options.pocketFlapRadius > 0) {
macro("round", {
macro('round', {
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: store.get("pocketFlapRadius"),
prefix: "roundLeft"
});
macro("round", {
radius: store.get('pocketFlapRadius'),
prefix: 'roundLeft'
})
macro('round', {
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: store.get("pocketFlapRadius"),
prefix: "roundRight"
});
radius: store.get('pocketFlapRadius'),
prefix: 'roundRight'
})
paths.seam = new Path()
.move(points.topLeft)
@ -40,60 +42,58 @@ export default function(part) {
paths.seam = new Path()
.move(points.topLeft)
.line(points.bottomLeft)
.line(points.bottomRight);
.line(points.bottomRight)
}
paths.seam = paths.seam
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 11,
title: "pocketFlap"
});
title: 'pocketFlap'
})
macro("grainline", {
from: points.bottomLeft.shift(0, points.topRight.x/5 ),
to: points.topLeft.shift(0, points.topRight.x/5)
});
macro('grainline', {
from: points.bottomLeft.shift(0, points.topRight.x / 5),
to: points.topLeft.shift(0, points.topRight.x / 5)
})
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
}
if (paperless) {
macro("hd", {
macro('hd', {
from: points.topLeft,
to: points.topRight,
y: points.topLeft.y - sa - 15
});
})
if (options.pocketFlapRadius > 0) {
macro("vd", {
macro('vd', {
from: points.roundRightStart,
to: points.roundRightEnd,
x: points.topRight.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.roundRightStart,
to: points.topRight,
x: points.topRight.x + sa + 30
});
})
} else {
macro("vd", {
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
})
}
}
}
return part;
return part
}

View file

@ -1,26 +1,34 @@
export default function(part) {
let { paperless, sa, store, complete, points, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
points.topLeft = points.bottomLeft.shiftFractionTowards(points.topLeft, 0.75);
points.topRight = new Point(
points.bottomRight.x,
points.topLeft.y
);
points.topLeft = points.bottomLeft.shiftFractionTowards(points.topLeft, 0.75)
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
if (options.pocketRadius > 0) {
macro("round", {
macro('round', {
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: store.get("pocketRadius"),
prefix: "roundLeft"
});
macro("round", {
radius: store.get('pocketRadius'),
prefix: 'roundLeft'
})
macro('round', {
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: store.get("pocketRadius"),
prefix: "roundRight"
});
radius: store.get('pocketRadius'),
prefix: 'roundRight'
})
paths.seam = new Path()
.move(points.topLeft)
@ -32,52 +40,52 @@ export default function(part) {
paths.seam = new Path()
.move(points.topLeft)
.line(points.bottomLeft)
.line(points.bottomRight);
.line(points.bottomRight)
}
paths.seam = paths.seam
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "lining");
.attr('class', 'lining')
delete paths.fold;
delete paths.fold
if (complete) {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5);
macro("title", {
points.title = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
macro('title', {
at: points.title,
nr: 16,
title: "pocketLining"
});
title: 'pocketLining'
})
macro("grainline", {
from: points.bottomLeft.shift(0, 10+ (store.get("pocketRadius") || 0)),
to: points.topLeft.shift(0, 10+ (store.get("pocketRadius") || 0)),
});
macro('grainline', {
from: points.bottomLeft.shift(0, 10 + (store.get('pocketRadius') || 0)),
to: points.topLeft.shift(0, 10 + (store.get('pocketRadius') || 0))
})
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "lining sa");
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'lining sa')
if (paperless) {
macro("vd", {
macro('vd', {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.topLeft,
to: points.topRight,
y: points.topRight.y - sa - 15
});
})
if (options.pocketRadius > 0) {
macro("hd", {
macro('hd', {
from: points.roundRightStart,
to: points.roundRightEnd,
y: points.bottomRight.y + sa + 15
});
})
}
}
}
return part;
return part
}

View file

@ -2,14 +2,14 @@
* This calculates a bunch of helper variables and stores them
*/
export const calculateRatios = part => {
let { store, measurements, options } = part.shorthand();
let { store, measurements, options } = part.shorthand()
// Calculate different values for reducing from chest to hips via waist
store.set("chest", measurements.chestCircumference * (1 + options.chestEase));
store.set("waist", measurements.naturalWaist * (1 + options.waistEase));
store.set("hips", measurements.hipsCircumference * (1 + options.hipsEase));
store.set("seat", measurements.seatCircumference * (1 + options.seatEase));
store.set('chest', measurements.chestCircumference * (1 + options.chestEase))
store.set('waist', measurements.naturalWaist * (1 + options.waistEase))
store.set('hips', measurements.hipsCircumference * (1 + options.hipsEase))
store.set('seat', measurements.seatCircumference * (1 + options.seatEase))
store.set("waistReduction", store.get("chest") - store.get("waist"));
store.set("hipsReduction", store.get("chest") - store.get("hips"));
};
store.set('waistReduction', store.get('chest') - store.get('waist'))
store.set('hipsReduction', store.get('chest') - store.get('hips'))
}

View file

@ -1,24 +1,35 @@
export default function(part) {
let { units, paperless, sa, store, complete, points, macro, Point, paths, Path } = part.shorthand();
let {
units,
paperless,
sa,
store,
complete,
points,
macro,
Point,
paths,
Path
} = part.shorthand()
let length = store.get("waistToHem") - store.get("beltWidth")/2;
let length = store.get('waistToHem') - store.get('beltWidth') / 2
points.cbTop = new Point(0,0);
points.fold1Top = points.cbTop.shift(0, store.get("cbToDart")/2);
points.fold2Top = points.cbTop.shift(0, store.get("cbToDart"));
points.fold3Top = points.cbTop.shift(0, store.get("cbToDart")*2);
points.fold4Top = points.fold3Top.shift(0, store.get("cbToDart")/2);
points.waistTop = points.fold4Top.shift(0, store.get("dartToSide"));
points.cbTop = new Point(0, 0)
points.fold1Top = points.cbTop.shift(0, store.get('cbToDart') / 2)
points.fold2Top = points.cbTop.shift(0, store.get('cbToDart'))
points.fold3Top = points.cbTop.shift(0, store.get('cbToDart') * 2)
points.fold4Top = points.fold3Top.shift(0, store.get('cbToDart') / 2)
points.waistTop = points.fold4Top.shift(0, store.get('dartToSide'))
// 12cm will do as we're just drawing a rectangle.
// But check that lenght > 12cm because doll clothes.
let drawnLength = length < 120 ? length : 120;
let drawnLength = length < 120 ? length : 120
for (let i of ["cb", "fold1", "fold2", "fold3", "fold4", "waist"]) {
points[i+"Bottom"] = points[i+"Top"].shift(-90, drawnLength);
if (i === "cb" || i === "waist") {
points[i+"MidTop"] = points[i+"Top"].shift(-90, drawnLength * 0.4);
points[i+"MidBottom"] = points[i+"Top"].shift(-90, drawnLength * 0.6);
for (let i of ['cb', 'fold1', 'fold2', 'fold3', 'fold4', 'waist']) {
points[i + 'Bottom'] = points[i + 'Top'].shift(-90, drawnLength)
if (i === 'cb' || i === 'waist') {
points[i + 'MidTop'] = points[i + 'Top'].shift(-90, drawnLength * 0.4)
points[i + 'MidBottom'] = points[i + 'Top'].shift(-90, drawnLength * 0.6)
}
}
@ -32,7 +43,7 @@ export default function(part) {
.move(points.waistMidTop)
.line(points.waistTop)
.line(points.cbTop)
.attr("class", "fabric");
.attr('class', 'fabric')
paths.folds = new Path()
.move(points.fold1Top)
@ -43,69 +54,72 @@ export default function(part) {
.line(points.fold3Bottom)
.move(points.fold4Top)
.line(points.fold4Bottom)
.attr("class", "lashed");
.attr('class', 'lashed')
paths.hint = new Path()
.move(points.cbMidTop)
.line(points.cbMidBottom)
.move(points.waistMidBottom)
.line(points.waistMidTop)
.attr("class", "fabric dashed");
.attr('class', 'fabric dashed')
if (complete) {
points.title = points.fold4Top.shiftFractionTowards(points.waistBottom, 0.5);
macro("title", {
points.title = points.fold4Top.shiftFractionTowards(points.waistBottom, 0.5)
macro('title', {
at: points.title,
nr: 3,
title: "tail"
});
title: 'tail'
})
macro("grainline", {
macro('grainline', {
from: points.fold2Bottom.shift(0, 10),
to: points.fold2Top.shift(0, 10)
});
})
if (sa) paths.sa = paths.seam.offset(sa).close().attr("class", "fabric sa");
macro("vd", {
if (sa)
paths.sa = paths.seam
.offset(sa)
.close()
.attr('class', 'fabric sa')
macro('vd', {
from: points.fold4Bottom.shift(0, 15),
to: points.fold4Top.shift(0, 15),
text: units(length)
});
})
if (paperless) {
macro("hd", {
macro('hd', {
from: points.cbBottom,
to: points.fold1Bottom,
y: points.cbBottom.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.fold1Bottom,
to: points.fold2Bottom,
y: points.cbBottom.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.fold2Bottom,
to: points.fold3Bottom,
y: points.cbBottom.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.fold3Bottom,
to: points.fold4Bottom,
y: points.cbBottom.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.fold4Bottom,
to: points.waistBottom,
y: points.cbBottom.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.cbBottom,
to: points.waistBottom,
y: points.cbBottom.y + sa + 30
});
})
}
}
return part;
return part
}

View file

@ -1,25 +1,36 @@
export default function(part) {
let { paperless, sa, store, complete, points, measurements, options, macro, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
measurements,
options,
macro,
paths,
Path
} = part.shorthand()
// Add cuff
let length = measurements.shoulderToWrist * options.cuffLength;
let angle = points.tsWristRight.angle(points.tsWristLeft);
points.cuffBottomRight = points.tsWristRight.shift(angle+90, length);
points.cuffBottomLeft = points.tsWristLeft.shift(angle+90, length);
macro("round", {
let length = measurements.shoulderToWrist * options.cuffLength
let angle = points.tsWristRight.angle(points.tsWristLeft)
points.cuffBottomRight = points.tsWristRight.shift(angle + 90, length)
points.cuffBottomLeft = points.tsWristLeft.shift(angle + 90, length)
macro('round', {
to: points.tsWristRight,
from: points.cuffBottomLeft,
via: points.cuffBottomRight,
radius: length/3,
radius: length / 3,
render: true,
prefix: "round"
});
store.set("topCuffWidth", points.tsWristLeft.dist(points.tsWristRight));
store.set("cuffLength", length);
store.set("cuffRadius", length/3);
prefix: 'round'
})
store.set('topCuffWidth', points.tsWristLeft.dist(points.tsWristRight))
store.set('cuffLength', length)
store.set('cuffRadius', length / 3)
// Clean up
for (let i in paths) delete paths[i];
for (let i in paths) delete paths[i]
// Paths
paths.seam = new Path()
@ -37,90 +48,89 @@ export default function(part) {
.curve(points.topCpLeft, points.frontPitchPointCpTop, points.frontPitchPoint)
.curve(points.frontPitchPointCpBottom, points.tsLeftEdgeCpRight, points.tsLeftEdge)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
macro("grainline", {
macro('grainline', {
from: points.boxBottom,
to: points.top
});
})
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
}
if (paperless) {
macro("ld", {
macro('ld', {
from: points.tsWristLeft,
to: points.tsWristRight,
d: -15
});
macro("vd", {
})
macro('vd', {
from: points.tsWristLeft,
to: points.tsElbowLeft,
x: points.tsLeftEdge.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.tsWristLeft,
to: points.tsLeftEdge,
x: points.tsLeftEdge.x - sa - 30
});
macro("ld", {
})
macro('ld', {
from: points.cuffBottomLeft,
to: points.tsWristLeft,
d: 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.cuffBottomRight,
to: points.usWristRight,
x: points.usWristRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.elbowRight,
x: points.elbowRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.tsRightEdge,
x: points.elbowRight.x + 30 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.backPitchPoint,
x: points.elbowRight.x + 45 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.top,
x: points.elbowRight.x + 60 + sa
});
macro("ld", {
})
macro('ld', {
from: points.tsElbowLeft,
to: points.elbowRight
});
macro("ld", {
})
macro('ld', {
from: points.tsLeftEdge,
to: points.tsRightEdge
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.top,
y: points.top.y - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.backPitchPoint,
y: points.top.y - sa - 30
});
macro("hd", {
})
macro('hd', {
from: points.tsLeftEdge,
to: points.tsRightEdge,
y: points.top.y - sa - 45
});
})
}
}
return part;
return part
}

View file

@ -1,23 +1,35 @@
export default function(part) {
let { paperless, sa, store, complete, points, measurements, options, macro, Point, paths, Path } = part.shorthand();
let {
paperless,
sa,
store,
complete,
points,
measurements,
options,
macro,
Point,
paths,
Path
} = part.shorthand()
// Add cuff
let length = measurements.shoulderToWrist * options.cuffLength;
let angle = points.usWristRight.angle(points.usWristLeft);
points.cuffBottomRight = points.usWristRight.shift(angle+90, length);
points.cuffBottomLeft = points.usWristLeft.shift(angle+90, length);
macro("round", {
let length = measurements.shoulderToWrist * options.cuffLength
let angle = points.usWristRight.angle(points.usWristLeft)
points.cuffBottomRight = points.usWristRight.shift(angle + 90, length)
points.cuffBottomLeft = points.usWristLeft.shift(angle + 90, length)
macro('round', {
to: points.usWristRight,
from: points.cuffBottomLeft,
via: points.cuffBottomRight,
radius: length/3,
radius: length / 3,
render: true,
prefix: "round"
});
store.set("underCuffWidth", points.usWristLeft.dist(points.usWristRight));
prefix: 'round'
})
store.set('underCuffWidth', points.usWristLeft.dist(points.usWristRight))
// Clean up
for (let i in paths) delete paths[i];
for (let i in paths) delete paths[i]
// Paths
paths.seam = new Path()
@ -34,79 +46,75 @@ export default function(part) {
.curve(points.usTipCpBottom, points.usLeftEdgeCpRight, points.usLeftEdgeRight)
.line(points.usLeftEdge)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
if (complete) {
macro("grainline", {
macro('grainline', {
from: points.boxBottom,
to: new Point(
points.top.x,
points.usLeftEdge.y
)
});
to: new Point(points.top.x, points.usLeftEdge.y)
})
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
}
if (paperless) {
macro("ld", {
macro('ld', {
from: points.usWristLeft,
to: points.usWristRight,
d: -15
});
macro("vd", {
})
macro('vd', {
from: points.usWristLeft,
to: points.usElbowLeft,
x: points.usLeftEdge.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.usWristLeft,
to: points.usLeftEdge,
x: points.usLeftEdge.x - sa - 30
});
macro("ld", {
})
macro('ld', {
from: points.cuffBottomLeft,
to: points.usWristLeft,
d: 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.cuffBottomRight,
to: points.usWristRight,
x: points.usWristRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.elbowRight,
x: points.elbowRight.x + 15 + sa
});
macro("vd", {
})
macro('vd', {
from: points.usWristRight,
to: points.usTip,
x: points.elbowRight.x + 30 + sa
});
macro("ld", {
})
macro('ld', {
from: points.usElbowLeft,
to: points.elbowRight
});
macro("ld", {
})
macro('ld', {
from: points.usLeftEdge,
to: points.usRightEdge,
d: -15
});
macro("hd", {
})
macro('hd', {
from: points.usLeftEdge,
to: points.usTip,
y: points.usTip.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.usLeftEdge,
to: points.usTip,
x: points.usLeftEdge.x - sa - 15
});
})
}
}
return part;
return part
}

View file

@ -1,22 +1,15 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
return (
<Workbench
freesewing={freesewing}
Pattern={Pattern}
config={config}
userLanguage="en"
/>
);
};
let instance = new Pattern()
let config = instance.config
return <Workbench freesewing={freesewing} Pattern={Pattern} config={config} userLanguage="en" />
}
export default App;
export default App

View file

@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<App />, document.getElementById('root'))
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
serviceWorker.unregister()

View file

@ -9,46 +9,44 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
)
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://goo.gl/SC7cgQ"
);
});
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
});
})
}
}
@ -57,38 +55,38 @@ function registerValidSW(swUrl, config) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
console.log('New content is available; please refresh.')
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
config.onUpdate(registration)
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log("Content is cached for offline use.");
console.log('Content is cached for offline use.')
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
config.onSuccess(registration)
}
}
}
}
}
};
};
})
.catch(error => {
console.error("Error during service worker registration:", error);
});
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl, config) {
@ -98,30 +96,28 @@ function checkValidServiceWorker(swUrl, config) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get("content-type").indexOf("javascript") === -1
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
registerValidSW(swUrl, config)
}
})
.catch(() => {
console.log(
"No internet connection found. App is running in offline mode."
);
});
console.log('No internet connection found. App is running in offline mode.')
})
}
export function unregister() {
if ("serviceWorker" in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
registration.unregister()
})
}
}

View file

@ -1,47 +1,27 @@
export default function(part) {
let {
measurements,
options,
store,
points,
paths,
Point,
Path,
utils,
debug
} = part.shorthand();
let { measurements, options, store, points, paths, Point, Path, utils, debug } = part.shorthand()
// Where to divide our corset into panels
if (options.panels === 11) store.set("gaps", [0.15, 0.275, 0.4, 0.6, 0.75]);
else store.set("gaps", [0.2, 0.35, 0.5, 0.65, 0.8]);
if (options.panels === 11) store.set('gaps', [0.15, 0.275, 0.4, 0.6, 0.75])
else store.set('gaps', [0.2, 0.35, 0.5, 0.65, 0.8])
// Absolute values for some options
store.set(
"waistReduction",
measurements.naturalWaist * options.waistReduction
);
store.set('waistReduction', measurements.naturalWaist * options.waistReduction)
debug({
type: "info",
label: "✅ Waist reduction",
msg: utils.units(store.get("waistReduction"))
});
store.set("backOpening", measurements.underbust * options.backOpening);
type: 'info',
label: '✅ Waist reduction',
msg: utils.units(store.get('waistReduction'))
})
store.set('backOpening', measurements.underbust * options.backOpening)
debug({
type: "info",
label: "✅ Back opening",
msg: utils.units(store.get("backOpening"))
});
let len =
measurements.naturalWaistToUnderbust + measurements.naturalWaistToHip;
for (let option of [
"backRise",
"backDrop",
"frontRise",
"frontDrop",
"hipRise"
])
store.set(option, len * options[option]);
store.set("length", len);
type: 'info',
label: '✅ Back opening',
msg: utils.units(store.get('backOpening'))
})
let len = measurements.naturalWaistToUnderbust + measurements.naturalWaistToHip
for (let option of ['backRise', 'backDrop', 'frontRise', 'frontDrop', 'hipRise'])
store.set(option, len * options[option])
store.set('length', len)
/**
* How much should we take in the corset at waist and bust
@ -50,62 +30,47 @@ export default function(part) {
* Can I be sure? Maybe not, but a larger underbust than hip
* measurements seems very rare to say the least.
*/
store.set('width', 0.5 * (measurements.hipsCircumference - store.get('backOpening')))
store.set(
"width",
0.5 * (measurements.hipsCircumference - store.get("backOpening"))
);
store.set(
"waistIntake",
0.5 *
(measurements.hipsCircumference -
measurements.naturalWaist +
store.get("waistReduction"))
);
store.set(
"bustIntake",
0.5 * (measurements.hipsCircumference - measurements.underbust)
);
'waistIntake',
0.5 * (measurements.hipsCircumference - measurements.naturalWaist + store.get('waistReduction'))
)
store.set('bustIntake', 0.5 * (measurements.hipsCircumference - measurements.underbust))
// Basic box (CB = Center back, CF = Center front)
let wid = store.get("width");
points.underbustCF = new Point(0, 0);
points.hipsCF = new Point(0, len);
points.hipsCB = new Point(wid, len);
points.underbustCB = new Point(wid, 0);
points.topSide = points.underbustCF.shiftFractionTowards(
points.underbustCB,
0.5
);
points.bottomSide = points.hipsCF.shiftFractionTowards(points.hipsCB, 0.5);
points.waistCF = points.underbustCF.shift(
-90,
measurements.naturalWaistToUnderbust
);
points.waistCB = new Point(points.hipsCB.x, points.waistCF.y);
let wid = store.get('width')
points.underbustCF = new Point(0, 0)
points.hipsCF = new Point(0, len)
points.hipsCB = new Point(wid, len)
points.underbustCB = new Point(wid, 0)
points.topSide = points.underbustCF.shiftFractionTowards(points.underbustCB, 0.5)
points.bottomSide = points.hipsCF.shiftFractionTowards(points.hipsCB, 0.5)
points.waistCF = points.underbustCF.shift(-90, measurements.naturalWaistToUnderbust)
points.waistCB = new Point(points.hipsCB.x, points.waistCF.y)
// frontRise
points.topCF = points.underbustCF.shift(90, store.get("frontRise"));
points.frontRiseStart = points.underbustCF.shift(0, wid * 0.15);
points.frontRiseStartCp2 = points.underbustCF.shift(0, wid * 0.11);
points.topCFCp1 = points.topCF.shift(0, wid * 0.11);
points.topCF = points.underbustCF.shift(90, store.get('frontRise'))
points.frontRiseStart = points.underbustCF.shift(0, wid * 0.15)
points.frontRiseStartCp2 = points.underbustCF.shift(0, wid * 0.11)
points.topCFCp1 = points.topCF.shift(0, wid * 0.11)
// frontDrop
points.bottomCF = points.hipsCF.shift(-90, store.get("frontDrop"));
points.bottomCFCp2 = points.bottomCF.shift(0, wid * 0.11);
points.bottomCF = points.hipsCF.shift(-90, store.get('frontDrop'))
points.bottomCFCp2 = points.bottomCF.shift(0, wid * 0.11)
// hipRise
points.hipRise = points.bottomSide.shift(90, store.get("hipRise"));
points.hipRiseCp1 = points.hipRise.shift(180, wid * 0.3);
points.hipRiseCp2 = points.hipRise.shift(0, wid * 0.2);
points.hipRise = points.bottomSide.shift(90, store.get('hipRise'))
points.hipRiseCp1 = points.hipRise.shift(180, wid * 0.3)
points.hipRiseCp2 = points.hipRise.shift(0, wid * 0.2)
// backDrop
points.backDrop = points.hipsCB.shift(-90, store.get("backDrop"));
points.backDropCp1 = points.backDrop.shift(180, wid * 0.3);
points.backDrop = points.hipsCB.shift(-90, store.get('backDrop'))
points.backDropCp1 = points.backDrop.shift(180, wid * 0.3)
// backRise
points.backRise = points.underbustCB.shift(90, store.get("backRise"));
points.backRiseCp1 = points.backRise.shift(180, wid * 0.4);
points.topSideCp1 = points.topSide.shift(0, wid * 0.2);
points.backRise = points.underbustCB.shift(90, store.get('backRise'))
points.backRiseCp1 = points.backRise.shift(180, wid * 0.4)
points.topSideCp1 = points.topSide.shift(0, wid * 0.2)
// Paths
paths.help1 = new Path()
@ -113,14 +78,14 @@ export default function(part) {
.line(points.hipsCF)
.line(points.hipsCB)
.line(points.underbustCB)
.close();
.close()
paths.help2 = new Path()
.move(points.topSide)
.line(points.bottomSide)
.line(points.waistCF)
.line(points.waistCB);
paths.help1.render = false;
paths.help2.render = false;
.line(points.waistCB)
paths.help1.render = false
paths.help2.render = false
paths.outline = new Path()
.move(points.bottomCF)
@ -131,7 +96,7 @@ export default function(part) {
.line(points.frontRiseStart)
.curve(points.frontRiseStartCp2, points.topCFCp1, points.topCF)
.line(points.bottomCF)
.close();
.close()
return part;
return part
}

View file

@ -1,27 +1,27 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle'
import config from '../config'
//Parts
import draftBase from "./base";
import draftPanels from "./panels";
import draftPanel1 from "./panel1";
import draftPanel2 from "./panel2";
import draftPanel3 from "./panel3";
import draftPanel4 from "./panel4";
import draftPanel5 from "./panel5";
import draftPanel6 from "./panel6";
import draftBase from './base'
import draftPanels from './panels'
import draftPanel1 from './panel1'
import draftPanel2 from './panel2'
import draftPanel3 from './panel3'
import draftPanel4 from './panel4'
import draftPanel5 from './panel5'
import draftPanel6 from './panel6'
// Create design
const Pattern = new freesewing.Design(config, plugins);
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
Pattern.prototype.draftBase = draftBase;
Pattern.prototype.draftPanels = draftPanels;
Pattern.prototype.draftPanel1 = draftPanel1;
Pattern.prototype.draftPanel2 = draftPanel2;
Pattern.prototype.draftPanel3 = draftPanel3;
Pattern.prototype.draftPanel4 = draftPanel4;
Pattern.prototype.draftPanel5 = draftPanel5;
Pattern.prototype.draftPanel6 = draftPanel6;
Pattern.prototype.draftBase = draftBase
Pattern.prototype.draftPanels = draftPanels
Pattern.prototype.draftPanel1 = draftPanel1
Pattern.prototype.draftPanel2 = draftPanel2
Pattern.prototype.draftPanel3 = draftPanel3
Pattern.prototype.draftPanel4 = draftPanel4
Pattern.prototype.draftPanel5 = draftPanel5
Pattern.prototype.draftPanel6 = draftPanel6
export default Pattern;
export default Pattern

View file

@ -1,73 +1,70 @@
import draftPanel1ab from "./panel1ab";
import draftPanel1ab from './panel1ab'
export default function(part) {
let { macro, sa, paths, options, complete, paperless } = part.shorthand();
let { macro, sa, paths, options, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel2;
delete paths.panel3;
delete paths.panel4;
delete paths.panel5;
delete paths.panel6;
delete paths.outline
delete paths.panel2
delete paths.panel3
delete paths.panel4
delete paths.panel5
delete paths.panel6
if (options.panels === 13) return draftPanel1ab(part);
if (options.panels === 13) return draftPanel1ab(part)
// Complete pattern?
if (complete) {
macro("cutonfold", {
macro('cutonfold', {
to: points.bottomCF,
from: points.topCF,
grainline: true
});
points.title = points.waistCF.shiftFractionTowards(
points.underbustGap1Left,
0.5
);
macro("title", {
})
points.title = points.waistCF.shiftFractionTowards(points.underbustGap1Left, 0.5)
macro('title', {
nr: 1,
title: "",
title: '',
at: points.title
});
if (sa) paths.sa = paths.panel1.offset(sa).attr("class", "fabric sa");
})
if (sa) paths.sa = paths.panel1.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("vd", {
macro('vd', {
from: points.bottomCF,
to: points.waistCF,
x: points.topCF.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistCF,
to: points.topCF,
x: points.topCF.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap1,
to: points.waistGap1Left,
x: points.hipsGap1.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap1Left,
to: points.underbustGap1Left,
x: points.hipsGap1.x + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.bottomCF,
to: points.hipsGap1,
y: points.bottomCF.y + sa + 15
});
macro("hd", {
})
macro('hd', {
from: points.topCF,
to: points.underbustGap1Left,
y: points.topCF.y - sa - 15
});
macro("ld", {
})
macro('ld', {
from: points.waistCF,
to: points.waistGap1Left
});
})
}
return part;
return part
}

View file

@ -1,28 +1,14 @@
export default function(part) {
let {
macro,
utils,
sa,
points,
paths,
Point,
Path,
complete,
paperless
} = part.shorthand();
let { macro, utils, sa, points, paths, Point, Path, complete, paperless } = part.shorthand()
let top = new Path()
.move(points.underbustGap1Left)
.curve(points.frontRiseStartCp2, points.topCFCp1, points.topCF);
points.topABsplit = top.shiftFractionAlong(0.3);
.curve(points.frontRiseStartCp2, points.topCFCp1, points.topCF)
points.topABsplit = top.shiftFractionAlong(0.3)
let bottom = new Path()
.move(points.bottomCF)
.curve(
paths.panel1.ops[1].cp1,
paths.panel1.ops[1].cp2,
paths.panel1.ops[1].to
);
points.bottomABsplit = bottom.shiftFractionAlong(0.3);
.curve(paths.panel1.ops[1].cp1, paths.panel1.ops[1].cp2, paths.panel1.ops[1].to)
points.bottomABsplit = bottom.shiftFractionAlong(0.3)
paths.panel1a = bottom
.split(points.bottomABsplit)[0]
@ -30,144 +16,134 @@ export default function(part) {
.join(top.split(points.topABsplit)[1])
.line(points.bottomCF)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.panel1b = bottom
.split(points.bottomABsplit)[1]
.curve(points.hipsGap1Cp, points.waistGap1LeftCp1, points.waistGap1Left)
.curve(
points.waistGap1LeftCp2,
points.underbustGap1LeftCp,
points.underbustGap1Left
)
.curve(points.waistGap1LeftCp2, points.underbustGap1LeftCp, points.underbustGap1Left)
.join(top.split(points.topABsplit)[0])
.line(points.bottomABsplit)
.close()
.attr("class", "fabric");
let translation = 5;
if (sa) translation = 2 * sa + 5;
paths.panel1b = paths.panel1b.translate(translation, 0);
delete paths.panel1;
.attr('class', 'fabric')
let translation = 5
if (sa) translation = 2 * sa + 5
paths.panel1b = paths.panel1b.translate(translation, 0)
delete paths.panel1
// Complete pattern?
if (complete) {
if (sa) {
paths.saA = paths.panel1a.offset(sa).attr("class", "fabric sa");
paths.saB = paths.panel1b.offset(sa).attr("class", "fabric sa");
paths.saA = paths.panel1a.offset(sa).attr('class', 'fabric sa')
paths.saB = paths.panel1b.offset(sa).attr('class', 'fabric sa')
}
macro("cutonfold", {
macro('cutonfold', {
to: points.bottomCF,
from: points.topCF,
grainline: true
});
macro("grainline", {
})
macro('grainline', {
to: points.topABsplit.translate(translation, 0),
from: new Point(
points.topABsplit.translate(translation, 0).x,
points.hipsGap1.translate(translation, 0).y
)
});
points.midwayAB = points.topABsplit.shiftFractionTowards(
points.bottomABsplit,
0.5
);
points.titleA = points.underbustCF.shiftFractionTowards(
points.midwayAB,
0.5
);
macro("title", {
nr: "1a",
prefix: "panel1a",
})
points.midwayAB = points.topABsplit.shiftFractionTowards(points.bottomABsplit, 0.5)
points.titleA = points.underbustCF.shiftFractionTowards(points.midwayAB, 0.5)
macro('title', {
nr: '1a',
prefix: 'panel1a',
at: points.titleA
});
})
points.titleB = points.hipsGap1
.translate(translation, 0)
.shiftFractionTowards(points.midwayAB, 0.5);
macro("title", {
nr: "1b",
prefix: "panel1b",
.shiftFractionTowards(points.midwayAB, 0.5)
macro('title', {
nr: '1b',
prefix: 'panel1b',
at: points.titleB
});
})
}
// Paperless?
if (paperless) {
// 1a
macro("vd", {
macro('vd', {
from: points.bottomCF,
to: points.waistCF,
x: points.topCF.x - sa - 30
});
macro("vd", {
})
macro('vd', {
from: points.waistCF,
to: points.topCF,
x: points.topCF.x - sa - 30
});
})
points.waistAB = utils.beamsIntersect(
points.topABsplit,
points.bottomABsplit,
points.waistCF,
points.waistGap1
);
macro("vd", {
)
macro('vd', {
from: points.bottomABsplit,
to: points.waistAB,
x: points.topCF.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistAB,
to: points.topABsplit,
x: points.topCF.x - sa - 15
});
macro("hd", {
})
macro('hd', {
from: points.bottomCF,
to: points.bottomABsplit,
y: points.bottomCF.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistCF,
to: points.waistAB
});
macro("hd", {
})
macro('hd', {
from: points.topCF,
to: points.topABsplit,
y: points.topCF.y - sa - 15
});
})
// 1b
macro("vd", {
macro('vd', {
from: points.hipsGap1.translate(translation, 0),
to: points.waistGap1Left.translate(translation, 0),
x: points.underbustGap1Left.translate(translation, 0).x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap1Left.translate(translation, 0),
to: points.underbustGap1Left.translate(translation, 0),
x: points.underbustGap1Left.translate(translation, 0).x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.bottomABsplit.translate(translation, 0),
to: points.waistAB.translate(translation, 0),
x: points.underbustGap1Left.translate(translation, 0).x + sa + 30
});
macro("vd", {
})
macro('vd', {
from: points.waistAB.translate(translation, 0),
to: points.topABsplit.translate(translation, 0),
x: points.underbustGap1Left.translate(translation, 0).x + sa + 30
});
macro("hd", {
})
macro('hd', {
from: points.bottomABsplit.translate(translation, 0),
to: points.hipsGap1.translate(translation, 0),
y: points.bottomABsplit.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistAB.translate(translation, 0),
to: points.waistGap1Left.translate(translation, 0)
});
macro("hd", {
})
macro('hd', {
from: points.topABsplit.translate(translation, 0),
to: points.underbustGap1Left.translate(translation, 0),
y: points.topABsplit.y - sa - 15
});
})
}
return part;
return part
}

View file

@ -1,84 +1,70 @@
export default function(part) {
let {
macro,
sa,
points,
paths,
Point,
complete,
paperless
} = part.shorthand();
let { macro, sa, points, paths, Point, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel1;
delete paths.panel3;
delete paths.panel4;
delete paths.panel5;
delete paths.panel6;
delete paths.outline
delete paths.panel1
delete paths.panel3
delete paths.panel4
delete paths.panel5
delete paths.panel6
// Complete pattern?
if (complete) {
points.grainlineTop = new Point(
points.waistGap1Right.shiftFractionTowards(points.waistGap2Left, 0.5).x,
points.underbustGap1Right.y
);
points.grainlineBottom = new Point(
points.grainlineTop.x,
points.hipsGap2.y
);
macro("grainline", {
)
points.grainlineBottom = new Point(points.grainlineTop.x, points.hipsGap2.y)
macro('grainline', {
from: points.grainlineBottom,
to: points.grainlineTop
});
points.title = points.grainlineTop.shift(
-90,
points.grainlineTop.dy(points.waistGap2Left) / 2
);
macro("title", {
})
points.title = points.grainlineTop.shift(-90, points.grainlineTop.dy(points.waistGap2Left) / 2)
macro('title', {
nr: 2,
title: "",
title: '',
at: points.title
});
if (sa) paths.sa = paths.panel2.offset(sa).attr("class", "fabric sa");
})
if (sa) paths.sa = paths.panel2.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.hipsGap1,
to: points.hipsGap2,
y: points.hipsGap1.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistGap1Right,
to: points.waistGap2Left
});
macro("hd", {
})
macro('hd', {
from: points.underbustGap1Right,
to: points.underbustGap2Left,
y: points.underbustGap1Right.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap1,
to: points.waistGap1Right,
x: points.hipsGap1.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap1Right,
to: points.underbustGap1Right,
x: points.hipsGap1.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap2,
to: points.waistGap1Right,
x: points.hipsGap2.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap1Right,
to: points.underbustGap2Left,
x: points.hipsGap2.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,84 +1,70 @@
export default function(part) {
let {
macro,
sa,
points,
paths,
Point,
complete,
paperless
} = part.shorthand();
let { macro, sa, points, paths, Point, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel1;
delete paths.panel2;
delete paths.panel4;
delete paths.panel5;
delete paths.panel6;
delete paths.outline
delete paths.panel1
delete paths.panel2
delete paths.panel4
delete paths.panel5
delete paths.panel6
// Complete pattern?
if (complete) {
points.grainlineTop = new Point(
points.waistGap2Right.shiftFractionTowards(points.waistGap3Left, 0.5).x,
points.underbustGap2Right.y
);
points.grainlineBottom = new Point(
points.grainlineTop.x,
points.hipsGap3.y
);
macro("grainline", {
)
points.grainlineBottom = new Point(points.grainlineTop.x, points.hipsGap3.y)
macro('grainline', {
from: points.grainlineBottom,
to: points.grainlineTop
});
points.title = points.grainlineTop.shift(
-90,
points.grainlineTop.dy(points.waistGap3Left) / 2
);
macro("title", {
})
points.title = points.grainlineTop.shift(-90, points.grainlineTop.dy(points.waistGap3Left) / 2)
macro('title', {
nr: 3,
title: "",
title: '',
at: points.title
});
if (sa) paths.sa = paths.panel3.offset(sa).attr("class", "fabric sa");
})
if (sa) paths.sa = paths.panel3.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.hipsGap2,
to: points.hipsGap3,
y: points.hipsGap2.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistGap2Right,
to: points.waistGap3Left
});
macro("hd", {
})
macro('hd', {
from: points.underbustGap2Right,
to: points.underbustGap3Left,
y: points.underbustGap2Right.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap2,
to: points.waistGap2Right,
x: points.hipsGap2.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap2Right,
to: points.underbustGap2Right,
x: points.hipsGap2.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap3,
to: points.waistGap2Right,
x: points.hipsGap3.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap2Right,
to: points.underbustGap3Left,
x: points.hipsGap3.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,92 +1,73 @@
export default function(part) {
let {
macro,
sa,
snippets,
Snippet,
points,
paths,
Point,
complete,
paperless
} = part.shorthand();
let { macro, sa, snippets, Snippet, points, paths, Point, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel1;
delete paths.panel2;
delete paths.panel3;
delete paths.panel5;
delete paths.panel6;
delete paths.outline
delete paths.panel1
delete paths.panel2
delete paths.panel3
delete paths.panel5
delete paths.panel6
// Complete pattern?
if (complete) {
points.grainlineTop = new Point(
points.waistGap3Right.shiftFractionTowards(points.waistGap4Left, 0.5).x,
points.underbustGap3Right.y
);
points.grainlineBottom = new Point(
points.grainlineTop.x,
points.hipsGap4.y
);
macro("grainline", {
)
points.grainlineBottom = new Point(points.grainlineTop.x, points.hipsGap4.y)
macro('grainline', {
from: points.grainlineBottom,
to: points.grainlineTop
});
points.title = points.grainlineTop.shift(
-90,
points.grainlineTop.dy(points.waistGap4Left) / 2
);
macro("title", {
})
points.title = points.grainlineTop.shift(-90, points.grainlineTop.dy(points.waistGap4Left) / 2)
macro('title', {
nr: 4,
title: "",
title: '',
at: points.title
});
points.logo = points.grainlineTop.shiftFractionTowards(
points.grainlineBottom,
0.8
);
snippets.logo = new Snippet("logo", points.logo).attr("data-scale", 0.8);
})
points.logo = points.grainlineTop.shiftFractionTowards(points.grainlineBottom, 0.8)
snippets.logo = new Snippet('logo', points.logo).attr('data-scale', 0.8)
if (sa) paths.sa = paths.panel4.offset(sa).attr("class", "fabric sa");
if (sa) paths.sa = paths.panel4.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.hipsGap3,
to: points.hipsGap4,
y: points.hipsGap3.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistGap3Right,
to: points.waistGap4Left
});
macro("hd", {
})
macro('hd', {
from: points.underbustGap3Right,
to: points.underbustGap4Left,
y: points.underbustGap4Left.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap3,
to: points.waistGap3Right,
x: points.hipsGap3.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap3Right,
to: points.underbustGap3Right,
x: points.hipsGap3.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap4,
to: points.waistGap3Right,
x: points.hipsGap4.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap3Right,
to: points.underbustGap4Left,
x: points.hipsGap4.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,84 +1,70 @@
export default function(part) {
let {
macro,
sa,
points,
paths,
Point,
complete,
paperless
} = part.shorthand();
let { macro, sa, points, paths, Point, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel1;
delete paths.panel2;
delete paths.panel3;
delete paths.panel4;
delete paths.panel6;
delete paths.outline
delete paths.panel1
delete paths.panel2
delete paths.panel3
delete paths.panel4
delete paths.panel6
// Complete pattern?
if (complete) {
points.grainlineTop = new Point(
points.waistGap4Right.shiftFractionTowards(points.waistGap5Left, 0.5).x,
points.underbustGap4Right.y
);
points.grainlineBottom = new Point(
points.grainlineTop.x,
points.hipsGap5.y
);
macro("grainline", {
)
points.grainlineBottom = new Point(points.grainlineTop.x, points.hipsGap5.y)
macro('grainline', {
from: points.grainlineBottom,
to: points.grainlineTop
});
points.title = points.grainlineTop.shift(
-90,
points.grainlineTop.dy(points.waistGap5Left) / 2
);
macro("title", {
})
points.title = points.grainlineTop.shift(-90, points.grainlineTop.dy(points.waistGap5Left) / 2)
macro('title', {
nr: 5,
title: "",
title: '',
at: points.title
});
if (sa) paths.sa = paths.panel5.offset(sa).attr("class", "fabric sa");
})
if (sa) paths.sa = paths.panel5.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.hipsGap4,
to: points.hipsGap5,
y: points.hipsGap4.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistGap4Right,
to: points.waistGap5Left
});
macro("hd", {
})
macro('hd', {
from: points.underbustGap4Right,
to: points.underbustGap5Left,
y: points.underbustGap5Left.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap4,
to: points.waistGap4Right,
x: points.hipsGap4.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap4Right,
to: points.underbustGap4Right,
x: points.hipsGap4.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap5,
to: points.waistGap4Right,
x: points.hipsGap5.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap4Right,
to: points.underbustGap5Left,
x: points.hipsGap5.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,89 +1,75 @@
export default function(part) {
let {
macro,
sa,
points,
paths,
Point,
complete,
paperless
} = part.shorthand();
let { macro, sa, points, paths, Point, complete, paperless } = part.shorthand()
delete paths.outline;
delete paths.panel1;
delete paths.panel2;
delete paths.panel3;
delete paths.panel4;
delete paths.panel5;
delete paths.outline
delete paths.panel1
delete paths.panel2
delete paths.panel3
delete paths.panel4
delete paths.panel5
// Complete pattern?
if (complete) {
points.grainlineTop = new Point(
points.waistGap5Right.shiftFractionTowards(points.waistCB, 0.5).x,
points.underbustGap5Right.y
);
points.grainlineBottom = new Point(
points.grainlineTop.x,
points.hipsGap5.y
);
macro("grainline", {
)
points.grainlineBottom = new Point(points.grainlineTop.x, points.hipsGap5.y)
macro('grainline', {
from: points.grainlineBottom,
to: points.grainlineTop
});
points.title = points.grainlineTop.shift(
-90,
points.grainlineTop.dy(points.waistGap5Right) / 2
);
macro("title", {
})
points.title = points.grainlineTop.shift(-90, points.grainlineTop.dy(points.waistGap5Right) / 2)
macro('title', {
nr: 6,
title: "",
title: '',
at: points.title
});
points.scalebox = new Point(points.grainlineTop.x, points.hipsGap5.y - 55);
macro("scalebox", {
})
points.scalebox = new Point(points.grainlineTop.x, points.hipsGap5.y - 55)
macro('scalebox', {
at: points.scalebox,
rotate: 90
});
if (sa) paths.sa = paths.panel6.offset(sa).attr("class", "fabric sa");
})
if (sa) paths.sa = paths.panel6.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro("hd", {
macro('hd', {
from: points.hipsGap5,
to: points.backDrop,
y: points.backDrop.y + sa + 15
});
macro("ld", {
})
macro('ld', {
from: points.waistGap5Right,
to: points.waistCB
});
macro("hd", {
})
macro('hd', {
from: points.underbustGap5Right,
to: points.backRise,
y: points.backRise.y - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.hipsGap5,
to: points.waistGap5Right,
x: points.hipsGap5.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.waistGap5Right,
to: points.underbustGap5Right,
x: points.hipsGap5.x - sa - 15
});
macro("vd", {
})
macro('vd', {
from: points.backDrop,
to: points.waistCB,
x: points.backDrop.x + sa + 15
});
macro("vd", {
})
macro('vd', {
from: points.waistCB,
to: points.backRise,
x: points.backDrop.x + sa + 15
});
})
}
return part;
return part
}

View file

@ -1,205 +1,141 @@
export default function(part) {
let {
measurements,
options,
store,
points,
paths,
Point,
Path,
debug
} = part.shorthand();
let count = 1;
let { measurements, options, store, points, paths, Point, Path, debug } = part.shorthand()
let count = 1
let bottom = new Path()
.move(points.bottomCF)
.curve(points.bottomCFCp2, points.hipRiseCp1, points.hipRise)
.curve(points.hipRiseCp2, points.backDropCp1, points.backDrop)
.attr("class", "lashed various stroke-xl");
for (let gap of store.get("gaps")) {
.attr('class', 'lashed various stroke-xl')
for (let gap of store.get('gaps')) {
// Underbust
points[`underbustGap${count}`] = new Point(store.get("width") * gap, 0);
points[`underbustGap${count}`] = new Point(store.get('width') * gap, 0)
points[`underbustGap${count}Right`] = points[`underbustGap${count}`].shift(
0,
store.get("bustIntake") * 0.1
);
store.get('bustIntake') * 0.1
)
points[`underbustGap${count}Left`] = points[`underbustGap${count}`].shift(
180,
store.get("bustIntake") * 0.1
);
points[`underbustGap${count}RightCp`] = points[
`underbustGap${count}Right`
].shift(-90, measurements.naturalWaistToUnderbust * 0.15);
points[`underbustGap${count}LeftCp`] = points[
`underbustGap${count}Left`
].shift(-90, measurements.naturalWaistToUnderbust * 0.15);
store.get('bustIntake') * 0.1
)
points[`underbustGap${count}RightCp`] = points[`underbustGap${count}Right`].shift(
-90,
measurements.naturalWaistToUnderbust * 0.15
)
points[`underbustGap${count}LeftCp`] = points[`underbustGap${count}Left`].shift(
-90,
measurements.naturalWaistToUnderbust * 0.15
)
// Waist
points[`waistGap${count}`] = new Point(
store.get("width") * gap,
points.waistCF.y
);
points[`waistGap${count}`] = new Point(store.get('width') * gap, points.waistCF.y)
points[`waistGap${count}Right`] = points[`waistGap${count}`].shift(
0,
store.get("waistIntake") * 0.1
);
store.get('waistIntake') * 0.1
)
points[`waistGap${count}Left`] = points[`waistGap${count}`].shift(
180,
store.get("waistIntake") * 0.1
);
store.get('waistIntake') * 0.1
)
points[`waistGap${count}RightCp1`] = points[`waistGap${count}Right`].shift(
90,
measurements.naturalWaistToUnderbust * 0.2
);
)
points[`waistGap${count}LeftCp2`] = points[`waistGap${count}Left`].shift(
90,
measurements.naturalWaistToUnderbust * 0.2
);
)
points[`waistGap${count}RightCp2`] = points[`waistGap${count}Right`].shift(
-90,
measurements.naturalWaistToHip * 0.2
);
)
points[`waistGap${count}LeftCp1`] = points[`waistGap${count}Left`].shift(
-90,
measurements.naturalWaistToHip * 0.2
);
)
// Hips
points[`hipsGap${count}`] = new Point(
store.get("width") * gap,
points.hipsCF.y
);
points[`hipsGap${count}`] = bottom
.intersectsX(points[`waistGap${count}`].x)
.pop();
points[`hipsGap${count}Cp`] = points[
`hipsGap${count}`
].shiftFractionTowards(points[`waistGap${count}`], 0.2);
points[`hipsGap${count}`] = new Point(store.get('width') * gap, points.hipsCF.y)
points[`hipsGap${count}`] = bottom.intersectsX(points[`waistGap${count}`].x).pop()
points[`hipsGap${count}Cp`] = points[`hipsGap${count}`].shiftFractionTowards(
points[`waistGap${count}`],
0.2
)
count++;
count++
}
// Paths
paths.panel1 = bottom
.split(points.hipsGap1)[0]
.curve(points.hipsGap1Cp, points.waistGap1LeftCp1, points.waistGap1Left)
.curve(
points.waistGap1LeftCp2,
points.underbustGap1LeftCp,
points.underbustGap1Left
)
.curve(points.waistGap1LeftCp2, points.underbustGap1LeftCp, points.underbustGap1Left)
.curve(points.frontRiseStartCp2, points.topCFCp1, points.topCF)
.line(points.bottomCF)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.panel2 = bottom
.split(points.hipsGap2)[0]
.split(points.hipsGap1)[1]
.curve(points.hipsGap2Cp, points.waistGap2LeftCp1, points.waistGap2Left)
.curve(
points.waistGap2LeftCp2,
points.underbustGap2LeftCp,
points.underbustGap2Left
)
.curve(points.waistGap2LeftCp2, points.underbustGap2LeftCp, points.underbustGap2Left)
.line(points.underbustGap1Right)
.curve(
points.underbustGap1RightCp,
points.waistGap1RightCp1,
points.waistGap1Right
)
.curve(points.underbustGap1RightCp, points.waistGap1RightCp1, points.waistGap1Right)
.curve(points.waistGap1RightCp2, points.hipsGap1Cp, points.hipsGap1)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
let panel3 = new Path()
.move(points.bottomCF)
.curve(points.bottomCFCp2, points.hipRiseCp1, points.hipRise)
.split(points.hipsGap2)[1];
if (options.panels === 11) panel3 = panel3.split(points.hipsGap3)[0];
.split(points.hipsGap2)[1]
if (options.panels === 11) panel3 = panel3.split(points.hipsGap3)[0]
paths.panel3 = panel3
.curve(points.hipsGap3Cp, points.waistGap3LeftCp1, points.waistGap3Left)
.curve(
points.waistGap3LeftCp2,
points.underbustGap3LeftCp,
points.underbustGap3Left
)
.curve(points.waistGap3LeftCp2, points.underbustGap3LeftCp, points.underbustGap3Left)
.line(points.underbustGap2Right)
.curve(
points.underbustGap2RightCp,
points.waistGap2RightCp1,
points.waistGap2Right
)
.curve(points.underbustGap2RightCp, points.waistGap2RightCp1, points.waistGap2Right)
.curve(points.waistGap2RightCp2, points.hipsGap2Cp, points.hipsGap2)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
let topBack = new Path()
.move(points.backRise)
.curve(points.backRiseCp1, points.topSideCp1, points.topSide);
points.underbustGap4Left = topBack
.intersectsX(points.underbustGap4Left.x)
.pop();
.curve(points.backRiseCp1, points.topSideCp1, points.topSide)
points.underbustGap4Left = topBack.intersectsX(points.underbustGap4Left.x).pop()
paths.panel4 = new Path()
.move(points.hipRise)
.curve(points.hipRiseCp2, points.backDropCp1, points.backDrop)
.split(points.hipsGap4)[0]
.curve(points.hipsGap4Cp, points.waistGap4LeftCp1, points.waistGap4Left)
.curve(
points.waistGap4LeftCp2,
points.underbustGap4LeftCp,
points.underbustGap4Left
)
.join(topBack.split(points.underbustGap4Left)[1]);
if (options.panels === 11) paths.panel4.line(points.underbustGap3Right);
.curve(points.waistGap4LeftCp2, points.underbustGap4LeftCp, points.underbustGap4Left)
.join(topBack.split(points.underbustGap4Left)[1])
if (options.panels === 11) paths.panel4.line(points.underbustGap3Right)
paths.panel4
.curve(
points.underbustGap3RightCp,
points.waistGap3RightCp1,
points.waistGap3Right
)
.curve(points.underbustGap3RightCp, points.waistGap3RightCp1, points.waistGap3Right)
.curve(points.waistGap3RightCp2, points.hipsGap3Cp, points.hipsGap3)
.close()
.attr("class", "fabric");
points.underbustGap4Right = topBack
.intersectsX(points.underbustGap4Right.x)
.pop();
points.underbustGap5Left = topBack
.intersectsX(points.underbustGap5Left.x)
.pop();
let top5 = topBack
.split(points.underbustGap5Left)[1]
.split(points.underbustGap4Right)[0];
.attr('class', 'fabric')
points.underbustGap4Right = topBack.intersectsX(points.underbustGap4Right.x).pop()
points.underbustGap5Left = topBack.intersectsX(points.underbustGap5Left.x).pop()
let top5 = topBack.split(points.underbustGap5Left)[1].split(points.underbustGap4Right)[0]
paths.panel5 = bottom
.split(points.hipsGap5)[0]
.split(points.hipsGap4)[1]
.curve(points.hipsGap5Cp, points.waistGap5LeftCp1, points.waistGap5Left)
.curve(
points.waistGap5LeftCp2,
points.underbustGap5LeftCp,
points.underbustGap5Left
)
.curve(points.waistGap5LeftCp2, points.underbustGap5LeftCp, points.underbustGap5Left)
.curve(top5.ops[1].cp1, top5.ops[1].cp2, top5.ops[1].to)
.curve(
points.underbustGap4RightCp,
points.waistGap4RightCp1,
points.waistGap4Right
)
.curve(points.underbustGap4RightCp, points.waistGap4RightCp1, points.waistGap4Right)
.curve(points.waistGap4RightCp2, points.hipsGap4Cp, points.hipsGap4)
.close()
.attr("class", "fabric");
points.underbustGap5Right = topBack
.intersectsX(points.underbustGap5Right.x)
.pop();
.attr('class', 'fabric')
points.underbustGap5Right = topBack.intersectsX(points.underbustGap5Right.x).pop()
paths.panel6 = bottom
.split(points.hipsGap5)[1]
.line(points.backRise)
.join(topBack.split(points.underbustGap5Right)[0])
.curve(
points.underbustGap5RightCp,
points.waistGap5RightCp1,
points.waistGap5Right
)
.curve(points.underbustGap5RightCp, points.waistGap5RightCp1, points.waistGap5Right)
.curve(points.waistGap5RightCp2, points.hipsGap5Cp, points.hipsGap5)
.close()
.attr("class", "fabric");
.attr('class', 'fabric')
paths.outline.render = false;
paths.outline.render = false
return part;
return part
}

View file

@ -1,19 +1,19 @@
export default [
"Blockquote",
"Draft",
"DraftConfigurator",
"Emblem",
"Example",
"Footer",
"Icon",
"Logo",
"Navbar",
"Ogol",
"Robot",
"Spinner",
"SampleConfigurator",
"withGist",
"withLanguage",
"withStorage",
"Workbench"
];
'Blockquote',
'Draft',
'DraftConfigurator',
'Emblem',
'Example',
'Footer',
'Icon',
'Logo',
'Navbar',
'Ogol',
'Robot',
'Spinner',
'SampleConfigurator',
'withGist',
'withLanguage',
'withStorage',
'Workbench'
]

View file

@ -1,99 +1,99 @@
function Attributes() {
this.list = {};
this.list = {}
}
/** Adds an attribute */
Attributes.prototype.add = function(name, value) {
if (typeof this.list[name] === "undefined") {
this.list[name] = [];
if (typeof this.list[name] === 'undefined') {
this.list[name] = []
}
this.list[name].push(value);
this.list[name].push(value)
return this;
};
return this
}
/** Sets an attribute, overwriting existing value */
Attributes.prototype.set = function(name, value) {
this.list[name] = [value];
this.list[name] = [value]
return this;
};
return this
}
/** Removes an attribute */
Attributes.prototype.remove = function(name) {
delete this.list[name];
delete this.list[name]
return this;
};
return this
}
/** Retrieves an attribute */
Attributes.prototype.get = function(name) {
if (typeof this.list[name] === "undefined") return false;
else return this.list[name].join(" ");
};
if (typeof this.list[name] === 'undefined') return false
else return this.list[name].join(' ')
}
/** Retrieves an attribute as array*/
Attributes.prototype.getAsArray = function(name) {
if (typeof this.list[name] === "undefined") return false;
else return this.list[name];
};
if (typeof this.list[name] === 'undefined') return false
else return this.list[name]
}
/** Returns SVG code for attributes */
Attributes.prototype.render = function() {
let svg = "";
let svg = ''
for (let key in this.list) {
svg += ` ${key}="${this.list[key].join(" ")}"`;
svg += ` ${key}="${this.list[key].join(' ')}"`
}
return svg;
};
return svg
}
/** Returns CSS code for attributes */
Attributes.prototype.renderAsCss = function() {
let css = "";
let css = ''
for (let key in this.list) {
css += ` ${key}:${this.list[key].join(" ")};`;
css += ` ${key}:${this.list[key].join(' ')};`
}
return css;
};
return css
}
/** Returns SVG code for attributes with a fiven prefix
* typically used for data-text*/
Attributes.prototype.renderIfPrefixIs = function(prefix = "") {
let svg = "";
let prefixLen = prefix.length;
Attributes.prototype.renderIfPrefixIs = function(prefix = '') {
let svg = ''
let prefixLen = prefix.length
for (let key in this.list) {
if (key.substr(0, prefixLen) === prefix) {
svg += ` ${key.substr(prefixLen)}="${this.list[key].join(" ")}"`;
svg += ` ${key.substr(prefixLen)}="${this.list[key].join(' ')}"`
}
}
return svg;
};
return svg
}
/** Returns a props object for attributes with a fiven prefix
* typically used for data-text*/
Attributes.prototype.asPropsIfPrefixIs = function(prefix = "") {
let props = {};
let prefixLen = prefix.length;
Attributes.prototype.asPropsIfPrefixIs = function(prefix = '') {
let props = {}
let prefixLen = prefix.length
for (let key in this.list) {
if (key.substr(0, prefixLen) === prefix) {
let propKey = key.substr(prefixLen);
if (propKey === "class") propKey = "className";
props[propKey] = this.get(key);
let propKey = key.substr(prefixLen)
if (propKey === 'class') propKey = 'className'
props[propKey] = this.get(key)
}
}
return props;
};
return props
}
/** Returns a deep copy of this */
Attributes.prototype.clone = function() {
let clone = new Attributes();
clone.list = JSON.parse(JSON.stringify(this.list));
let clone = new Attributes()
clone.list = JSON.parse(JSON.stringify(this.list))
return clone;
};
return clone
}
export default Attributes;
export default Attributes

View file

@ -1,18 +1,18 @@
import Pattern from "./pattern";
import Pattern from './pattern'
export default function Design(config, plugins = false) {
const pattern = function(settings) {
Pattern.call(this, config);
if (Array.isArray(plugins)) for (let plugin of plugins) this.use(plugin);
else if (plugins) this.use(plugins);
this.apply(settings);
Pattern.call(this, config)
if (Array.isArray(plugins)) for (let plugin of plugins) this.use(plugin)
else if (plugins) this.use(plugins)
this.apply(settings)
return this;
};
return this
}
// Set up inheritance
pattern.prototype = Object.create(Pattern.prototype);
pattern.prototype.constructor = pattern;
pattern.prototype = Object.create(Pattern.prototype)
pattern.prototype.constructor = pattern
return pattern;
return pattern
}

View file

@ -8,5 +8,5 @@ export default function Hooks() {
postRender: [],
insertText: [],
debug: []
};
}
}

View file

@ -1,10 +1,10 @@
import Design from "./design";
import Pattern from "./pattern";
import Point from "./point";
import Path from "./path";
import Snippet from "./snippet";
import * as utils from "./utils";
import { version } from "../package.json";
import Design from './design'
import Pattern from './pattern'
import Point from './point'
import Path from './path'
import Snippet from './snippet'
import * as utils from './utils'
import { version } from '../package.json'
export default {
version,
@ -16,4 +16,4 @@ export default {
utils,
patterns: {},
plugins: {}
};
}

View file

@ -1,9 +1,9 @@
function Option(config) {
this.id = config.id;
this.config = config;
this.val = config.val;
this.id = config.id
this.config = config
this.val = config.val
return this;
return this
}
export default Option;
export default Option

View file

@ -1,202 +1,196 @@
import * as utils from "./utils";
import Point from "./point";
import Path from "./path";
import Snippet from "./snippet";
import Attributes from "./attributes";
import Hooks from "./hooks";
import * as utils from './utils'
import Point from './point'
import Path from './path'
import Snippet from './snippet'
import Attributes from './attributes'
import Hooks from './hooks'
function Part() {
this.attributes = new Attributes();
this.points = {};
this.paths = {};
this.snippets = {};
this.freeId = 0;
this.topLeft = false;
this.bottomRight = false;
this.width = false;
this.height = false;
this.render = true;
this.utils = utils;
this.attributes = new Attributes()
this.points = {}
this.paths = {}
this.snippets = {}
this.freeId = 0
this.topLeft = false
this.bottomRight = false
this.width = false
this.height = false
this.render = true
this.utils = utils
// Constructors so macros can create objects
this.Point = Point;
this.Path = Path;
this.Snippet = Snippet;
this.Point = Point
this.Path = Path
this.Snippet = Snippet
this.hooks = new Hooks(); // Hooks container
this.hooks = new Hooks() // Hooks container
return this;
return this
}
Part.prototype.macroClosure = function(args) {
let self = this;
let self = this
let method = function(key, args) {
let macro = utils.macroName(key);
if (typeof self[macro] === "function") {
self[macro](args);
let macro = utils.macroName(key)
if (typeof self[macro] === 'function') {
self[macro](args)
} else {
self.debug({
type: "warning",
label: "🚨 Macro not found",
type: 'warning',
label: '🚨 Macro not found',
msg: `Macro ${key} is not registered`
});
})
}
}
};
return method;
};
return method
}
Part.prototype.debugClosure = function() {
let self = this;
let self = this
let method = function(data) {
self.debug(data);
};
self.debug(data)
}
return method;
};
return method
}
Part.prototype.runHooks = function(hookName, data = false) {
if (data === false) data = this;
let hooks = this.hooks[hookName];
if (data === false) data = this
let hooks = this.hooks[hookName]
if (hooks && hooks.length > 0) {
for (let hook of hooks) {
hook.method(data, hook.data);
hook.method(data, hook.data)
}
}
};
}
/** Debug method */
Part.prototype.debug = function(data) {
this.runHooks("debug", data);
};
this.runHooks('debug', data)
}
/** Returns an unused ID */
Part.prototype.getId = function() {
this.freeId += 1;
this.freeId += 1
return "" + this.freeId;
};
return '' + this.freeId
}
/** Returns a value formatted for units provided in settings */
Part.prototype.unitsClosure = function(value) {
let self = this;
let self = this
let method = function(value) {
return utils.units(value, self.context.settings.units);
};
return utils.units(value, self.context.settings.units)
}
return method;
};
return method
}
/** Calculates the part's bounding box and sets it */
Part.prototype.boundary = function() {
if (this.topLeft) return this; // Cached
if (this.topLeft) return this // Cached
let topLeft = new Point(Infinity, Infinity);
let bottomRight = new Point(-Infinity, -Infinity);
let topLeft = new Point(Infinity, Infinity)
let bottomRight = new Point(-Infinity, -Infinity)
for (let key in this.paths) {
let path = this.paths[key].boundary();
let path = this.paths[key].boundary()
if (path.render) {
if (path.topLeft.x < topLeft.x) topLeft.x = path.topLeft.x;
if (path.topLeft.y < topLeft.y) topLeft.y = path.topLeft.y;
if (path.bottomRight.x > bottomRight.x)
bottomRight.x = path.bottomRight.x;
if (path.bottomRight.y > bottomRight.y)
bottomRight.y = path.bottomRight.y;
if (path.topLeft.x < topLeft.x) topLeft.x = path.topLeft.x
if (path.topLeft.y < topLeft.y) topLeft.y = path.topLeft.y
if (path.bottomRight.x > bottomRight.x) bottomRight.x = path.bottomRight.x
if (path.bottomRight.y > bottomRight.y) bottomRight.y = path.bottomRight.y
}
}
for (let key in this.points) {
let point = this.points[key];
let radius = point.attributes.get("data-circle");
let point = this.points[key]
let radius = point.attributes.get('data-circle')
if (radius) {
radius = parseFloat(radius);
if (point.x - radius < topLeft.x) topLeft.x = point.x - radius;
if (point.y - radius < topLeft.y) topLeft.y = point.y - radius;
if (point.x + radius > bottomRight.x) bottomRight.x = point.x + radius;
if (point.y + radius > bottomRight.y) bottomRight.y = point.y + radius;
radius = parseFloat(radius)
if (point.x - radius < topLeft.x) topLeft.x = point.x - radius
if (point.y - radius < topLeft.y) topLeft.y = point.y - radius
if (point.x + radius > bottomRight.x) bottomRight.x = point.x + radius
if (point.y + radius > bottomRight.y) bottomRight.y = point.y + radius
}
}
// Fix infinity if part has no paths
if (topLeft.x === Infinity) topLeft.x = 0;
if (topLeft.y === Infinity) topLeft.y = 0;
if (bottomRight.x === -Infinity) bottomRight.x = 0;
if (bottomRight.y === -Infinity) bottomRight.y = 0;
if (topLeft.x === Infinity) topLeft.x = 0
if (topLeft.y === Infinity) topLeft.y = 0
if (bottomRight.x === -Infinity) bottomRight.x = 0
if (bottomRight.y === -Infinity) bottomRight.y = 0
// Add margin
let margin = this.context.settings.margin;
if (this.context.settings.paperless && margin < 10) margin = 10;
this.topLeft = new Point(topLeft.x - margin, topLeft.y - margin);
this.bottomRight = new Point(bottomRight.x + margin, bottomRight.y + margin);
this.width = this.bottomRight.x - this.topLeft.x;
this.height = this.bottomRight.y - this.topLeft.y;
let margin = this.context.settings.margin
if (this.context.settings.paperless && margin < 10) margin = 10
this.topLeft = new Point(topLeft.x - margin, topLeft.y - margin)
this.bottomRight = new Point(bottomRight.x + margin, bottomRight.y + margin)
this.width = this.bottomRight.x - this.topLeft.x
this.height = this.bottomRight.y - this.topLeft.y
return this;
};
return this
}
/** Stacks part so that its top left corner is in (0,0) */
Part.prototype.stack = function() {
if (this.topLeft !== false) return this;
else this.boundary();
if (this.topLeft.x == 0 && this.topLeft.y == 0) return this;
else
this.attr(
"transform",
`translate(${this.topLeft.x * -1}, ${this.topLeft.y * -1})`
);
if (this.topLeft !== false) return this
else this.boundary()
if (this.topLeft.x == 0 && this.topLeft.y == 0) return this
else this.attr('transform', `translate(${this.topLeft.x * -1}, ${this.topLeft.y * -1})`)
return this;
};
return this
}
/** Adds an attribute. This is here to make this call chainable in assignment */
Part.prototype.attr = function(name, value, overwrite = false) {
if (overwrite) this.attributes.set(name, value);
else this.attributes.add(name, value);
if (overwrite) this.attributes.set(name, value)
else this.attributes.add(name, value)
return this;
};
return this
}
/** Copies point/path/snippet data from part orig into this */
Part.prototype.inject = function(orig) {
const findBasePoint = p => {
for (let i in orig.points) {
if (orig.points[i] === p) return i;
if (orig.points[i] === p) return i
}
return false;
};
return false
}
for (let i in orig.points) this.points[i] = orig.points[i].clone();
for (let i in orig.points) this.points[i] = orig.points[i].clone()
for (let i in orig.paths) {
this.paths[i] = orig.paths[i].clone();
this.paths[i] = orig.paths[i].clone()
// Keep link between points and path ops where possible
for (let j in orig.paths[i].ops) {
let op = orig.paths[i].ops[j];
if (op.type !== "close") {
let toPoint = findBasePoint(op.to);
if (toPoint) this.paths[i].ops[j].to = this.points[toPoint];
let op = orig.paths[i].ops[j]
if (op.type !== 'close') {
let toPoint = findBasePoint(op.to)
if (toPoint) this.paths[i].ops[j].to = this.points[toPoint]
}
if (op.type === "curve") {
let cp1Point = findBasePoint(op.cp1);
if (cp1Point) this.paths[i].ops[j].cp1 = this.points[cp1Point];
let cp2Point = findBasePoint(op.cp2);
if (cp2Point) this.paths[i].ops[j].cp2 = this.points[cp2Point];
if (op.type === 'curve') {
let cp1Point = findBasePoint(op.cp1)
if (cp1Point) this.paths[i].ops[j].cp1 = this.points[cp1Point]
let cp2Point = findBasePoint(op.cp2)
if (cp2Point) this.paths[i].ops[j].cp2 = this.points[cp2Point]
}
}
}
for (let i in orig.snippets) {
this.snippets[i] = orig.snippets[i].clone();
this.snippets[i] = orig.snippets[i].clone()
}
return this;
};
return this
}
Part.prototype.units = function(input) {
return utils.units(input, this.context.settings.units);
};
return utils.units(input, this.context.settings.units)
}
/** Returns an object with shorthand access for pattern design */
Part.prototype.shorthand = function() {
let complete = this.context.settings.complete ? true : false;
let paperless = this.context.settings.paperless === true ? true : false;
let sa = this.context.settings.complete ? this.context.settings.sa || 0 : 0;
let complete = this.context.settings.complete ? true : false
let paperless = this.context.settings.paperless === true ? true : false
let sa = this.context.settings.complete ? this.context.settings.sa || 0 : 0
return {
sa,
measurements: this.context.settings.measurements || {},
@ -214,7 +208,7 @@ Part.prototype.shorthand = function() {
complete,
paperless,
debug: this.debugClosure()
};
};
}
}
export default Part;
export default Part

File diff suppressed because it is too large Load diff

View file

@ -1,72 +1,63 @@
import { macroName, round, sampleStyle, capitalize } from "./utils";
import Part from "./part";
import Point from "./point";
import Path from "./path";
import Snippet from "./snippet";
import Svg from "./svg";
import pack from "bin-pack";
import Store from "./store";
import Hooks from "./hooks";
import Attributes from "./attributes";
import { macroName, round, sampleStyle, capitalize } from './utils'
import Part from './part'
import Point from './point'
import Path from './path'
import Snippet from './snippet'
import Svg from './svg'
import pack from 'bin-pack'
import Store from './store'
import Hooks from './hooks'
import Attributes from './attributes'
export default function Pattern(config = { options: {} }) {
this.config = config; // Pattern configuration
this.width = 0; // Will be set after render
this.height = 0; // Will be set after render
this.is = ""; // Will be set when drafting/sampling
this.config = config // Pattern configuration
this.width = 0 // Will be set after render
this.height = 0 // Will be set after render
this.is = '' // Will be set when drafting/sampling
this.store = new Store(); // Store for sharing data across parts
this.parts = {}; // Parts container
this.hooks = new Hooks(); // Hooks container
this.Point = Point; // Point constructor
this.Path = Path; // Path constructor
this.Snippet = Snippet; // Snippet constructor
this.Attributes = Attributes; // Attributes constructor
this.store = new Store() // Store for sharing data across parts
this.parts = {} // Parts container
this.hooks = new Hooks() // Hooks container
this.Point = Point // Point constructor
this.Path = Path // Path constructor
this.Snippet = Snippet // Snippet constructor
this.Attributes = Attributes // Attributes constructor
// Default settings
this.settings = {
complete: true,
idPrefix: "fs-",
locale: "en",
units: "metric",
idPrefix: 'fs-',
locale: 'en',
units: 'metric',
margin: 2,
layout: true,
options: {}
};
}
if (typeof this.config.dependencies === "undefined")
this.config.dependencies = {};
if (typeof this.config.inject === "undefined") this.config.inject = {};
if (typeof this.config.hide === "undefined") this.config.hide = [];
this.config.resolvedDependencies = this.resolveDependencies(
this.config.dependencies
);
this.config.draftOrder = this.draftOrder(this.config.resolvedDependencies);
if (typeof this.config.dependencies === 'undefined') this.config.dependencies = {}
if (typeof this.config.inject === 'undefined') this.config.inject = {}
if (typeof this.config.hide === 'undefined') this.config.hide = []
this.config.resolvedDependencies = this.resolveDependencies(this.config.dependencies)
this.config.draftOrder = this.draftOrder(this.config.resolvedDependencies)
// Convert options
for (let i in config.options) {
let option = config.options[i];
if (typeof option === "object") {
if (typeof option.pct !== "undefined")
this.settings.options[i] = option.pct / 100;
else if (typeof option.mm !== "undefined")
this.settings.options[i] = option.mm;
else if (typeof option.deg !== "undefined")
this.settings.options[i] = option.deg;
else if (typeof option.count !== "undefined")
this.settings.options[i] = option.count;
else if (typeof option.bool !== "undefined")
this.settings.options[i] = option.bool;
else if (typeof option.dflt !== "undefined")
this.settings.options[i] = option.dflt;
else throw new Error("Unknown option type: " + JSON.stringify(option));
let option = config.options[i]
if (typeof option === 'object') {
if (typeof option.pct !== 'undefined') this.settings.options[i] = option.pct / 100
else if (typeof option.mm !== 'undefined') this.settings.options[i] = option.mm
else if (typeof option.deg !== 'undefined') this.settings.options[i] = option.deg
else if (typeof option.count !== 'undefined') this.settings.options[i] = option.count
else if (typeof option.bool !== 'undefined') this.settings.options[i] = option.bool
else if (typeof option.dflt !== 'undefined') this.settings.options[i] = option.dflt
else throw new Error('Unknown option type: ' + JSON.stringify(option))
} else {
this.settings.options[i] = option;
this.settings.options[i] = option
}
}
// Macros
this.macros = {};
this.macros = {}
// Context object to add to Part closure
const context = {
@ -75,406 +66,385 @@ export default function Pattern(config = { options: {} }) {
settings: this.settings,
store: this.store,
macros: this.macros
};
}
// Part closure
this.Part = function() {
let part = new Part();
part.context = context;
let part = new Part()
part.context = context
for (let macro in context.macros) {
part[macroName(macro)] = context.macros[macro];
part[macroName(macro)] = context.macros[macro]
}
return part
}
return part;
};
}
// Merges settings object with this.settings
Pattern.prototype.apply = function(settings) {
if (typeof settings !== "object") return this;
if (typeof settings !== 'object') return this
for (let key of Object.keys(settings)) {
if (Array.isArray(settings[key])) {
if (Array.isArray(this.settings[key])) {
for (let entry of settings[key]) this.settings[key].push(entry);
} else this.settings[key] = settings[key];
} else if (typeof settings[key] === "object") {
for (let entry of settings[key]) this.settings[key].push(entry)
} else this.settings[key] = settings[key]
} else if (typeof settings[key] === 'object') {
this.settings[key] = {
...this.settings[key],
...settings[key]
};
} else this.settings[key] = settings[key];
}
} else this.settings[key] = settings[key]
}
return this;
};
return this
}
Pattern.prototype.runHooks = function(hookName, data = false) {
if (data === false) data = this;
let hooks = this.hooks[hookName];
if (data === false) data = this
let hooks = this.hooks[hookName]
if (hooks.length > 0) {
for (let hook of hooks) {
hook.method(data, hook.data);
hook.method(data, hook.data)
}
}
};
}
/**
* The default draft method with pre- and postDraft hooks
*/
Pattern.prototype.draft = function() {
if (this.is !== "sample") this.is = "draft";
this.runHooks("preDraft");
if (this.is !== 'sample') this.is = 'draft'
this.runHooks('preDraft')
for (let partName of this.config.draftOrder) {
this.parts[partName] = new this.Part();
if (typeof this.config.inject[partName] === "string") {
this.parts[partName].inject(this.parts[this.config.inject[partName]]);
this.parts[partName] = new this.Part()
if (typeof this.config.inject[partName] === 'string') {
this.parts[partName].inject(this.parts[this.config.inject[partName]])
}
if (this.needs(partName)) {
let method = "draft" + capitalize(partName);
if (typeof this[method] !== "function")
let method = 'draft' + capitalize(partName)
if (typeof this[method] !== 'function')
throw new Error('Method "' + method + '" on pattern object is not callable')
this.parts[partName] = this[method](this.parts[partName])
if (typeof this.parts[partName] === 'undefined')
throw new Error(
'Method "' + method + '" on pattern object is not callable'
);
this.parts[partName] = this[method](this.parts[partName]);
if (typeof this.parts[partName] === "undefined")
throw new Error(
"Result of " +
method +
"() was undefined. Did you forget to return the Part object?"
);
'Result of ' + method + '() was undefined. Did you forget to return the Part object?'
)
this.parts[partName].render =
this.parts[partName].render === false ? false : this.wants(partName);
this.parts[partName].render === false ? false : this.wants(partName)
} else {
this.parts[partName].render = false;
this.parts[partName].render = false
}
}
this.runHooks("postDraft");
this.runHooks('postDraft')
return this;
};
return this
}
/**
* Handles pattern sampling
*/
Pattern.prototype.sample = function() {
if (this.settings.sample.type === "option") {
return this.sampleOption(this.settings.sample.option);
} else if (this.settings.sample.type === "measurement") {
return this.sampleMeasurement(this.settings.sample.measurement);
} else if (this.settings.sample.type === "models") {
return this.sampleModels(
this.settings.sample.models,
this.settings.sample.focus || false
);
if (this.settings.sample.type === 'option') {
return this.sampleOption(this.settings.sample.option)
} else if (this.settings.sample.type === 'measurement') {
return this.sampleMeasurement(this.settings.sample.measurement)
} else if (this.settings.sample.type === 'models') {
return this.sampleModels(this.settings.sample.models, this.settings.sample.focus || false)
}
};
}
Pattern.prototype.sampleParts = function() {
let parts = {};
this.settings.complete = false;
this.settings.paperless = false;
this.draft();
let parts = {}
this.settings.complete = false
this.settings.paperless = false
this.draft()
for (let i in this.parts) {
parts[i] = new this.Part();
parts[i].render = this.parts[i].render;
parts[i] = new this.Part()
parts[i].render = this.parts[i].render
}
return parts;
};
return parts
}
Pattern.prototype.sampleRun = function(
parts,
anchors,
run,
runs,
extraClass = false
) {
this.draft();
Pattern.prototype.sampleRun = function(parts, anchors, run, runs, extraClass = false) {
this.draft()
for (let i in this.parts) {
let anchor = false;
let dx = 0;
let dy = 0;
let anchor = false
let dx = 0
let dy = 0
if (this.parts[i].points.anchor) {
if (typeof anchors[i] === "undefined")
anchors[i] = this.parts[i].points.anchor;
if (typeof anchors[i] === 'undefined') anchors[i] = this.parts[i].points.anchor
else {
if (!anchors[i].sitsOn(this.parts[i].points.anchor)) {
dx = this.parts[i].points.anchor.dx(anchors[i]);
dy = this.parts[i].points.anchor.dy(anchors[i]);
dx = this.parts[i].points.anchor.dx(anchors[i])
dy = this.parts[i].points.anchor.dy(anchors[i])
}
}
}
for (let j in this.parts[i].paths) {
parts[i].paths[j + "_" + run] = this.parts[i].paths[j]
parts[i].paths[j + '_' + run] = this.parts[i].paths[j]
.clone()
.attr("style", sampleStyle(run, runs));
.attr('style', sampleStyle(run, runs))
if (this.parts[i].points.anchor)
parts[i].paths[j + "_" + run] = parts[i].paths[j + "_" + run].translate(
dx,
dy
);
if (extraClass !== false)
parts[i].paths[j + "_" + run].attributes.add("class", extraClass);
parts[i].paths[j + '_' + run] = parts[i].paths[j + '_' + run].translate(dx, dy)
if (extraClass !== false) parts[i].paths[j + '_' + run].attributes.add('class', extraClass)
}
}
};
}
/**
* Handles option sampling
*/
Pattern.prototype.sampleOption = function(optionName) {
this.is = "sample";
this.runHooks("preSample");
let step, val;
let factor = 1;
let anchors = {};
let parts = this.sampleParts();
let option = this.config.options[optionName];
if (typeof option.list === "object") {
return this.sampleListOption(optionName);
this.is = 'sample'
this.runHooks('preSample')
let step, val
let factor = 1
let anchors = {}
let parts = this.sampleParts()
let option = this.config.options[optionName]
if (typeof option.list === 'object') {
return this.sampleListOption(optionName)
}
if (typeof option.min === "undefined" || typeof option.max === "undefined") {
let min = option * 0.9;
let max = option * 1.1;
option = { min, max };
if (typeof option.min === 'undefined' || typeof option.max === 'undefined') {
let min = option * 0.9
let max = option * 1.1
option = { min, max }
}
if (typeof option.pct !== "undefined") factor = 100;
val = option.min / factor;
step = (option.max / factor - val) / 9;
if (typeof option.pct !== 'undefined') factor = 100
val = option.min / factor
step = (option.max / factor - val) / 9
for (let run = 1; run < 11; run++) {
this.settings.options[optionName] = val;
this.settings.options[optionName] = val
this.debug({
type: "info",
label: "🏃🏿‍♀️ Sample run",
type: 'info',
label: '🏃🏿‍♀️ Sample run',
msg: `Sampling option ${optionName} with value ${round(val)}`
});
this.sampleRun(parts, anchors, run, 10);
val += step;
})
this.sampleRun(parts, anchors, run, 10)
val += step
}
this.parts = parts;
this.runHooks("postSample");
this.parts = parts
this.runHooks('postSample')
return this;
};
return this
}
Pattern.prototype.sampleListOption = function(optionName) {
let parts = this.sampleParts();
let option = this.config.options[optionName];
let anchors = {};
let run = 1;
let runs = option.list.length;
let parts = this.sampleParts()
let option = this.config.options[optionName]
let anchors = {}
let run = 1
let runs = option.list.length
for (let val of option.list) {
this.settings.options[optionName] = val;
this.settings.options[optionName] = val
this.debug({
type: "info",
label: "🏃🏿‍♀️ Sample run",
type: 'info',
label: '🏃🏿‍♀️ Sample run',
msg: `Sampling option ${optionName} with value ${round(val)}`
});
this.sampleRun(parts, anchors, run, runs);
run++;
})
this.sampleRun(parts, anchors, run, runs)
run++
}
this.parts = parts;
this.parts = parts
return this;
};
return this
}
/**
* Handles measurement sampling
*/
Pattern.prototype.sampleMeasurement = function(measurementName) {
this.is = "sample";
this.runHooks("preSample");
let anchors = {};
let parts = this.sampleParts();
let val = this.settings.measurements[measurementName];
this.is = 'sample'
this.runHooks('preSample')
let anchors = {}
let parts = this.sampleParts()
let val = this.settings.measurements[measurementName]
if (val === undefined)
throw new Error(
"Cannot sample a measurement that is undefined: " + measurementName
);
let step = val / 50;
val = val * 0.9;
throw new Error('Cannot sample a measurement that is undefined: ' + measurementName)
let step = val / 50
val = val * 0.9
for (let run = 1; run < 11; run++) {
this.settings.measurements[measurementName] = val;
this.settings.measurements[measurementName] = val
this.debug({
type: "info",
label: "🏃🏿‍♀️ Sample run",
type: 'info',
label: '🏃🏿‍♀️ Sample run',
msg: `Sampling option ${measurementName} with value ${round(val)}`
});
this.sampleRun(parts, anchors, run, 10);
val += step;
})
this.sampleRun(parts, anchors, run, 10)
val += step
}
this.parts = parts;
this.runHooks("postSample");
this.parts = parts
this.runHooks('postSample')
return this;
};
return this
}
/**
* Handles models sampling
*/
Pattern.prototype.sampleModels = function(models, focus = false) {
this.is = "sample";
this.runHooks("preSample");
let anchors = {};
let parts = this.sampleParts();
let run = 0;
let runs = Object.keys(models).length;
this.is = 'sample'
this.runHooks('preSample')
let anchors = {}
let parts = this.sampleParts()
let run = 0
let runs = Object.keys(models).length
for (let l in models) {
run++;
this.settings.measurements = models[l];
run++
this.settings.measurements = models[l]
this.debug({
type: "info",
label: "🏃🏿‍♀️ Sample run",
type: 'info',
label: '🏃🏿‍♀️ Sample run',
msg: `Sampling model ${l}`
});
let className = l === focus ? "sample-focus" : "";
this.sampleRun(parts, anchors, run, runs, className);
})
let className = l === focus ? 'sample-focus' : ''
this.sampleRun(parts, anchors, run, runs, className)
}
this.parts = parts;
this.runHooks("postSample");
this.parts = parts
this.runHooks('postSample')
return this;
};
return this
}
/** Debug method, exposes debug hook */
Pattern.prototype.debug = function(data) {
this.runHooks("debug", data);
};
this.runHooks('debug', data)
}
Pattern.prototype.render = function() {
this.svg = new Svg(this);
this.svg.hooks = this.hooks;
this.svg = new Svg(this)
this.svg.hooks = this.hooks
return this.pack().svg.render(this);
};
return this.pack().svg.render(this)
}
Pattern.prototype.on = function(hook, method, data) {
this.hooks[hook].push({ method, data });
};
this.hooks[hook].push({ method, data })
}
Pattern.prototype.use = function(plugin, data = false) {
this.debug({
type: "success",
label: "🔌 Plugin loaded",
type: 'success',
label: '🔌 Plugin loaded',
msg: `${plugin.name} v${plugin.version}`
});
if (plugin.hooks) this.loadPluginHooks(plugin, data);
if (plugin.macros) this.loadPluginMacros(plugin);
})
if (plugin.hooks) this.loadPluginHooks(plugin, data)
if (plugin.macros) this.loadPluginMacros(plugin)
return this;
};
return this
}
Pattern.prototype.loadPluginHooks = function(plugin, data) {
for (let hook of Object.keys(this.hooks)) {
if (typeof plugin.hooks[hook] === "function") {
this.on(hook, plugin.hooks[hook], data);
if (typeof plugin.hooks[hook] === 'function') {
this.on(hook, plugin.hooks[hook], data)
} else if (Array.isArray(plugin.hooks[hook])) {
for (let method of plugin.hooks[hook]) {
this.on(hook, method, data);
this.on(hook, method, data)
}
}
}
};
}
Pattern.prototype.loadPluginMacros = function(plugin) {
for (let macro in plugin.macros) {
if (typeof plugin.macros[macro] === "function") {
this.macro(macro, plugin.macros[macro]);
if (typeof plugin.macros[macro] === 'function') {
this.macro(macro, plugin.macros[macro])
}
}
};
}
Pattern.prototype.macro = function(key, method) {
this.macros[key] = method;
};
this.macros[key] = method
}
/** Packs parts in a 2D space and sets pattern size */
Pattern.prototype.pack = function() {
let bins = [];
let bins = []
for (let key in this.parts) {
let part = this.parts[key];
let part = this.parts[key]
// Avoid multiple render calls to cause stacking of transforms
part.attributes.remove("transform");
part.attributes.remove('transform')
if (part.render) {
part.stack();
let width = part.bottomRight.x - part.topLeft.x;
let height = part.bottomRight.y - part.topLeft.y;
if (this.settings.layout === true) bins.push({ id: key, width, height });
part.stack()
let width = part.bottomRight.x - part.topLeft.x
let height = part.bottomRight.y - part.topLeft.y
if (this.settings.layout === true) bins.push({ id: key, width, height })
else {
if (this.width < width) this.width = width;
if (this.height < height) this.height = height;
if (this.width < width) this.width = width
if (this.height < height) this.height = height
}
}
}
if (this.settings.layout === true) {
let size = pack(bins, { inPlace: true });
let size = pack(bins, { inPlace: true })
for (let bin of bins) {
let part = this.parts[bin.id];
if (bin.x !== 0 || bin.y !== 0)
part.attr("transform", `translate (${bin.x}, ${bin.y})`);
let part = this.parts[bin.id]
if (bin.x !== 0 || bin.y !== 0) part.attr('transform', `translate (${bin.x}, ${bin.y})`)
}
this.width = size.width;
this.height = size.height;
} else if (typeof this.settings.layout === "object") {
this.width = this.settings.layout.width;
this.height = this.settings.layout.height;
this.width = size.width
this.height = size.height
} else if (typeof this.settings.layout === 'object') {
this.width = this.settings.layout.width
this.height = this.settings.layout.height
for (let partId of Object.keys(this.settings.layout.parts)) {
let transforms = this.settings.layout.parts[partId];
let transforms = this.settings.layout.parts[partId]
// Moving
if (typeof transforms.move === "object") {
if (typeof transforms.move === 'object') {
this.parts[partId].attributes.set(
"transform",
"translate(" + transforms.move.x + ", " + transforms.move.y + ")"
);
'transform',
'translate(' + transforms.move.x + ', ' + transforms.move.y + ')'
)
}
// Mirrorring
let center = this.parts[partId].topLeft.shiftFractionTowards(
this.parts[partId].bottomRight,
0.5
);
let anchor = { x: 0, y: 0 };
)
let anchor = { x: 0, y: 0 }
if (transforms.flipX) {
let dx = anchor.x - center.x;
let transform = `translate(${center.x * -1}, ${center.y * -1})`;
transform += " scale(-1, 1)";
transform += ` translate(${center.x * -1 + 2 * dx}, ${center.y})`;
this.parts[partId].attributes.add("transform", transform);
let dx = anchor.x - center.x
let transform = `translate(${center.x * -1}, ${center.y * -1})`
transform += ' scale(-1, 1)'
transform += ` translate(${center.x * -1 + 2 * dx}, ${center.y})`
this.parts[partId].attributes.add('transform', transform)
}
if (transforms.flipY) {
let dy = anchor.y - center.y;
let transform = `translate(${center.x * -1}, ${center.y * -1})`;
transform += " scale(1, -1)";
transform += ` translate(${center.x}, ${center.y * -1 + 2 * dy})`;
this.parts[partId].attributes.add("transform", transform);
let dy = anchor.y - center.y
let transform = `translate(${center.x * -1}, ${center.y * -1})`
transform += ' scale(1, -1)'
transform += ` translate(${center.x}, ${center.y * -1 + 2 * dy})`
this.parts[partId].attributes.add('transform', transform)
}
if (transforms.rotate) {
let transform = `rotate(${transforms.rotate}, ${center.x -
anchor.x}, ${center.y - anchor.y})`;
this.parts[partId].attributes.add("transform", transform);
let transform = `rotate(${transforms.rotate}, ${center.x - anchor.x}, ${center.y -
anchor.y})`
this.parts[partId].attributes.add('transform', transform)
}
}
}
return this;
};
return this
}
/** Determines the order to draft parts in, based on dependencies */
Pattern.prototype.draftOrder = function(graph = this.resolveDependencies()) {
let sorted = [];
let visited = {};
let sorted = []
let visited = {}
Object.keys(graph).forEach(function visit(name, ancestors) {
if (!Array.isArray(ancestors)) ancestors = [];
ancestors.push(name);
visited[name] = true;
if (typeof graph[name] !== "undefined") {
if (!Array.isArray(ancestors)) ancestors = []
ancestors.push(name)
visited[name] = true
if (typeof graph[name] !== 'undefined') {
graph[name].forEach(function(dep) {
if (visited[dep]) return;
visit(dep, ancestors.slice(0));
});
if (visited[dep]) return
visit(dep, ancestors.slice(0))
})
}
if (sorted.indexOf(name) < 0) sorted.push(name);
});
if (sorted.indexOf(name) < 0) sorted.push(name)
})
return sorted;
};
return sorted
}
/** Recursively solves part dependencies for a part */
Pattern.prototype.resolveDependency = function(
@ -483,135 +453,119 @@ Pattern.prototype.resolveDependency = function(
graph = this.config.dependencies,
deps = []
) {
if (typeof seen[part] === "undefined") seen[part] = true;
if (typeof graph[part] === "string") {
if (deps.indexOf(graph[part]) === -1) deps.push(graph[part]);
return this.resolveDependency(seen, graph[part], graph, deps);
if (typeof seen[part] === 'undefined') seen[part] = true
if (typeof graph[part] === 'string') {
if (deps.indexOf(graph[part]) === -1) deps.push(graph[part])
return this.resolveDependency(seen, graph[part], graph, deps)
} else if (Array.isArray(graph[part])) {
if (graph[part].length === 0) return [];
if (graph[part].length === 0) return []
else {
if (deps.length === 0) deps = graph[part];
for (let apart of graph[part])
deps.concat(this.resolveDependency(seen, apart, graph, deps));
if (deps.length === 0) deps = graph[part]
for (let apart of graph[part]) deps.concat(this.resolveDependency(seen, apart, graph, deps))
}
}
return deps;
};
return deps
}
/** Resolves part dependencies into a flat array */
Pattern.prototype.resolveDependencies = function(
graph = this.config.dependencies
) {
Pattern.prototype.resolveDependencies = function(graph = this.config.dependencies) {
for (let i in this.config.inject) {
let dependency = this.config.inject[i];
if (typeof this.config.dependencies[i] === "undefined")
this.config.dependencies[i] = dependency;
let dependency = this.config.inject[i]
if (typeof this.config.dependencies[i] === 'undefined') this.config.dependencies[i] = dependency
else if (this.config.dependencies[i] !== dependency) {
if (typeof this.config.dependencies[i] === "string")
this.config.dependencies[i] = [this.config.dependencies[i], dependency];
if (typeof this.config.dependencies[i] === 'string')
this.config.dependencies[i] = [this.config.dependencies[i], dependency]
else if (Array.isArray(this.config.dependencies[i])) {
if (this.config.dependencies[i].indexOf(dependency) === -1)
this.config.dependencies[i].push(dependency);
} else
throw new Error(
"Part dependencies should be a string or an array of strings"
);
this.config.dependencies[i].push(dependency)
} else throw new Error('Part dependencies should be a string or an array of strings')
}
// Parts both in the parts and dependencies array trip up the dependency resolver
if (Array.isArray(this.config.parts)) {
let pos = this.config.parts.indexOf(this.config.inject[i]);
if (pos !== -1) this.config.parts.splice(pos, 1);
let pos = this.config.parts.indexOf(this.config.inject[i])
if (pos !== -1) this.config.parts.splice(pos, 1)
}
}
// Include parts outside the dependency graph
if (Array.isArray(this.config.parts)) {
for (let part of this.config.parts) {
if (typeof this.config.dependencies[part] === "undefined")
this.config.dependencies[part] = [];
if (typeof this.config.dependencies[part] === 'undefined') this.config.dependencies[part] = []
}
}
let resolved = {};
let seen = {};
for (let part in graph)
resolved[part] = this.resolveDependency(seen, part, graph);
for (let part in seen)
if (typeof resolved[part] === "undefined") resolved[part] = [];
let resolved = {}
let seen = {}
for (let part in graph) resolved[part] = this.resolveDependency(seen, part, graph)
for (let part in seen) if (typeof resolved[part] === 'undefined') resolved[part] = []
return resolved;
};
return resolved
}
/** Determines whether a part is needed
* This depends on the 'only' setting and the
* configured dependencies.
*/
Pattern.prototype.needs = function(partName) {
if (typeof this.settings.only === "undefined" || this.settings.only === false)
return true;
else if (typeof this.settings.only === "string") {
if (this.settings.only === partName) return true;
if (typeof this.settings.only === 'undefined' || this.settings.only === false) return true
else if (typeof this.settings.only === 'string') {
if (this.settings.only === partName) return true
if (Array.isArray(this.config.resolvedDependencies[this.settings.only])) {
for (let dependency of this.config.resolvedDependencies[
this.settings.only
]) {
if (dependency === partName) return true;
for (let dependency of this.config.resolvedDependencies[this.settings.only]) {
if (dependency === partName) return true
}
}
} else if (Array.isArray(this.settings.only)) {
for (let part of this.settings.only) {
if (part === partName) return true;
if (part === partName) return true
for (let dependency of this.config.resolvedDependencies[part]) {
if (dependency === partName) return true;
if (dependency === partName) return true
}
}
}
return false;
};
return false
}
/* Checks whether a part is hidden in the config */
Pattern.prototype.isHidden = function(partName) {
if (Array.isArray(this.config.hide)) {
if (this.config.hide.indexOf(partName) !== -1) return true;
if (this.config.hide.indexOf(partName) !== -1) return true
}
return false;
};
return false
}
/** Determines whether a part is wanted by the user
* This depends on the 'only' setting
*/
Pattern.prototype.wants = function(partName) {
if (
typeof this.settings.only === "undefined" ||
this.settings.only === false
) {
if (this.isHidden(partName)) return false;
} else if (typeof this.settings.only === "string") {
if (this.settings.only === partName) return true;
return false;
if (typeof this.settings.only === 'undefined' || this.settings.only === false) {
if (this.isHidden(partName)) return false
} else if (typeof this.settings.only === 'string') {
if (this.settings.only === partName) return true
return false
} else if (Array.isArray(this.settings.only)) {
for (let part of this.settings.only) {
if (part === partName) return true;
if (part === partName) return true
}
return false;
return false
}
return true;
};
return true
}
/** Returns props required to render this pattern through
* an external renderer (eg. a React component)
*/
Pattern.prototype.getRenderProps = function() {
this.pack();
let props = {};
props.width = this.width;
props.height = this.height;
props.settings = this.settings;
props.parts = {};
this.pack()
let props = {}
props.width = this.width
props.height = this.height
props.settings = this.settings
props.parts = {}
for (let p in this.parts) {
if (this.parts[p].render) {
props.parts[p] = {
@ -623,9 +577,9 @@ Pattern.prototype.getRenderProps = function() {
width: this.parts[p].width,
bottomRight: this.parts[p].bottomRight,
topLeft: this.parts[p].topLeft
};
}
}
}
return props;
};
return props
}

View file

@ -1,142 +1,139 @@
import Attributes from "./attributes";
import { round } from "./utils";
import Attributes from './attributes'
import { round } from './utils'
function Point(x, y) {
this.x = round(x);
this.y = round(y);
this.attributes = new Attributes();
this.x = round(x)
this.y = round(y)
this.attributes = new Attributes()
}
/** Radians to degrees */
Point.prototype.rad2deg = function(radians) {
return radians * 57.29577951308232;
};
return radians * 57.29577951308232
}
/** Degrees to radians */
Point.prototype.deg2rad = function(degrees) {
return degrees / 57.29577951308232;
};
return degrees / 57.29577951308232
}
/** Adds an attribute. This is here to make this call chainable in assignment */
Point.prototype.attr = function(name, value, overwrite = false) {
if (overwrite) this.attributes.set(name, value);
else this.attributes.add(name, value);
if (overwrite) this.attributes.set(name, value)
else this.attributes.add(name, value)
return this;
};
return this
}
/** Returns the distance between this point and that point */
Point.prototype.dist = function(that) {
let dx = this.x - that.x;
let dy = this.y - that.y;
let dx = this.x - that.x
let dy = this.y - that.y
return round(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)));
};
return round(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)))
}
/** Returns slope of a line made by this point and that point */
Point.prototype.slope = function(that) {
return (that.y - this.y) / (that.x - this.x);
};
return (that.y - this.y) / (that.x - this.x)
}
/** Returns the x-delta between this point and that point */
Point.prototype.dx = function(that) {
return that.x - this.x;
};
return that.x - this.x
}
/** Returns the y-delta between this point and that point */
Point.prototype.dy = function(that) {
return that.y - this.y;
};
return that.y - this.y
}
/** Returns the angle between this point and that point */
Point.prototype.angle = function(that) {
let rad = Math.atan2(-1 * this.dy(that), this.dx(that));
while (rad < 0) rad += 2 * Math.PI;
let rad = Math.atan2(-1 * this.dy(that), this.dx(that))
while (rad < 0) rad += 2 * Math.PI
return this.rad2deg(rad);
};
return this.rad2deg(rad)
}
/** Rotate this point deg around that point */
Point.prototype.rotate = function(deg, that) {
let radius = this.dist(that);
let angle = this.angle(that);
let x = that.x + radius * Math.cos(this.deg2rad(angle + deg)) * -1;
let y = that.y + radius * Math.sin(this.deg2rad(angle + deg));
let radius = this.dist(that)
let angle = this.angle(that)
let x = that.x + radius * Math.cos(this.deg2rad(angle + deg)) * -1
let y = that.y + radius * Math.sin(this.deg2rad(angle + deg))
return new Point(x, y);
};
return new Point(x, y)
}
/** returns an identical copy of this point */
Point.prototype.copy = function() {
return new Point(this.x, this.y);
};
return new Point(this.x, this.y)
}
/** Mirrors this point around X value of that point */
Point.prototype.flipX = function(that = false) {
if (that === false || that.x === 0) return new Point(this.x * -1, this.y);
else return new Point(that.x + this.dx(that), this.y);
};
if (that === false || that.x === 0) return new Point(this.x * -1, this.y)
else return new Point(that.x + this.dx(that), this.y)
}
/** Mirrors this point around Y value of that point */
Point.prototype.flipY = function(that = false) {
if (that === false || that.y === 0) return new Point(this.x, this.y * -1);
else return new Point(this.x, that.y + this.dy(that));
};
if (that === false || that.y === 0) return new Point(this.x, this.y * -1)
else return new Point(this.x, that.y + this.dy(that))
}
/** Shifts this point distance in the deg direction */
Point.prototype.shift = function(deg, distance) {
let p = this.copy();
p.x += distance;
let p = this.copy()
p.x += distance
return p.rotate(deg, this);
};
return p.rotate(deg, this)
}
/** Shifts this point distance in the direction of that point */
Point.prototype.shiftTowards = function(that, distance) {
return this.shift(this.angle(that), distance);
};
return this.shift(this.angle(that), distance)
}
/** Checks whether this has the same coordinates as that */
Point.prototype.sitsOn = function(that) {
if (this.x === that.x && this.y === that.y) return true;
else return false;
};
if (this.x === that.x && this.y === that.y) return true
else return false
}
/** Checks whether this has roughly the same coordinates as that */
Point.prototype.sitsRoughlyOn = function(that) {
if (
Math.round(this.x) === Math.round(that.x) &&
Math.round(this.y) === Math.round(that.y)
)
return true;
else return false;
};
if (Math.round(this.x) === Math.round(that.x) && Math.round(this.y) === Math.round(that.y))
return true
else return false
}
/** Shifts this point fraction of the distance towards that point */
Point.prototype.shiftFractionTowards = function(that, fraction) {
return this.shiftTowards(that, this.dist(that) * fraction);
};
return this.shiftTowards(that, this.dist(that) * fraction)
}
/** Shifts this point distance beyond that point */
Point.prototype.shiftOutwards = function(that, distance) {
return this.shiftTowards(that, this.dist(that) + distance);
};
return this.shiftTowards(that, this.dist(that) + distance)
}
/** Returns a deep copy of this */
Point.prototype.clone = function() {
let clone = new Point(this.x, this.y);
clone.attributes = this.attributes.clone();
let clone = new Point(this.x, this.y)
clone.attributes = this.attributes.clone()
return clone;
};
return clone
}
/** Applies a translate transform */
Point.prototype.translate = function(x, y) {
let p = this.copy();
p.x += x;
p.y += y;
let p = this.copy()
p.x += x
p.y += y
return p;
};
return p
}
export default Point;
export default Point

View file

@ -1,27 +1,27 @@
import Attributes from "./attributes";
import Attributes from './attributes'
function Snippet(def, anchor) {
this.def = def;
this.anchor = anchor;
this.attributes = new Attributes();
this.def = def
this.anchor = anchor
this.attributes = new Attributes()
return this;
return this
}
/** Adds an attribute. This is here to make this call chainable in assignment */
Snippet.prototype.attr = function(name, value, overwrite = false) {
if (overwrite) this.attributes.set(name, value);
else this.attributes.add(name, value);
if (overwrite) this.attributes.set(name, value)
else this.attributes.add(name, value)
return this;
};
return this
}
/** Returns a deep copy of this */
Snippet.prototype.clone = function() {
let clone = new Snippet(this.def, this.anchor.clone());
clone.attributes = this.attributes.clone();
let clone = new Snippet(this.def, this.anchor.clone())
clone.attributes = this.attributes.clone()
return clone;
};
return clone
}
export default Snippet;
export default Snippet

View file

@ -1,20 +1,20 @@
function Store() {
this.data = new Map();
this.data = new Map()
}
/** Sets a value under index key */
Store.prototype.set = function(key, value) {
this.data.set(key, value);
};
this.data.set(key, value)
}
/** Sets a value under index key */
Store.prototype.setIfUnset = function(key, value) {
if (!this.data.has(key)) this.data.set(key, value);
};
if (!this.data.has(key)) this.data.set(key, value)
}
/** Gets a value under index key */
Store.prototype.get = function(key) {
return this.data.get(key);
};
return this.data.get(key)
}
export default Store;
export default Store

View file

@ -1,319 +1,306 @@
import Attributes from "./attributes";
import Attributes from './attributes'
import { version } from "../package.json";
import { version } from '../package.json'
function Svg(pattern) {
this.openGroups = [];
this.layout = {};
this.freeId = 0;
this.body = "";
this.style = "";
this.script = "";
this.defs = "";
this.pattern = pattern; // Needed to expose pattern to hooks
this.prefix = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
this.attributes = new Attributes();
this.attributes.add("xmlns", "http://www.w3.org/2000/svg");
this.attributes.add("xmlns:svg", "http://www.w3.org/2000/svg");
this.attributes.add("xmlns:xlink", "http://www.w3.org/1999/xlink");
this.attributes.add("xml:lang", pattern.settings.locale);
this.attributes.add(
"xmlns:freesewing",
"http://freesewing.org/namespaces/freesewing"
);
this.attributes.add("freesewing", version);
this.openGroups = []
this.layout = {}
this.freeId = 0
this.body = ''
this.style = ''
this.script = ''
this.defs = ''
this.pattern = pattern // Needed to expose pattern to hooks
this.prefix = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
this.attributes = new Attributes()
this.attributes.add('xmlns', 'http://www.w3.org/2000/svg')
this.attributes.add('xmlns:svg', 'http://www.w3.org/2000/svg')
this.attributes.add('xmlns:xlink', 'http://www.w3.org/1999/xlink')
this.attributes.add('xml:lang', pattern.settings.locale)
this.attributes.add('xmlns:freesewing', 'http://freesewing.org/namespaces/freesewing')
this.attributes.add('freesewing', version)
}
Svg.prototype.runHooks = function(hookName, data = false) {
if (data === false) data = this;
let hooks = this.hooks[hookName];
if (data === false) data = this
let hooks = this.hooks[hookName]
if (hooks.length > 0) {
for (let hook of hooks) {
hook.method(data, hook.data);
hook.method(data, hook.data)
}
}
};
}
/** Runs insertText hooks */
Svg.prototype.insertText = function(text) {
if (this.hooks.insertText.length > 0) {
for (let hook of this.hooks.insertText)
text = hook.method(this.pattern.settings.locale, text, hook.data);
text = hook.method(this.pattern.settings.locale, text, hook.data)
}
return text;
};
return text
}
/** Debug method, exposes debug hook */
Svg.prototype.debug = function() {};
Svg.prototype.debug = function() {}
/** Renders a draft object as SVG */
Svg.prototype.render = function(pattern) {
this.idPrefix = pattern.settings.idPrefix;
this.runHooks("preRender");
this.idPrefix = pattern.settings.idPrefix
this.runHooks('preRender')
if (!pattern.settings.embed) {
this.attributes.add("width", pattern.width + "mm");
this.attributes.add("height", pattern.height + "mm");
this.attributes.add('width', pattern.width + 'mm')
this.attributes.add('height', pattern.height + 'mm')
}
this.attributes.add("viewBox", `0 0 ${pattern.width} ${pattern.height}`);
this.head = this.renderHead();
this.tail = this.renderTail();
this.svg = "";
this.layout = {}; // Reset layout
this.attributes.add('viewBox', `0 0 ${pattern.width} ${pattern.height}`)
this.head = this.renderHead()
this.tail = this.renderTail()
this.svg = ''
this.layout = {} // Reset layout
for (let partId in pattern.parts) {
let part = pattern.parts[partId];
let part = pattern.parts[partId]
if (part.render) {
let partSvg = this.renderPart(part);
let partSvg = this.renderPart(part)
this.layout[partId] = {
svg: partSvg,
transform: part.attributes.getAsArray("transform")
};
this.svg += this.openGroup(
`${this.idPrefix}part-${partId}`,
part.attributes
);
this.svg += partSvg;
this.svg += this.closeGroup();
transform: part.attributes.getAsArray('transform')
}
this.svg += this.openGroup(`${this.idPrefix}part-${partId}`, part.attributes)
this.svg += partSvg
this.svg += this.closeGroup()
}
}
this.svg =
this.prefix + this.renderSvgTag() + this.head + this.svg + this.tail;
this.runHooks("postRender");
this.svg = this.prefix + this.renderSvgTag() + this.head + this.svg + this.tail
this.runHooks('postRender')
return this.svg;
};
return this.svg
}
/** Renders SVG head section */
Svg.prototype.renderHead = function() {
let svg = this.renderStyle();
svg += this.renderScript();
svg += this.renderDefs();
svg += this.openGroup(this.idPrefix + "container");
let svg = this.renderStyle()
svg += this.renderScript()
svg += this.renderDefs()
svg += this.openGroup(this.idPrefix + 'container')
return svg;
};
return svg
}
/** Renders SVG closing section */
Svg.prototype.renderTail = function() {
let svg = "";
svg += this.closeGroup();
svg += this.nl() + "</svg>";
let svg = ''
svg += this.closeGroup()
svg += this.nl() + '</svg>'
return svg;
};
return svg
}
/** Returns SVG code for the opening SVG tag */
Svg.prototype.renderSvgTag = function() {
let svg = "<svg";
this.indent();
svg += this.nl() + this.attributes.render();
this.outdent();
svg += this.nl() + ">" + this.nl();
let svg = '<svg'
this.indent()
svg += this.nl() + this.attributes.render()
this.outdent()
svg += this.nl() + '>' + this.nl()
return svg;
};
return svg
}
/** Returns SVG code for the style block */
Svg.prototype.renderStyle = function() {
let svg = '<style type="text/css"> <![CDATA[ ';
this.indent();
svg += this.nl() + this.style;
this.outdent();
svg += this.nl() + "]]>" + this.nl() + "</style>" + this.nl();
return svg;
};
let svg = '<style type="text/css"> <![CDATA[ '
this.indent()
svg += this.nl() + this.style
this.outdent()
svg += this.nl() + ']]>' + this.nl() + '</style>' + this.nl()
return svg
}
/** Returns SVG code for the script block */
Svg.prototype.renderScript = function() {
let svg = '<script type="text/javascript"> <![CDATA[';
this.indent();
svg += this.nl() + this.script;
this.outdent();
svg += this.nl() + "]]>" + this.nl() + "</script>" + this.nl();
let svg = '<script type="text/javascript"> <![CDATA['
this.indent()
svg += this.nl() + this.script
this.outdent()
svg += this.nl() + ']]>' + this.nl() + '</script>' + this.nl()
return svg;
};
return svg
}
/** Returns SVG code for the defs block */
Svg.prototype.renderDefs = function() {
let svg = "<defs>";
this.indent();
svg += this.nl() + this.defs;
this.outdent();
svg += this.nl() + "</defs>" + this.nl();
let svg = '<defs>'
this.indent()
svg += this.nl() + this.defs
this.outdent()
svg += this.nl() + '</defs>' + this.nl()
return svg;
};
return svg
}
/** Returns SVG code for a Part object */
Svg.prototype.renderPart = function(part) {
let svg = "";
let svg = ''
for (let key in part.paths) {
let path = part.paths[key];
if (path.render) svg += this.renderPath(path);
let path = part.paths[key]
if (path.render) svg += this.renderPath(path)
}
for (let key in part.points) {
if (part.points[key].attributes.get("data-text")) {
svg += this.renderText(part.points[key]);
if (part.points[key].attributes.get('data-text')) {
svg += this.renderText(part.points[key])
}
if (part.points[key].attributes.get("data-circle")) {
svg += this.renderCircle(part.points[key]);
if (part.points[key].attributes.get('data-circle')) {
svg += this.renderCircle(part.points[key])
}
}
for (let key in part.snippets) {
let snippet = part.snippets[key];
svg += this.renderSnippet(snippet, part);
let snippet = part.snippets[key]
svg += this.renderSnippet(snippet, part)
}
return svg;
};
return svg
}
/** Returns SVG code for a Path object */
Svg.prototype.renderPath = function(path) {
if (!path.attributes.get("id"))
path.attributes.add("id", this.idPrefix + this.getId());
path.attributes.set("d", path.asPathstring());
if (!path.attributes.get('id')) path.attributes.add('id', this.idPrefix + this.getId())
path.attributes.set('d', path.asPathstring())
return `${this.nl()}<path ${path.attributes.render()} />${this.renderPathText(
path
)}`;
};
return `${this.nl()}<path ${path.attributes.render()} />${this.renderPathText(path)}`
}
Svg.prototype.renderPathText = function(path) {
let text = path.attributes.get("data-text");
if (!text) return "";
else this.text = this.insertText(text);
let attributes = path.attributes.renderIfPrefixIs("data-text-");
let text = path.attributes.get('data-text')
if (!text) return ''
else this.text = this.insertText(text)
let attributes = path.attributes.renderIfPrefixIs('data-text-')
// Sadly aligning text along a patch can't be done in CSS only
let offset = "";
let align = path.attributes.get("data-text-class");
if (align && align.indexOf("center") > -1) offset = ' startOffset="50%" ';
else if (align && align.indexOf("right") > -1)
offset = ' startOffset="100%" ';
let svg = this.nl() + "<text>";
this.indent();
svg += `<textPath xlink:href="#${path.attributes.get(
"id"
)}" ${offset}><tspan ${attributes}>${this.text}</tspan></textPath>`;
this.outdent();
svg += this.nl() + "</text>";
let offset = ''
let align = path.attributes.get('data-text-class')
if (align && align.indexOf('center') > -1) offset = ' startOffset="50%" '
else if (align && align.indexOf('right') > -1) offset = ' startOffset="100%" '
let svg = this.nl() + '<text>'
this.indent()
svg += `<textPath xlink:href="#${path.attributes.get('id')}" ${offset}><tspan ${attributes}>${
this.text
}</tspan></textPath>`
this.outdent()
svg += this.nl() + '</text>'
return svg;
};
return svg
}
Svg.prototype.renderText = function(point) {
let text = point.attributes.getAsArray("data-text");
let text = point.attributes.getAsArray('data-text')
if (text !== false) {
let joint = "";
let joint = ''
for (let string of text) {
this.text = this.insertText(string);
joint += this.text + " ";
this.text = this.insertText(string)
joint += this.text + ' '
}
this.text = this.insertText(joint);
this.text = this.insertText(joint)
}
point.attributes.set("data-text-x", point.x);
point.attributes.set("data-text-y", point.y);
let lineHeight = point.attributes.get("data-text-lineheight") || 12;
point.attributes.remove("data-text-lineheight");
let svg = `${this.nl()}<text ${point.attributes.renderIfPrefixIs(
"data-text-"
)}>`;
this.indent();
point.attributes.set('data-text-x', point.x)
point.attributes.set('data-text-y', point.y)
let lineHeight = point.attributes.get('data-text-lineheight') || 12
point.attributes.remove('data-text-lineheight')
let svg = `${this.nl()}<text ${point.attributes.renderIfPrefixIs('data-text-')}>`
this.indent()
// Multi-line text?
if (this.text.indexOf("\n") !== -1) {
let lines = this.text.split("\n");
svg += `<tspan>${lines.shift()}</tspan>`;
if (this.text.indexOf('\n') !== -1) {
let lines = this.text.split('\n')
svg += `<tspan>${lines.shift()}</tspan>`
for (let line of lines) {
svg += `<tspan x="${point.x}" dy="${lineHeight}">${line}</tspan>`;
svg += `<tspan x="${point.x}" dy="${lineHeight}">${line}</tspan>`
}
} else {
svg += `<tspan>${this.text}</tspan>`;
svg += `<tspan>${this.text}</tspan>`
}
this.outdent();
svg += this.nl() + "</text>";
this.outdent()
svg += this.nl() + '</text>'
return svg;
};
return svg
}
Svg.prototype.renderCircle = function(point) {
return `<circle cx="${point.x}" cy="${point.y}" r="${point.attributes.get(
"data-circle"
)}" ${point.attributes.renderIfPrefixIs("data-circle-")}></circle>`;
};
'data-circle'
)}" ${point.attributes.renderIfPrefixIs('data-circle-')}></circle>`
}
/** Returns SVG code for a snippet */
Svg.prototype.renderSnippet = function(snippet, part) {
let x = snippet.anchor.x;
let y = snippet.anchor.y;
let scale = snippet.attributes.get("data-scale");
let x = snippet.anchor.x
let y = snippet.anchor.y
let scale = snippet.attributes.get('data-scale')
if (scale) {
snippet.attributes.add("transform", `translate(${x}, ${y})`);
snippet.attributes.add("transform", `scale(${scale})`);
snippet.attributes.add("transform", `translate(${x * -1}, ${y * -1})`);
snippet.attributes.add('transform', `translate(${x}, ${y})`)
snippet.attributes.add('transform', `scale(${scale})`)
snippet.attributes.add('transform', `translate(${x * -1}, ${y * -1})`)
}
let rotate = snippet.attributes.get("data-rotate");
let rotate = snippet.attributes.get('data-rotate')
if (rotate) {
snippet.attributes.add("transform", `rotate(${rotate}, ${x}, ${y})`);
snippet.attributes.add('transform', `rotate(${rotate}, ${x}, ${y})`)
}
let svg = this.nl();
svg += `<use x="${x}" y="${y}" `;
svg += `xlink:href="#${snippet.def}" ${snippet.attributes.render()}>`;
svg += "</use>";
let svg = this.nl()
svg += `<use x="${x}" y="${y}" `
svg += `xlink:href="#${snippet.def}" ${snippet.attributes.render()}>`
svg += '</use>'
return svg;
};
return svg
}
/** Returns SVG code to open a group */
Svg.prototype.openGroup = function(id, attributes = false) {
let svg = this.nl() + this.nl();
svg += `<!-- Start of group #${id} -->`;
svg += this.nl();
svg += `<g id="${id}"`;
if (attributes) svg += ` ${attributes.render()}`;
svg += ">";
this.indent();
this.openGroups.push(id);
let svg = this.nl() + this.nl()
svg += `<!-- Start of group #${id} -->`
svg += this.nl()
svg += `<g id="${id}"`
if (attributes) svg += ` ${attributes.render()}`
svg += '>'
this.indent()
this.openGroups.push(id)
return svg;
};
return svg
}
/** Returns SVG code to close a group */
Svg.prototype.closeGroup = function() {
this.outdent();
this.outdent()
return `${this.nl()}</g>${this.nl()}<!-- end of group #${this.openGroups.pop()} -->`;
};
return `${this.nl()}</g>${this.nl()}<!-- end of group #${this.openGroups.pop()} -->`
}
/** Returns a linebreak + identation */
Svg.prototype.nl = function() {
return "\n" + this.tab();
};
return '\n' + this.tab()
}
/** Returns indentation */
Svg.prototype.tab = function() {
let space = "";
let space = ''
for (let i = 0; i < this.tabs; i++) {
space += " ";
space += ' '
}
return space;
};
return space
}
/** Increases indentation by 1 */
Svg.prototype.indent = function() {
this.tabs += 1;
};
this.tabs += 1
}
/** Decreases indentation by 1 */
Svg.prototype.outdent = function() {
this.tabs -= 1;
};
this.tabs -= 1
}
/** Returns an unused ID */
Svg.prototype.getId = function() {
this.freeId += 1;
this.freeId += 1
return "" + this.freeId;
};
return '' + this.freeId
}
export default Svg;
export default Svg

View file

@ -1,95 +1,89 @@
import Path from "./path";
import Point from "./point";
import Bezier from "bezier-js";
import Path from './path'
import Point from './point'
import Bezier from 'bezier-js'
export function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
return string.charAt(0).toUpperCase() + string.slice(1)
}
/** Returns internal hook name for a macro */
export function macroName(name) {
return `_macro_${name}`;
return `_macro_${name}`
}
/** Find intersection of two (endless) lines */
export function beamsIntersect(a1, a2, b1, b2) {
let slopeA = a1.slope(a2);
let slopeB = b1.slope(b2);
if (slopeA === slopeB) return false; // Parallel lines
let slopeA = a1.slope(a2)
let slopeB = b1.slope(b2)
if (slopeA === slopeB) return false // Parallel lines
if (a1.x === a2.x)
return new Point(a1.x, slopeB * a1.x + (b1.y - slopeB * b1.x));
if (a1.x === a2.x) return new Point(a1.x, slopeB * a1.x + (b1.y - slopeB * b1.x))
// Vertical line A
else if (b1.x === b2.x)
return new Point(b1.x, slopeA * b1.x + (a1.y - slopeA * a1.x));
else if (b1.x === b2.x) return new Point(b1.x, slopeA * b1.x + (a1.y - slopeA * a1.x))
// Vertical line B
else {
// Swap points if line A or B goes from right to left
if (a1.x > a2.x) a1 = a2.copy();
if (b1.x > b2.x) b1 = b2.copy();
if (a1.x > a2.x) a1 = a2.copy()
if (b1.x > b2.x) b1 = b2.copy()
// Find y intercept
let iA = a1.y - slopeA * a1.x;
let iB = b1.y - slopeB * b1.x;
let iA = a1.y - slopeA * a1.x
let iB = b1.y - slopeB * b1.x
// Find intersection
let x = (iB - iA) / (slopeA - slopeB);
let y = slopeA * x + iA;
let x = (iB - iA) / (slopeA - slopeB)
let y = slopeA * x + iA
return new Point(x, y);
return new Point(x, y)
}
}
/** Find intersection of two line segments */
export function linesIntersect(a1, a2, b1, b2) {
let p = beamsIntersect(a1, a2, b1, b2);
if (!p) return false;
let lenA = a1.dist(a2);
let lenB = b1.dist(b2);
let lenC = a1.dist(p) + p.dist(a2);
let lenD = b1.dist(p) + p.dist(b2);
if (
Math.round(lenA) == Math.round(lenC) &&
Math.round(lenB) == Math.round(lenD)
)
return p;
else return false;
let p = beamsIntersect(a1, a2, b1, b2)
if (!p) return false
let lenA = a1.dist(a2)
let lenB = b1.dist(b2)
let lenC = a1.dist(p) + p.dist(a2)
let lenD = b1.dist(p) + p.dist(b2)
if (Math.round(lenA) == Math.round(lenC) && Math.round(lenB) == Math.round(lenD)) return p
else return false
}
/** Finds out whether a point lies on an endless line */
export function pointOnBeam(from, to, check, precision = 1e6) {
if (from.sitsOn(check)) return true;
if (to.sitsOn(check)) return true;
let cross = check.dx(from) * to.dy(from) - check.dy(from) * to.dx(from);
if (from.sitsOn(check)) return true
if (to.sitsOn(check)) return true
let cross = check.dx(from) * to.dy(from) - check.dy(from) * to.dx(from)
if (Math.abs(Math.round(cross * precision) / precision) === 0) return true;
else return false;
if (Math.abs(Math.round(cross * precision) / precision) === 0) return true
else return false
}
/** Finds out whether a point lies on a line segment */
export function pointOnLine(from, to, check, precision = 1e6) {
if (!pointOnBeam(from, to, check, precision)) return false;
let lenA = from.dist(to);
let lenB = from.dist(check) + check.dist(to);
if (Math.round(lenA) == Math.round(lenB)) return true;
else return false;
if (!pointOnBeam(from, to, check, precision)) return false
let lenA = from.dist(to)
let lenB = from.dist(check) + check.dist(to)
if (Math.round(lenA) == Math.round(lenB)) return true
else return false
}
/** Finds out whether a point lies on a curve */
export function pointOnCurve(start, cp1, cp2, end, check) {
if (start.sitsOn(check)) return true;
if (end.sitsOn(check)) return true;
if (start.sitsOn(check)) return true
if (end.sitsOn(check)) return true
let curve = new Bezier(
{ x: start.x, y: start.y },
{ x: cp1.x, y: cp1.y },
{ x: cp2.x, y: cp2.y },
{ x: end.x, y: end.y }
);
)
let intersections = curve.intersects({
p1: { x: check.x - 1, y: check.y },
p2: { x: check.x + 1, y: check.y }
});
if (intersections.length > 0) return intersections.shift();
else return false;
})
if (intersections.length > 0) return intersections.shift()
else return false
}
/** Splits a curve on a point */
@ -97,7 +91,7 @@ export function splitCurve(start, cp1, cp2, end, split) {
let [c1, c2] = new Path()
.move(start)
.curve(cp1, cp2, end)
.split(split);
.split(split)
return [
{
@ -112,215 +106,201 @@ export function splitCurve(start, cp1, cp2, end, split) {
cp2: c2.ops[1].cp2,
end: c2.ops[1].to
}
];
]
}
/** Find where an (endless) line intersects with a certain X-value */
export function beamIntersectsX(from, to, x) {
if (from.x === to.x) return false; // Vertical line
let top = new Point(x, -10);
let bottom = new Point(x, 10);
if (from.x === to.x) return false // Vertical line
let top = new Point(x, -10)
let bottom = new Point(x, 10)
return beamsIntersect(from, to, top, bottom);
return beamsIntersect(from, to, top, bottom)
}
/** Find where an (endless) line intersects with a certain Y-value */
export function beamIntersectsY(from, to, y) {
if (from.y === to.y) return false; // Horizontal line
let left = new Point(-10, y);
let right = new Point(10, y);
if (from.y === to.y) return false // Horizontal line
let left = new Point(-10, y)
let right = new Point(10, y)
return beamsIntersect(from, to, left, right);
return beamsIntersect(from, to, left, right)
}
/** Convert value in mm to cm or imperial units */
export function units(value, to = "metric") {
if (to === "imperial") return round(value / 25.4) + '"';
else return round(value / 10) + "cm";
export function units(value, to = 'metric') {
if (to === 'imperial') return round(value / 25.4) + '"'
else return round(value / 10) + 'cm'
}
/** Find where a curve intersects with line */
export function lineIntersectsCurve(start, end, from, cp1, cp2, to) {
let intersections = [];
let intersections = []
let bz = new Bezier(
{ x: from.x, y: from.y },
{ x: cp1.x, y: cp1.y },
{ x: cp2.x, y: cp2.y },
{ x: to.x, y: to.y }
);
)
let line = {
p1: { x: start.x, y: start.y },
p2: { x: end.x, y: end.y }
};
}
for (let t of bz.intersects(line)) {
let isect = bz.get(t);
intersections.push(new Point(isect.x, isect.y));
let isect = bz.get(t)
intersections.push(new Point(isect.x, isect.y))
}
if (intersections.length === 0) return false;
else if (intersections.length === 1) return intersections[0];
else return intersections;
if (intersections.length === 0) return false
else if (intersections.length === 1) return intersections[0]
else return intersections
}
/** Find where a curve intersects with a given X-value */
export function curveIntersectsX(from, cp1, cp2, to, x) {
let start = new Point(x, -10000);
let end = new Point(x, 10000);
return lineIntersectsCurve(start, end, from, cp1, cp2, to);
let start = new Point(x, -10000)
let end = new Point(x, 10000)
return lineIntersectsCurve(start, end, from, cp1, cp2, to)
}
/** Find where a curve intersects with a given Y-value */
export function curveIntersectsY(from, cp1, cp2, to, y) {
let start = new Point(-10000, y);
let end = new Point(10000, y);
return lineIntersectsCurve(start, end, from, cp1, cp2, to);
let start = new Point(-10000, y)
let end = new Point(10000, y)
return lineIntersectsCurve(start, end, from, cp1, cp2, to)
}
/** Find where a curve intersects with another curve */
export function curvesIntersect(
fromA,
cp1A,
cp2A,
toA,
fromB,
cp1B,
cp2B,
toB
) {
let precision = 0.005; // See https://github.com/Pomax/bezierjs/issues/99
let intersections = [];
export function curvesIntersect(fromA, cp1A, cp2A, toA, fromB, cp1B, cp2B, toB) {
let precision = 0.005 // See https://github.com/Pomax/bezierjs/issues/99
let intersections = []
let curveA = new Bezier(
{ x: fromA.x, y: fromA.y },
{ x: cp1A.x, y: cp1A.y },
{ x: cp2A.x, y: cp2A.y },
{ x: toA.x, y: toA.y }
);
)
let curveB = new Bezier(
{ x: fromB.x, y: fromB.y },
{ x: cp1B.x, y: cp1B.y },
{ x: cp2B.x, y: cp2B.y },
{ x: toB.x, y: toB.y }
);
)
for (let tvalues of curveA.intersects(curveB, precision)) {
let intersection = curveA.get(tvalues.substr(0, tvalues.indexOf("/")));
intersections.push(new Point(intersection.x, intersection.y));
let intersection = curveA.get(tvalues.substr(0, tvalues.indexOf('/')))
intersections.push(new Point(intersection.x, intersection.y))
}
if (intersections.length === 0) return false;
else if (intersections.length === 1) return intersections.shift();
if (intersections.length === 0) return false
else if (intersections.length === 1) return intersections.shift()
else {
let unique = [];
let unique = []
for (let i of intersections) {
let dupe = false;
let dupe = false
for (let u of unique) {
if (i.sitsRoughlyOn(u)) dupe = true;
if (i.sitsRoughlyOn(u)) dupe = true
}
if (!dupe) unique.push(i);
if (!dupe) unique.push(i)
}
return unique;
return unique
}
}
/** Find the intersections between two circles */
export function circlesIntersect(c1, r1, c2, r2, sort = "x") {
let dx = c1.dx(c2);
let dy = c1.dy(c2);
let dist = c1.dist(c2);
export function circlesIntersect(c1, r1, c2, r2, sort = 'x') {
let dx = c1.dx(c2)
let dy = c1.dy(c2)
let dist = c1.dist(c2)
// Check for edge cases
if (dist > parseFloat(r1) + parseFloat(r2)) return false; // Circles do not intersect
if (dist < parseFloat(r2) - parseFloat(r1)) return false; // One circle is contained in the other
if (dist === 0 && r1 === r2) return false; // Two circles are identical
let chorddistance =
(Math.pow(r1, 2) - Math.pow(r2, 2) + Math.pow(dist, 2)) / (2 * dist);
let halfchordlength = Math.sqrt(Math.pow(r1, 2) - Math.pow(chorddistance, 2));
let chordmidpointx = c1.x + (chorddistance * dx) / dist;
let chordmidpointy = c1.y + (chorddistance * dy) / dist;
if (dist > parseFloat(r1) + parseFloat(r2)) return false // Circles do not intersect
if (dist < parseFloat(r2) - parseFloat(r1)) return false // One circle is contained in the other
if (dist === 0 && r1 === r2) return false // Two circles are identical
let chorddistance = (Math.pow(r1, 2) - Math.pow(r2, 2) + Math.pow(dist, 2)) / (2 * dist)
let halfchordlength = Math.sqrt(Math.pow(r1, 2) - Math.pow(chorddistance, 2))
let chordmidpointx = c1.x + (chorddistance * dx) / dist
let chordmidpointy = c1.y + (chorddistance * dy) / dist
let i1 = new Point(
chordmidpointx + (halfchordlength * dy) / dist,
chordmidpointy - (halfchordlength * dx) / dist
);
)
let i2 = new Point(
chordmidpointx - (halfchordlength * dy) / dist,
chordmidpointy + (halfchordlength * dx) / dist
);
)
if ((sort === "x" && i1.x <= i2.x) || (sort === "y" && i1.y <= i2.y))
return [i1, i2];
else return [i2, i1];
if ((sort === 'x' && i1.x <= i2.x) || (sort === 'y' && i1.y <= i2.y)) return [i1, i2]
else return [i2, i1]
}
/** Find the intersections between a beam and a circle */
export function beamIntersectsCircle(c, r, p1, p2, sort = "x") {
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
let A = Math.pow(dx, 2) + Math.pow(dy, 2);
let B = 2 * (dx * (p1.x - c.x) + dy * (p1.y - c.y));
let C = Math.pow(p1.x - c.x, 2) + Math.pow(p1.y - c.y, 2) - Math.pow(r, 2);
export function beamIntersectsCircle(c, r, p1, p2, sort = 'x') {
let dx = p2.x - p1.x
let dy = p2.y - p1.y
let A = Math.pow(dx, 2) + Math.pow(dy, 2)
let B = 2 * (dx * (p1.x - c.x) + dy * (p1.y - c.y))
let C = Math.pow(p1.x - c.x, 2) + Math.pow(p1.y - c.y, 2) - Math.pow(r, 2)
let det = Math.pow(B, 2) - 4 * A * C;
let det = Math.pow(B, 2) - 4 * A * C
if (A <= 0.0000001 || det < 0) return false;
if (A <= 0.0000001 || det < 0) return false
// No real solutions
else if (det === 0) {
// One solution
let t = (-1 * B) / (2 * A);
let i1 = new Point(p1.x + t * dx, p1.y + t * dy);
return [i1];
let t = (-1 * B) / (2 * A)
let i1 = new Point(p1.x + t * dx, p1.y + t * dy)
return [i1]
} else {
// Two solutions
let t = (-1 * B + Math.sqrt(det)) / (2 * A);
let i1 = new Point(p1.x + t * dx, p1.y + t * dy);
t = (-1 * B - Math.sqrt(det)) / (2 * A);
let i2 = new Point(p1.x + t * dx, p1.y + t * dy);
if ((sort === "x" && i1.x <= i2.x) || (sort === "y" && i1.y <= i2.y))
return [i1, i2];
else return [i2, i1];
let t = (-1 * B + Math.sqrt(det)) / (2 * A)
let i1 = new Point(p1.x + t * dx, p1.y + t * dy)
t = (-1 * B - Math.sqrt(det)) / (2 * A)
let i2 = new Point(p1.x + t * dx, p1.y + t * dy)
if ((sort === 'x' && i1.x <= i2.x) || (sort === 'y' && i1.y <= i2.y)) return [i1, i2]
else return [i2, i1]
}
}
/** Find the intersections between a line and a circle */
export function lineIntersectsCircle(c, r, p1, p2, sort = "x") {
let intersections = beamIntersectsCircle(c, r, p1, p2, sort);
if (intersections === false) return false;
export function lineIntersectsCircle(c, r, p1, p2, sort = 'x') {
let intersections = beamIntersectsCircle(c, r, p1, p2, sort)
if (intersections === false) return false
else {
if (intersections.length === 1) {
if (pointOnLine(p1, p2, intersections[0])) return intersections;
else return false;
if (pointOnLine(p1, p2, intersections[0])) return intersections
else return false
} else {
let i1 = intersections[0];
let i2 = intersections[1];
if (!pointOnLine(p1, p2, i1, 5) && !pointOnLine(p1, p2, i2, 5))
return false;
let i1 = intersections[0]
let i2 = intersections[1]
if (!pointOnLine(p1, p2, i1, 5) && !pointOnLine(p1, p2, i2, 5)) return false
else if (pointOnLine(p1, p2, i1, 5) && pointOnLine(p1, p2, i2, 5)) {
if ((sort === "x" && i1.x <= i2.x) || (sort === "y" && i1.y <= i2.y))
return [i1, i2];
else return [i2, i1];
} else if (pointOnLine(p1, p2, i1, 5)) return [i1];
else if (pointOnLine(p1, p2, i2, 5)) return [i2];
if ((sort === 'x' && i1.x <= i2.x) || (sort === 'y' && i1.y <= i2.y)) return [i1, i2]
else return [i2, i1]
} else if (pointOnLine(p1, p2, i1, 5)) return [i1]
else if (pointOnLine(p1, p2, i2, 5)) return [i2]
}
}
}
export function curveEdge(curve, edge, steps = 500) {
let x = Infinity;
let y = Infinity;
let p;
if (edge === "bottom") y = -Infinity;
if (edge === "right") x = -Infinity;
let x = Infinity
let y = Infinity
let p
if (edge === 'bottom') y = -Infinity
if (edge === 'right') x = -Infinity
for (let i = 0; i < steps; i++) {
p = curve.get(i / steps);
p = curve.get(i / steps)
if (
(edge === "top" && p.y < y) ||
(edge === "bottom" && p.y > y) ||
(edge === "right" && p.x > x) ||
(edge === "left" && p.x < x)
(edge === 'top' && p.y < y) ||
(edge === 'bottom' && p.y > y) ||
(edge === 'right' && p.x > x) ||
(edge === 'left' && p.x < x)
) {
x = p.x;
y = p.y;
x = p.x
y = p.y
}
}
return new Point(x, y);
return new Point(x, y)
}
/**
@ -335,23 +315,23 @@ export function curveEdge(curve, edge, steps = 500) {
* This method does that calculation.
*/
export function stretchToScale(stretch) {
return 1 / (1 + parseFloat(stretch));
return 1 / (1 + parseFloat(stretch))
}
export function round(value) {
return Math.round(value * 1e2) / 1e2;
return Math.round(value * 1e2) / 1e2
}
export function sampleStyle(run, runs) {
let hue = (run - 1) * (330 / runs);
let hue = (run - 1) * (330 / runs)
return `stroke: hsl(${hue}, 100%, 35%);`;
return `stroke: hsl(${hue}, 100%, 35%);`
}
export function deg2rad(degrees) {
return degrees * (Math.PI / 180);
return degrees * (Math.PI / 180)
}
export function rad2deg(radians) {
return (radians / Math.PI) * 180;
return (radians / Math.PI) * 180
}

View file

@ -1,14 +1,14 @@
import React from "react";
import freesewing from "@freesewing/core";
import Workbench from "@freesewing/components/Workbench";
import "typeface-roboto-condensed";
import "@freesewing/css-theme";
import React from 'react'
import freesewing from '@freesewing/core'
import Workbench from '@freesewing/components/Workbench'
import 'typeface-roboto-condensed'
import '@freesewing/css-theme'
import Pattern from "pattern";
import Pattern from 'pattern'
const App = props => {
let instance = new Pattern();
let config = instance.config;
let instance = new Pattern()
let config = instance.config
return (
<Workbench
freesewing={freesewing}
@ -16,7 +16,7 @@ const App = props => {
config={config}
userLanguage="{{language}}"
/>
);
};
)
}
export default App;
export default App

View file

@ -1,9 +1,9 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(<App />, div)
ReactDOM.unmountComponentAtNode(div)
})

Some files were not shown because too many files have changed in this diff Show more