turtlestitch/stitchcode/turtleShepherd.js

939 wiersze
25 KiB
JavaScript

/*
TurtleShepherd
------------------------------------------------------------------
turltestich's embroidery intelligence agency
Embroidery function for Javscript
------------------------------------------------------------------
Copyright (C) 2016-2021 Michael Aschauer
*/
// TODO: Cleanup TABS!
function TurtleShepherd() {
this.init();
}
TurtleShepherd.prototype.init = function() {
this.clear();
this.pixels_per_millimeter = 5;
this.metric = true;
this.maxLength = 121;
this.calcTooLong = true;
this.densityMax = 15;
this.ignoreColors = false;
this.ignoreWarning = false;
this.backgroundColor = {r:0,g:0,b:0,a:1};
this.defaultColor = {r:0,g:0,b:0,a:1};
this.oldColor = this.defaultColor;
};
TurtleShepherd.prototype.clear = function() {
this.cache = [];
this.w = 0;
this.h = 0;
this.minX = 0;
this.minY = 0;
this.maxX = 0;
this.maxY = 0;
this.initX = 0;
this.initY = 0;
this.lastX = 0;
this.lastY = 0;
this.scale = 1;
this.steps = 0;
this.stitchCount = 0;
this.jumpCount = 0;
this.tooLongCount = 0;
this.density = {};
this.densityWarning = false;
this.colors = [];
this.newColor = 0;
this.oldColor = this.defaultColor;
this.penSize = 1;
this.newPenSize = 0;
};
TurtleShepherd.prototype.toggleMetric = function() {
return this.metric = !this.metric;
};
TurtleShepherd.prototype.setMetric = function(b) {
this.metric = b;
};
TurtleShepherd.prototype.isMetric = function() {
return this.metric;
};
TurtleShepherd.prototype.getIgnoreColors = function() {
return this.ignoreColors;
};
TurtleShepherd.prototype.toggleIgnoreColors = function() {
this.ignoreColors = !this.ignoreColors;
};
TurtleShepherd.prototype.isEmpty = function() {
return this.steps < 1;
};
TurtleShepherd.prototype.hasSteps = function() {
return this.steps > 0;
};
TurtleShepherd.prototype.getStepCount = function() {
return this.steps;
};
TurtleShepherd.prototype.getJumpCount = function() {
return this.jumpCount;
};
TurtleShepherd.prototype.getTooLongCount = function() {
return this.tooLongCount;
};
TurtleShepherd.prototype.getTooLongStr = function() {
if (this.tooLongCount > 1 && !this.ignoreWarning)
return this.tooLongCount + " are too long! (will get clamped)"
else if (this.tooLongCount == 1 && !this.ignoreWarning)
return this.tooLongCount + " is too long! (will get clamped)"
else
return "";
};
TurtleShepherd.prototype.getDensityWarningStr = function() {
if (this.densityWarning && !this.ignoreWarning)
return "DENSITY WARNING!";
else
return "";
};
TurtleShepherd.prototype.getDimensions = function() {
if (this.metric) {
//c = 1;
//unit = "mm";
c = 0.1
unit = "cm";
} else {
c = 0.03937;
unit = "in";
}
w= ((this.maxX - this.minX)/ this.pixels_per_millimeter * c).toFixed(2).toString();
h= ((this.maxY - this.minY)/ this.pixels_per_millimeter * c).toFixed(2).toString();
return w + " x " + h + " " + unit;
};
TurtleShepherd.prototype.getMetricWidth = function() {
c = 0.1
return ((this.maxX - this.minX)/ this.pixels_per_millimeter * c).toFixed(2).toString();
};
TurtleShepherd.prototype.getMetricHeight = function() {
c = 0.1
return((this.maxY - this.minY)/ this.pixels_per_millimeter * c).toFixed(2).toString();
};
TurtleShepherd.prototype.moveTo= function(x1, y1, x2, y2, penState) {
// ignore jump stitches withouth any previous stitches
//if (this.steps === 0 && !penState)
// return
warn = false
if (this.steps === 0) {
this.initX = x1;
this.initY = y1;
this.minX = x1;
this.minY = y1;
this.maxX = x1;
this.maxY = y1;
this.cache.push(
{
"cmd":"move",
"x":x1,
"y":y1,
"penDown":penState,
}
);
this.density[Math.round(x1) + "x" + Math.round(y1)] = 1;
if (this.colors.length < 1) {
if (this.newColor) {
this.colors.push(this.newColor);
} else {
this.colors.push(this.defaultColor);
}
}
}
if (this.newColor) {
this.pushColorChangeNow();
}
if (this.newPenSize) {
this.pushPenSizeNow();
}
if (x2 < this.minX) this.minX = x2;
if (x2 > this.maxX) this.maxX = x2;
if (y2 < this.minY) this.minY = y2;
if (y2 > this.maxY) this.maxY = y2;
var d = Math.round(x2) + "x" + Math.round(y2);
if (this.density[d]) {
this.density[d] += 1;
if (this.density[d] > this.densityMax) {
this.densityWarning = true;
if (this.density[d] <= this.densityMax+1)
warn = true;
}
} else {
this.density[d] = 1;
}
if ( this.calcTooLong && penState) {
dist = Math.sqrt( (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) );
if ( (dist / this.pixels_per_millimeter * 10) > this.maxLength)
this.tooLongCount += 1;
}
this.cache.push(
{
"cmd":"move",
"x":x2,
"y":y2,
"penDown":penState,
}
);
this.w = this.maxX - this.minX;
this.h = this.maxY - this.minY;
if (!penState)
this.jumpCount++;
else {
this.steps++;
}
if (warn) {
warn = false;
return [x2, y2];
} else {
return false;
}
this.lastX = x2;
this.lastY = y2;
};
TurtleShepherd.prototype.setDefaultColor= function(color) {
var c = {
r: Math.round(color.r),
g: Math.round(color.g),
b: Math.round(color.b),
a: color.a
};
this.defaultColor = c;
};
TurtleShepherd.prototype.getDefaultColorAsHex = function (){
return new String(
"#" + (
(1 << 24)
+ (Math.round(this.defaultColor.r) << 16)
+ (Math.round(this.defaultColor.g) << 8)
+ Math.round(this.defaultColor.b)
).toString(16).slice(1));
};
TurtleShepherd.prototype.setBackgroundColor= function(color) {
var c = {
r: Math.round(color.r),
g: Math.round(color.g),
b: Math.round(color.b),
a: color.a
};
this.backgroundColor = c;
};
TurtleShepherd.prototype.getBackgroundColorAsHex = function (){
return new String(
"#" + (
(1 << 24)
+ (Math.round(this.backgroundColor.r) << 16)
+ (Math.round(this.backgroundColor.g) << 8)
+ Math.round(this.backgroundColor.b)
).toString(16).slice(1));
}
TurtleShepherd.prototype.addColorChange= function(color) {
var c = {
r: Math.round(color.r),
g: Math.round(color.g),
b: Math.round(color.b),
a: color.a
};
this.newColor = c;
};
TurtleShepherd.prototype.pushColorChangeNow = function() {
c = this.newColor;
o = this.oldColor;
if (c.r == o.r && c.g == o.g && c.b == o.b && c.a == o.a) {
this.newColor = false;
return;
}
index = this.colors.findIndex(x => (x.r == c.r && x.b == x.b && x.g == c.g && x.a == c.a) );
if (index < 0) {
index = this.colors.push(this.newColor)-1;
}
this.cache.push(
{
"cmd":"color",
"color": this.newColor,
"thread": index
}
);
this.oldColor = this.newColor;
this.newColor = false;
};
TurtleShepherd.prototype.setPenSize = function(s) {
this.newPenSize = s;
};
TurtleShepherd.prototype.pushPenSizeNow = function() {
n = this.newPenSize;
o = this.penSize;
if (n == o) {
this.newPenSize = false;
return;
}
this.cache.push(
{
"cmd":"pensize",
"pensize": n
}
);
this.penSize = this.newPenSize;
this.newPenSize = false;
};
TurtleShepherd.prototype.undoStep = function() {
var last = this.cache.pop();
if (last.cmd == "move") {
if (last.penDown) {
this.steps--;
} else {
this.jumpCount--;
}
}
};
TurtleShepherd.prototype.toSVG = function() {
var svgStr = "<?xml version=\"1.0\" standalone=\"no\"?>\n";
svgStr += "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
svgStr += '<svg width="' + (this.w) + '" height="' + (this.h) + '"' +
' viewBox="0 0 ' + (this.w) + ' ' + (this.h) + '" style="background-color:' + this.getBackgroundColorAsHex() + '"';
svgStr += ' xmlns="http://www.w3.org/2000/svg" version="1.1">\n';
svgStr += '<title>Embroidery export</title>\n';
hasFirst = false;
tagOpen = false;
colorChanged = false;
penSizeChanged = false;
penSize = 1;
lastStitch = null;
color = this.defaultColor;
for (var i=0; i < this.cache.length; i++) {
if (this.cache[i].cmd == "color" && !this.ignoreColors) {
color = this.cache[i].color;
if (hasFirst) colorChanged = true;
if (tagOpen) svgStr += '" />\n';
tagOpen = false;
} else if (this.cache[i].cmd == "pensize") {
penSize = this.cache[i].pensize;
if (hasFirst) penSizeChanged = true;
if (tagOpen) svgStr += '" />\n';
tagOpen = false;
} else if (this.cache[i].cmd == "move") {
stitch = this.cache[i];
if (!hasFirst) {
if (stitch.penDown) {
svgStr += '<path fill="none" style="' +
'stroke:rgb('+ color.r + ',' + color.g + ',' + color.b + '); ' +
'stroke-width:' + penSize + ';' +
'stroke-linecap:round;' +
'stroke-opacity:' + color.a + ';' +
'"' +
' d="M ' +
(this.initX - this.minX) +
' ' +
(this.maxY - this.initY) ;
hasFirst = true;
tagOpen = true;
} else {
// do nothing
}
} else {
if (stitch.penDown ) {
if (!lastStich.penDown || colorChanged || penSizeChanged) {
svgStr += '<path fill="none" style="' +
'stroke:rgb('+ color.r + ',' + color.g + ',' + color.b +'); ' +
'stroke-width:' + penSize + ';' +
'stroke-linecap:round;' +
'stroke-opacity:' + color.a + ';' +
'"' +
' d="M ' +
(lastStich.x - this.minX) +
' ' +
(this.maxY - lastStich.y) +
' L ' +
(stitch.x - this.minX) +
' ' +
(this.maxY - stitch.y);
}
svgStr += ' L ' +
(stitch.x- this.minX) +
' ' +
(this.maxY - stitch.y);
tagOpen = true;
colorChanged = false;
penSizeChanged = false;
} else {
if (tagOpen) svgStr += '" />\n';
tagOpen = false;
}
}
lastStich = stitch;
}
}
if (tagOpen) svgStr += '" />\n';
svgStr += '</svg>\n';
return svgStr;
};
TurtleShepherd.prototype.toPNG = function() {
var color = this.defaultColor;
var hasFirst = false;
var colorChanged = false;
var cnv = document.createElement('canvas');
cnv.width = Math.round(this.w);
cnv.height = Math.round(this.h);
ctx = cnv.getContext('2d');
ctx.strokeStyle = "rgb(" + color.r + "," + color.g + "," + color.b + ")";
ctx.lineWidth = 1.0;
ctx.beginPath();
for (var i=0; i < this.cache.length; i++) {
if (this.cache[i].cmd == "color" && !this.ignoreColors) {
if (hasFirst) {
ctx.stroke();
ctx.beginPath();
colorChanged = true;
}
color = this.cache[i].color;
ctx.strokeStyle = "rgb(" + color.r + "," + color.g + "," + color.b + ")";
} else if (this.cache[i].cmd == "pensize") {
if (hasFirst) {
ctx.stroke();
ctx.beginPath();
colorChanged = true;
}
ctx.lineWidth = this.cache[i].pensize;
} else if (this.cache[i].cmd == "move") {
stitch = this.cache[i];
if (stitch.penDown) {
if (colorChanged) {
ctx.moveTo(lastStitch.x - this.minX, this.maxY - lastStitch.y);
colorChanged = false;
}
ctx.lineTo( stitch.x - this.minX, this.maxY - stitch.y);
hasFirst = true;
} else {
ctx.moveTo(stitch.x - this.minX, this.maxY - stitch.y);
hasFirst = true;
lastJumped = true;
}
lastStitch = stitch;
}
}
ctx.stroke();
console.log(cnv);
return cnv.toDataURL();
}
TurtleShepherd.prototype.toEXP = function() {
var expArr = [];
pixels_per_millimeter = this.pixels_per_millimeter;
scale = 10 / pixels_per_millimeter;
lastStitch = null;
hasFirst = false;
weJustChangedColors = false;
origin = {}
function move(x, y) {
y *= -1;
if (x<0) x = x + 256;
expArr.push(Math.round(x));
if (y<0) y = y + 256;
expArr.push(Math.round(y));
}
for (var i=0; i < this.cache.length; i++) {
if (this.cache[i].cmd == "color" && !this.ignoreColors) {
expArr.push(0x80);
expArr.push(0x01);
expArr.push(0x00);
expArr.push(0x00);
weJustChangedColors = true;
} else if (this.cache[i].cmd == "move") {
stitch = this.cache[i];
if (!hasFirst) {
origin.x = Math.round(stitch.x * scale);
origin.y = Math.round(stitch.y * scale);
// remove zero stitch - why is it here?
//if (!stitch.penDown) {
// expArr.push(0x80);
// expArr.push(0x04);
//}
//move(0,0);
lastStitch = {cmd: "move", x: 0, y: -0, penDown: stitch.penDown}
hasFirst = true;
} else if (hasFirst) {
x1 = Math.round(stitch.x * scale) - origin.x;
y1 = -Math.round(stitch.y * scale) - origin.y;
x0 = Math.round(lastStitch.x * scale) - origin.x;
y0 = -Math.round(lastStitch.y * scale) - origin.y;
sum_x = 0;
sum_y = 0;
dmax = Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0));
dsteps = Math.abs(dmax / 127);
// remove zero stitch - why is it here?
//if (!lastStitch.penDown)
// move(0,0);
if (weJustChangedColors) {
// remove zero stitch - why is it here?
// if (!stitch.penDown) {
// expArr.push(0x80);
// expArr.push(0x04);
// }
// move(0,0);
weJustChangedColors = false;
}
if (dsteps <= 1) {
if (!stitch.penDown) {
expArr.push(0x80);
expArr.push(0x04);
}
move(Math.round(x1 - x0), Math.round(y1 - y0));
} else {
for(j=0;j<dsteps;j++) {
if (!stitch.penDown) {
expArr.push(0x80);
expArr.push(0x04);
}
if (j < dsteps -1) {
move((x1 - x0)/dsteps, (y1 - y0)/dsteps);
sum_x += (x1 - x0)/dsteps;
sum_y += (y1 - y0)/dsteps;
} else {
move(Math.round((x1 - x0) - sum_x), Math.round((y1 - y0) - sum_y));
}
}
}
}
lastStitch = stitch;
hasFirst = true;
}
}
expUintArr = new Uint8Array(expArr.length);
for (i=0;i<expArr.length;i++) {
expUintArr[i] = Math.round(expArr[i]);
}
return expUintArr;
};
TurtleShepherd.prototype.toDST = function(name="noname") {
var expArr = [];
lastStitch = null;
hasFirst = false;
pixels_per_millimeter = this.pixels_per_millimeter;
scale = 10 / pixels_per_millimeter;
count_stitches = 0;
count_jumps = 0;
function encodeTajimaStitch(dx, dy, jump) {
b1 = 0;
b2 = 0;
b3 = 0;
if (dx > 40) {
b3 |= 0x04;
dx -= 81;
}
if (dx < -40) {
b3 |= 0x08;
dx += 81;
}
if (dy > 40) {
b3 |= 0x20;
dy -= 81;
}
if (dy < -40) {
b3 |= 0x10;
dy += 81;
}
if (dx > 13) {
b2 |= 0x04;
dx -= 27;
}
if (dx < -13) {
b2 |= 0x08;
dx += 27;
}
if (dy > 13) {
b2 |= 0x20;
dy -= 27;
}
if (dy < -13) {
b2 |= 0x10;
dy += 27;
}
if (dx > 4) {
b1 |= 0x04;
dx -= 9;
}
if (dx < -4) {
b1 |= 0x08;
dx += 9;
}
if (dy > 4) {
b1 |= 0x20;
dy -= 9;
}
if (dy < -4) {
b1 |= 0x10;
dy += 9;
}
if (dx > 1) {
b2 |= 0x01;
dx -= 3;
}
if (dx < -1) {
b2 |= 0x02;
dx += 3;
}
if (dy > 1) {
b2 |= 0x80;
dy -= 3;
}
if (dy < -1) {
b2 |= 0x40;
dy += 3;
}
if (dx > 0) {
b1 |= 0x01;
dx -= 1;
}
if (dx < 0) {
b1 |= 0x02;
dx += 1;
}
if (dy > 0) {
b1 |= 0x80;
dy -= 1;
}
if (dy < 0) {
b1 |= 0x40;
dy += 1;
}
expArr.push(b1);
expArr.push(b2);
if (jump) {
expArr.push(b3 | 0x83);
} else {
expArr.push(b3 | 0x03);
}
}
function writeHeader(str, length, padWithSpace=true) {
for(var i = 0; i<length-1; i++) {
if (i < str.length) {
expArr.push("0xF1" + str[i].charCodeAt(0).toString(16));
} else {
if (padWithSpace) {
expArr.push(0x20);
} else {
expArr.push(0x00);
}
}
}
expArr.push(0x0d);
}
function pad(n, width, z) {
z = z || ' ';
n = n != 0 ? n + '' : "0";
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
var extx1 = Math.round(this.maxX) - this.initX;
var exty1 = Math.round(this.maxY) - this.initY;
var extx2 = Math.round(this.minX) - this.initX;
var exty2 = Math.round(this.maxY) - this.initY;
writeHeader("LA:" + name.substr(0, 16), 20, true);
writeHeader("ST:" + pad(this.steps, 7), 11);
writeHeader("CO:" + pad(this.colors.length, 3), 7);
writeHeader("+X:" + pad(Math.round(extx1 / this.pixels_per_millimeter) * 10, 5), 9); // Math.round(this.getMetricWidth()*10), 9);
writeHeader("-X:" + pad(Math.abs(Math.round(extx2 / this.pixels_per_millimeter)) * 10, 5), 9);
writeHeader("+Y:" + pad(Math.round(exty1 / this.pixels_per_millimeter) * 10, 5), 9); //Math.round(this.getMetricHeight()*10), 9);
writeHeader("-Y:" + pad(Math.abs(Math.round(exty2 / this.pixels_per_millimeter)) * 10, 5), 9);
var needle_end_x = this.lastX - this.initX;
var needle_end_y = this.lastY - this.initY;
writeHeader("AX:" + pad(Math.round(needle_end_x / this.pixels_per_millimeter) * 10, 6), 10);
writeHeader("AY:" + pad(Math.round(needle_end_y / this.pixels_per_millimeter) * 10, 6), 10);
writeHeader("MX:", 10);
writeHeader("MY:", 10);
writeHeader("PD:", 10);
// extented header would go here
// "AU:%s\r" % author)
// "CP:%s\r" % meta_copyright)
// "TC:%s,%s,%s\r" % (thread.hex_color(), thread.description, thread.catalog_number))
// end of header data
expArr.push(0x1a);
// Print remaining empty header
for (var i=0; i<387; i++) {
expArr.push(0x20);
}
origin = {}
hasFirst = false;
weJustChangedColors = false;
for (i=0; i < this.cache.length; i++) {
if (this.cache[i].cmd == "color" && !this.ignoreColors) {
expArr.push(0x00);
expArr.push(0x00);
expArr.push(0xC3);
weJustChangedColors = true;
} else if (this.cache[i].cmd == "move") {
stitch = this.cache[i];
if (!hasFirst) { // create a stitch at origin
origin.x = Math.round(stitch.x * scale);
origin.y = Math.round(stitch.y * scale);
// zero stitch: Why is it here
encodeTajimaStitch(0, 0, !stitch.penDown);
lastStitch = {cmd: "move", x: 0, y:0, penDown: stitch.penDown}
hasFirst = true;
} else {
x1 = Math.round(stitch.x * scale) - origin.x;
y1 = Math.round(stitch.y * scale) - origin.y;
x0 = Math.round(lastStitch.x * scale) - origin.x;
y0 = Math.round(lastStitch.y * scale) - origin.y;
sum_x = 0;
sum_y = 0;
dmax = Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0));
dsteps = Math.abs(dmax / 121);
if (!lastStitch.penDown)
// zero stitch: Why is it here
encodeTajimaStitch(0,0, false);
if (weJustChangedColors) {
// zero stitch: Why is it here
encodeTajimaStitch(0, 0, !stitch.penDown);
weJustChangedColors = false;
}
if (dsteps <= 1) {
encodeTajimaStitch((x1 - x0), (y1 - y0), !stitch.penDown);
count_stitches++;
} else {
for(j=0;j<dsteps;j++) {
if (j < dsteps -1) {
encodeTajimaStitch(
Math.round((x1 - x0)/dsteps),
Math.round((y1 - y0)/dsteps),
!stitch.penDown
);
count_stitches++;
sum_x += (x1 - x0)/dsteps;
sum_y += (y1 - y0)/dsteps;
} else {
encodeTajimaStitch(
Math.round((x1 - x0) - sum_x),
Math.round((y1 - y0) - sum_y),
!stitch.penDown
);
count_stitches++;
}
}
}
}
lastStitch = stitch;
hasFirst = true;
}
}
// end pattern
expArr.push(0x00);
expArr.push(0x00);
expArr.push(0xF3);
// convert
expUintArr = new Uint8Array(expArr.length);
for (i=0;i<expArr.length;i++) {
expUintArr[i] = Math.round(expArr[i]);
}
return expUintArr;
};
TurtleShepherd.prototype.getStitchesAsArr = function () {
stitches = [];
lastX = 0; lastY = 0;
hasFirst = false;
color = this.defaultColor;
for(i=0;i<this.cache.length;i++) {
if (this.cache[i].cmd == "color") {
color = this.cache[i].color;
}
if (this.cache[i].cmd == "move") {
if (!hasFirst) {
lastY = this.cache[i].y;
lastX = this.cache[i].x;
hasFirst = true;
} else {
stitches.push( [
[lastX, lastY],
[this.cache[i].x, this.cache[i].y ],
color
]);
lastY = this.cache[i].y;
lastX = this.cache[i].x;
}
}
}
return stitches;
}
TurtleShepherd.prototype.debug_msg = function (st, clear) {
o = "";
if (!clear) {
o = document.getElementById("debug").innerHTML;
} else {
o = "";
}
o = st + "<br />" + o;
document.getElementById("debug").innerHTML = o;
};
TurtleShepherd.prototype.toDXF = function() {
var dxfString = '',
isFirst = false,
myself = this,
i,
stitch,
lastStitch;
function dxfHead(maxX=1000,maxY=1000) {
dxfString += ' 0\nSECTION\n 2\nHEADER\n 9\n$ACADVER\n 1\nAC1009\n 9\n$EXTMIN\n 10\n0.0\n 20\n0.0\n 30\n0.0\n 9\n$EXTMAX\n';
dxfString += ' 10\n';
dxfString += maxX.toFixed(1).toString();
dxfString += '\n 20\n';
dxfString += maxY.toFixed(1).toString();
dxfString += '\n 30\n0.0\n 9\n$FILLMODE\n 70\n 0\n 9\n$SPLFRAME\n 70\n 1\n 0\nENDSEC\n';
dxfString += ' 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n 2\nLAYER\n 70\n1\n 0\nLAYER\n 2\n0\n 70\n 0\n 62\n 7\n 6\nCONTINUOUS\n 0\nENDTAB\n 0\nENDSEC\n';
dxfString += ' 0\nSECTION\n 2\nENTITIES\n';
}
function dxfLine(start,end) {
dxfString += ' 0\nLINE\n 8\n0\n 62\n 150\n';
dxfString += ' 10\n';
dxfString += ((start.x - myself.minX)*0.2).toFixed(3).toString();
dxfString += '\n 20\n';
dxfString += ((start.y - myself.minY)*0.2).toFixed(3).toString();
dxfString += '\n 30\n0.0\n 11\n';
dxfString += ((end.x - myself.minX)*0.2).toFixed(3).toString();
dxfString += '\n 21\n';
dxfString += ((end.y - myself.minY)*0.2).toFixed(3).toString();
dxfString += '\n 31\n0.0\n';
}
function dxfEnd() {
dxfString += ' 0\nENDSEC\n 0\nEOF\n';
}
dxfHead((this.maxX-this.minX)*0.4 > 1000 ? (this.maxX-this.minX)*0.4 : 1000,(this.maxY-this.minY)*0.4 > 1000 ? (this.maxY-this.minY)*0.4 : 1000);
for (i=0; i < this.cache.length; i++) {
if (this.cache[i].cmd == "move") {
stitch = this.cache[i];
if (!isFirst) {
isFirst = true;
} else {
if (stitch.penDown && (stitch.x != lastStitch.x || stitch.y != lastStitch.y)) {
dxfLine(lastStitch,stitch);
}
}
lastStitch = stitch;
}
}
dxfEnd();
return dxfString;
};