1
0
Fork 0
freesewing/src/part.js

177 lines
4.7 KiB
JavaScript
Raw Normal View History

2018-08-10 19:04:25 +02:00
import * as utils from "./utils";
import Point from "./point";
import Path from "./path";
import Snippet from "./snippet";
import Attributes from "./attributes";
import * as hooklib from "hooks";
import { round } from "./round";
2018-07-23 11:12:06 +00:00
function Part() {
this.attributes = new Attributes();
2018-07-23 11:12:06 +00:00
this.points = {};
this.paths = {};
this.snippets = {};
this.freeId = 0;
2018-08-01 18:18:29 +02:00
this.topLeft = false;
this.bottomRight = false;
2018-08-03 14:20:28 +02:00
this.width = false;
this.height = false;
this.render = true;
2018-08-10 19:04:25 +02:00
this.utils = utils;
this.points.origin = new Point(0, 0);
for (let k in hooklib) this[k] = hooklib[k];
2018-08-07 13:46:38 +02:00
// Keep track of attached hooks
2018-07-23 11:12:06 +00:00
// Constructors so macros can create objects
this.Point = Point;
this.Path = Path;
this.Snippet = Snippet;
// Expose round method to plugins
this.round = round;
2018-08-07 15:22:23 +02:00
let self = this;
this.hooks.attach("debug", self);
2018-07-23 20:14:32 +02:00
return this;
}
2018-07-23 11:12:06 +00:00
Part.prototype.macroClosure = function(args) {
2018-07-23 20:14:32 +02:00
let self = this;
2018-08-13 11:04:22 +02:00
let method = function(key, args) {
2018-08-10 19:04:25 +02:00
let macro = utils.macroName(key);
2018-07-23 20:14:32 +02:00
if (typeof self[macro] === "function") {
2018-08-13 11:04:22 +02:00
self[macro](args);
} else {
self.debug(`Warning: ${macro} is not registered`);
2018-07-23 20:14:32 +02:00
}
};
2018-07-23 20:14:32 +02:00
return method;
};
2018-07-23 11:12:06 +00:00
Part.prototype.debugClosure = function() {
let self = this;
let method = function(d, e, b, u, g) {
self.debug(d, e, b, u, g);
};
return method;
};
2018-08-07 13:46:38 +02:00
/** Debug method, exposes debug hook */
2018-08-07 15:22:23 +02:00
Part.prototype.debug = function(data) {};
2018-08-07 13:46:38 +02:00
/** Returns an unused ID */
Part.prototype.getUid = function() {
this.freeId += 1;
return "" + this.freeId;
};
2018-08-01 18:18:29 +02:00
/** Returns a value formatted for units provided in settings */
Part.prototype.unitsClosure = function(value) {
let self = this;
let method = function(value) {
2018-08-10 19:04:25 +02:00
return utils.units(value, self.context.settings.units);
};
return method;
};
2018-08-01 18:18:29 +02:00
/** Calculates the part's bounding box and sets it */
Part.prototype.boundary = function() {
2018-08-01 18:18:29 +02:00
if (this.topLeft) return this; // Cached
let topLeft = new Point(Infinity, Infinity);
let bottomRight = new Point(-Infinity, -Infinity);
2018-08-01 18:18:29 +02:00
for (let key in this.paths) {
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;
}
}
2018-08-12 16:19:04 +02:00
// Fix infinity of 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;
2018-08-01 18:18:29 +02:00
// Add 10mm margin
this.topLeft = new Point(topLeft.x - 10, topLeft.y - 10);
this.bottomRight = new Point(bottomRight.x + 10, bottomRight.y + 10);
2018-08-03 14:20:28 +02:00
this.width = this.bottomRight.x - this.topLeft.x;
this.height = this.bottomRight.y - this.topLeft.y;
2018-08-01 18:18:29 +02:00
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})`
);
2018-08-01 18:18:29 +02:00
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);
2018-08-01 18:18:29 +02:00
return this;
};
/** Copies point/path/snippet data from part orig into this */
Part.prototype.copy = function(orig) {
for (let type of ["points", "paths", "snippets"]) {
for (let i in orig[type]) {
if (typeof this[type][i] === "undefined") {
this[type][i] = orig[type][i].clone();
}
}
}
return this;
2018-08-03 14:20:28 +02:00
};
Part.prototype.units = function(input) {
return utils.units(input, this.context.settings.units);
};
/** Returns an object with shorthand access for pattern design */
Part.prototype.shorthand = function() {
let final = this.context.settings.mode === "draft" ? true : false;
let paperless = this.context.settings.paperless === true ? true : false;
return {
sa: this.context.settings.sa || 0,
measurements: this.context.settings.measurements || {},
options: this.context.options || {},
store: this.context.store,
points: this.points || {},
paths: this.paths || {},
snippets: this.snippets || {},
macro: this.macroClosure(),
units: this.unitsClosure(),
utils: utils,
Point: this.Point,
Path: this.Path,
Snippet: this.Snippet,
final,
paperless,
debug: this.debugClosure()
};
};
export default Part;