2017-01-20 09:49:47 +00:00
|
|
|
|
/*
|
|
|
|
|
TurtleShepherd
|
|
|
|
|
|
|
|
|
|
turltestich's central intelligence agancy
|
|
|
|
|
|
|
|
|
|
*/
|
2017-01-19 22:00:37 +00:00
|
|
|
|
|
2017-01-21 11:29:20 +00:00
|
|
|
|
function TurtleShepherd() {
|
|
|
|
|
this.init();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-21 11:12:26 +00:00
|
|
|
|
function TurtleShepherd(world) {
|
2017-01-21 11:29:20 +00:00
|
|
|
|
this.init();
|
|
|
|
|
this.setWorld(world);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.init = function() {
|
2017-01-20 12:14:35 +00:00
|
|
|
|
this.w = 480;
|
|
|
|
|
this.h = 360;
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.clear();
|
2017-01-20 12:14:35 +00:00
|
|
|
|
this.gridSize = 50;
|
2017-01-20 17:33:32 +00:00
|
|
|
|
this.showJumpStitches = true;
|
|
|
|
|
this.showStitches = true;
|
|
|
|
|
this.showGrid = true;
|
|
|
|
|
this.showTurtle = true;
|
2017-01-21 11:29:20 +00:00
|
|
|
|
};
|
2017-01-19 22:00:37 +00:00
|
|
|
|
|
2017-01-20 09:49:47 +00:00
|
|
|
|
TurtleShepherd.prototype.clear = function() {
|
|
|
|
|
this.cache = [];
|
|
|
|
|
this.minX = 0;
|
|
|
|
|
this.minY = 0;
|
|
|
|
|
this.maxX = 0;
|
|
|
|
|
this.maxY = 0;
|
|
|
|
|
this.steps = 0;
|
|
|
|
|
this.initX = 0;
|
|
|
|
|
this.initY = 0;
|
|
|
|
|
this.scale = 1;
|
2017-01-21 12:06:10 +00:00
|
|
|
|
this.dx = 0;
|
|
|
|
|
this.dy = 0;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-21 11:29:20 +00:00
|
|
|
|
TurtleShepherd.prototype.setWorld = function(world) {
|
|
|
|
|
this.world = world;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:49:47 +00:00
|
|
|
|
TurtleShepherd.prototype.hasSteps = function() {
|
|
|
|
|
return this.steps > 0;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-21 15:50:09 +00:00
|
|
|
|
TurtleShepherd.prototype.addMoveTo= function(x, y, penState) {
|
|
|
|
|
|
|
|
|
|
x = Math.round(x);
|
|
|
|
|
y = Math.round(y);
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.cache.push(
|
|
|
|
|
{
|
|
|
|
|
"cmd":"move",
|
|
|
|
|
"x":x,
|
|
|
|
|
"y":-y,
|
|
|
|
|
"penDown":penState,
|
|
|
|
|
}
|
|
|
|
|
);
|
2017-01-20 09:49:47 +00:00
|
|
|
|
if (this.steps === 0) {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.minX = x;
|
|
|
|
|
this.minY = y;
|
|
|
|
|
this.maxX = x;
|
|
|
|
|
this.maxY = y;
|
|
|
|
|
} else {
|
|
|
|
|
if (x < this.minX) this.minX = x;
|
|
|
|
|
if (x > this.maxX) this.maxX = x;
|
|
|
|
|
|
|
|
|
|
if (y < this.minY) this.minY = y;
|
|
|
|
|
if (y > this.maxY) this.maxY = y;
|
|
|
|
|
}
|
2017-01-20 09:49:47 +00:00
|
|
|
|
this.steps++;
|
|
|
|
|
if (DEBUG) this.debug_msg("move to " + x + " " + y + " " + penState );
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:49:47 +00:00
|
|
|
|
TurtleShepherd.prototype.initPosition = function(x,y) {
|
2017-01-21 15:50:09 +00:00
|
|
|
|
x = Math.round(x);
|
|
|
|
|
y = Math.round(y);
|
2017-01-20 09:49:47 +00:00
|
|
|
|
this.initX = x;
|
2017-01-20 15:21:36 +00:00
|
|
|
|
this.initY = -y;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
if (DEBUG) this.debug_msg("init " + x + " " + y );
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:32:01 +00:00
|
|
|
|
TurtleShepherd.prototype.addColorChange= function(color) {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.cache.push(
|
|
|
|
|
{
|
|
|
|
|
"cmd":"color",
|
|
|
|
|
"value":color,
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-01-20 09:32:01 +00:00
|
|
|
|
TurtleShepherd.prototype.setScale = function(s) {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.scale = s;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
if (DEBUG) this.debug_msg("zoom to scale "+ s );
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-01-20 09:32:01 +00:00
|
|
|
|
TurtleShepherd.prototype.zoomIn = function() {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
this.scale += 0.1;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
if (DEBUG) this.debug_msg("zoom to scale "+this.scale );
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:32:01 +00:00
|
|
|
|
TurtleShepherd.prototype.zoomOut = function() {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
if (this.scale > 0.15)
|
|
|
|
|
this.scale -= 0.1;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
if (DEBUG) this.debug_msg("zoom to scale "+ this.scale );
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-21 12:06:10 +00:00
|
|
|
|
TurtleShepherd.prototype.zoomIn = function() {
|
|
|
|
|
this.scale += 0.1;
|
|
|
|
|
if (DEBUG) this.debug_msg("zoom to scale "+this.scale );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.pan = function(dx, dy) {
|
|
|
|
|
this.dx -= dx;
|
|
|
|
|
this.dy -= dy;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 12:14:35 +00:00
|
|
|
|
TurtleShepherd.prototype.setStageDimensions = function(w,h) {
|
|
|
|
|
this.w = w;
|
|
|
|
|
this.h = h;
|
|
|
|
|
/*
|
|
|
|
|
document.getElementById("svg2").style.left = x + "px";
|
|
|
|
|
document.getElementById("svg2").style.top = y+ "px";
|
|
|
|
|
*/
|
2017-01-21 12:06:10 +00:00
|
|
|
|
/*
|
2017-01-20 12:14:35 +00:00
|
|
|
|
document.getElementById("svg2").style.width = w + "px";
|
|
|
|
|
document.getElementById("svg2").style.height = h + "px";
|
|
|
|
|
document.getElementById("svg2").style.right = "0";
|
|
|
|
|
document.getElementById("svg2").style.bottom = "0";
|
2017-01-21 12:06:10 +00:00
|
|
|
|
*/
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 12:14:35 +00:00
|
|
|
|
TurtleShepherd.prototype.setStagePosition = function(x,y) {
|
|
|
|
|
//document.getElementById("svg2").style.top = y + "px";
|
|
|
|
|
//document.getElementById("svg2").style.left = x + "px";
|
|
|
|
|
};
|
2017-01-19 22:00:37 +00:00
|
|
|
|
|
2017-01-20 12:14:35 +00:00
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.renderGrid = function(size) {
|
|
|
|
|
size = this.gridSize;
|
|
|
|
|
return '<defs>' +
|
|
|
|
|
'<pattern id="grid" width="'+size+'" height="'+size+'" patternUnits="userSpaceOnUse">' +
|
|
|
|
|
'<path d="M '+size+' 0 L 0 0 0 '+size+'" fill="none" stroke="gray" stroke-width="0.5"/>' +
|
2017-01-19 22:00:37 +00:00
|
|
|
|
'</pattern>' +
|
2017-01-20 09:49:47 +00:00
|
|
|
|
'</defs>\n';
|
2017-01-19 22:00:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:32:01 +00:00
|
|
|
|
TurtleShepherd.prototype.toSVG = function() {
|
2017-01-19 22:00:37 +00:00
|
|
|
|
|
2017-01-21 11:12:26 +00:00
|
|
|
|
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 + '"' +
|
2017-01-21 12:06:10 +00:00
|
|
|
|
' viewBox="' +
|
|
|
|
|
(-1 * (this.w / 2) * this.scale) + ' ' +
|
2017-01-20 15:21:36 +00:00
|
|
|
|
(-1 * (this.h / 2) * this.scale) + ' ' +
|
|
|
|
|
(this.w * this.scale) + ' ' +
|
|
|
|
|
(this.h * this.scale) + '"\n';
|
2017-01-19 22:00:37 +00:00
|
|
|
|
svgStr += ' xmlns="http://www.w3.org/2000/svg" version="1.1">\n';
|
|
|
|
|
svgStr += '<title>Embroidery export</title>\n';
|
|
|
|
|
|
|
|
|
|
svgStr += this.renderGrid();
|
|
|
|
|
svgStr += '<rect x="' + (-1 * this.w / 2 * this.scale) +
|
|
|
|
|
'" y="' + (-1 * this.h / 2 * this.scale) +
|
2017-01-20 09:49:47 +00:00
|
|
|
|
'" width="100%" height="100%" fill="url(#grid)" />\n';
|
|
|
|
|
|
2017-01-19 22:00:37 +00:00
|
|
|
|
hasFirst = false;
|
|
|
|
|
tagOpen = false;
|
2017-01-20 09:49:47 +00:00
|
|
|
|
|
2017-01-19 22:00:37 +00:00
|
|
|
|
for (var i=0; i < this.cache.length; i++) {
|
|
|
|
|
if (this.cache[i].cmd == "move") {
|
|
|
|
|
stitch = this.cache[i];
|
|
|
|
|
if (!hasFirst) {
|
|
|
|
|
if (stitch.penDown) {
|
|
|
|
|
svgStr += '<path fill="none" stroke="black" d="M ' +
|
|
|
|
|
this.initX +
|
|
|
|
|
' ' +
|
|
|
|
|
this.initY ;
|
|
|
|
|
hasFirst = true;
|
|
|
|
|
tagOpen = true;
|
|
|
|
|
} else {
|
|
|
|
|
svgStr += '<path stroke="red" stroke-dasharray="4 4" d="M ' +
|
|
|
|
|
this.initX +
|
|
|
|
|
' ' +
|
|
|
|
|
this.initY +
|
|
|
|
|
' L ' +
|
|
|
|
|
(stitch.x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(stitch.y) +
|
|
|
|
|
'" />\n' ;
|
|
|
|
|
hasFirst = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if (this.cache[i].penDown ) {
|
|
|
|
|
if (!this.cache[i-1].penDown ) {
|
|
|
|
|
svgStr +=' <path fill="none" stroke="black" d="M ' +
|
|
|
|
|
(this.cache[i-1].x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(this.cache[i-1].y) +
|
|
|
|
|
' L ' +
|
|
|
|
|
(stitch.x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(stitch.y);
|
|
|
|
|
}
|
|
|
|
|
svgStr += ' L ' +
|
|
|
|
|
(stitch.x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(stitch.y);
|
|
|
|
|
tagOpen = true;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
svgStr += '<path stroke="red" stroke-dasharray="4 4" d="M ' +
|
|
|
|
|
(this.cache[i-1].x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(this.cache[i-1].y) +
|
|
|
|
|
' L ' +
|
|
|
|
|
(stitch.x) +
|
|
|
|
|
' ' +
|
|
|
|
|
(stitch.y) +
|
|
|
|
|
'" />\n' ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (tagOpen) svgStr += '" />\n';
|
|
|
|
|
svgStr += '</svg>\n';
|
|
|
|
|
return svgStr;
|
|
|
|
|
};
|
2017-01-20 09:49:47 +00:00
|
|
|
|
|
2017-01-20 17:33:32 +00:00
|
|
|
|
TurtleShepherd.prototype.toogleShowStitches = function() {
|
|
|
|
|
this.showStitches = !this.showStitches;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.getShowStitches = function() {
|
|
|
|
|
return this.showStitches;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.toogleShowJumpStitches = function() {
|
|
|
|
|
this.showJumpStitches = !this.showJumpStitches;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.getShowJumpStitches = function() {
|
|
|
|
|
return this.showJumpStitches;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.toogleShowGrid = function() {
|
|
|
|
|
this.showGrid = !this.showGrid;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TurtleShepherd.prototype.getShowGrid = function() {
|
|
|
|
|
return this.showGrid;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 16:43:55 +00:00
|
|
|
|
TurtleShepherd.prototype.toSVG2 = function() {
|
2017-01-21 15:50:09 +00:00
|
|
|
|
tx = ((-1 * (this.w / 2) * this.scale) + (this.dx * this.scale));
|
|
|
|
|
ty = ((-1 * (this.h / 2) * this.scale) + (this.dy * this.scale));
|
|
|
|
|
bx = ((this.w * this.scale) + (this.dx * this.scale));
|
|
|
|
|
by = ((this.h * this.scale) + (this.dy * this.scale));
|
|
|
|
|
|
|
|
|
|
// TODO: Panning
|
2017-01-20 16:43:55 +00:00
|
|
|
|
|
|
|
|
|
//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 + '"' +
|
2017-01-21 12:06:10 +00:00
|
|
|
|
' viewBox="' +
|
2017-01-21 15:50:09 +00:00
|
|
|
|
(tx) + ' ' +
|
|
|
|
|
(ty) + ' ' +
|
|
|
|
|
(bx) + ' ' +
|
|
|
|
|
(by) + '"\n';
|
2017-01-20 16:43:55 +00:00
|
|
|
|
svgStr += ' xmlns="http://www.w3.org/2000/svg" version="1.1">\n';
|
|
|
|
|
svgStr += '<title>Embroidery export</title>\n';
|
|
|
|
|
|
2017-01-20 17:33:32 +00:00
|
|
|
|
if (this.showGrid) {
|
|
|
|
|
svgStr += this.renderGrid();
|
2017-01-21 15:50:09 +00:00
|
|
|
|
svgStr += '<rect x="' + ((-1 * (this.w / 2) * this.scale)) +
|
|
|
|
|
'" y="' + ((-1 * (this.h / 2) * this.scale)) +
|
2017-01-20 17:33:32 +00:00
|
|
|
|
'" width="100%" height="100%" fill="url(#grid)" />\n';
|
|
|
|
|
}
|
2017-01-20 16:43:55 +00:00
|
|
|
|
hasFirst = false;
|
|
|
|
|
tagOpen = false;
|
|
|
|
|
prevX = this.initX;
|
|
|
|
|
prevY = this.initY;
|
|
|
|
|
|
|
|
|
|
for (var i=0; i < this.cache.length; i++) {
|
|
|
|
|
if (this.cache[i].cmd == "move") {
|
|
|
|
|
stitch = this.cache[i];
|
2017-01-20 17:33:32 +00:00
|
|
|
|
if (stitch.penDown || this.showJumpStitches)
|
2017-01-21 15:50:09 +00:00
|
|
|
|
svgStr += '<line x1="'+ (prevX) +
|
|
|
|
|
'" y1="'+ (prevY) +
|
|
|
|
|
'" x2="' + (stitch.x) +
|
|
|
|
|
'" y2="' + (stitch.y);
|
2017-01-20 17:33:32 +00:00
|
|
|
|
|
2017-01-20 16:43:55 +00:00
|
|
|
|
if (stitch.penDown)
|
2017-01-20 17:33:32 +00:00
|
|
|
|
svgStr +='" stroke-linecap="round" style="stroke:rgb(0,0,0);stroke-width:1" />\n';
|
2017-01-20 16:43:55 +00:00
|
|
|
|
else
|
2017-01-20 17:33:32 +00:00
|
|
|
|
if (this.showJumpStitches)
|
|
|
|
|
svgStr +='" stroke-linecap="round" style="stroke:rgb(255,0,0);stroke-width:0.6;" stroke-dasharray="4 4" />\n';
|
2017-01-20 17:14:16 +00:00
|
|
|
|
|
2017-01-20 17:33:32 +00:00
|
|
|
|
if (this.showStitches) {
|
2017-01-21 15:50:09 +00:00
|
|
|
|
svgStr +='<circle cx="'+ (stitch.x) +
|
|
|
|
|
'" cy="'+ (stitch.y) +
|
2017-01-21 11:12:26 +00:00
|
|
|
|
'" r="1.8" stroke="blue" fill="blue"/>\n';
|
2017-01-20 17:33:32 +00:00
|
|
|
|
}
|
2017-01-20 17:14:16 +00:00
|
|
|
|
|
2017-01-20 16:43:55 +00:00
|
|
|
|
}
|
2017-01-20 17:14:16 +00:00
|
|
|
|
prevX = stitch.x;
|
|
|
|
|
prevY = stitch.y;
|
2017-01-20 16:43:55 +00:00
|
|
|
|
}
|
|
|
|
|
if (tagOpen) svgStr += '" />\n';
|
|
|
|
|
svgStr += '</svg>\n';
|
|
|
|
|
return svgStr;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-20 09:49:47 +00:00
|
|
|
|
TurtleShepherd.prototype.reRender = function(cnv) {
|
2017-01-20 16:43:55 +00:00
|
|
|
|
sourceSVG = turtleShepherd.toSVG2();
|
2017-01-21 11:12:26 +00:00
|
|
|
|
|
|
|
|
|
/* get canvas of world not via call
|
|
|
|
|
if (DEBUG) this.debug_msg("this world is " + this.world.children[0].stage.penTrails() );
|
|
|
|
|
if (typeof this.world !== 'undefined') {
|
|
|
|
|
cnv = this.world.children[0].stage.penTrails();
|
|
|
|
|
this.debug_msg("override canvas" );
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// draw via canvg's drawSVF
|
2017-01-21 15:50:09 +00:00
|
|
|
|
|
2017-01-21 11:12:26 +00:00
|
|
|
|
if (cnv) {
|
|
|
|
|
var ctx = cnv.getContext('2d');
|
|
|
|
|
ctx.clearRect(0, 0, cnv.width, cnv.height);
|
|
|
|
|
ctx.drawSvg(turtleShepherd.toSVG2(), 0, 0, cnv.width, cnv.height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// debug options
|
2017-01-21 15:50:09 +00:00
|
|
|
|
if (DEBUG) {
|
|
|
|
|
document.getElementById("code").innerHTML = sourceSVG;
|
|
|
|
|
//document.getElementById("svg2").innerHTML = sourceSVG;
|
|
|
|
|
}
|
2017-01-21 11:12:26 +00:00
|
|
|
|
// drawing alternatives - to be REMOVED:
|
|
|
|
|
|
|
|
|
|
// draw via canvg - works but very slow!
|
|
|
|
|
//canvg(document.getElementById('svg'), turtleShepherd.toSVG());
|
|
|
|
|
|
|
|
|
|
// draw via canvg - works but very slow!
|
|
|
|
|
//canvg(cnv, turtleShepherd.toSVG());
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// another method to draw svg on canvas
|
|
|
|
|
var svgString = (new XMLSerializer()).serializeToString(document.querySelector('svg'));
|
|
|
|
|
var img = new Image();
|
|
|
|
|
ctx = cnv.getContext('2d');
|
|
|
|
|
img.src = "data:image/svg+xml;base64," + btoa(svgString);
|
|
|
|
|
img.onload = function() {
|
|
|
|
|
// after this, Canvas’ origin-clean is DIRTY
|
|
|
|
|
ctx.clearRect(0, 0, cnv.width, cnv.height);
|
|
|
|
|
ctx.drawImage(img, 0, 0, cnv.width, cnv.height);
|
2017-01-20 15:21:36 +00:00
|
|
|
|
};
|
|
|
|
|
*/
|
2017-01-20 09:49:47 +00:00
|
|
|
|
|
2017-01-20 12:14:35 +00:00
|
|
|
|
};
|
2017-01-20 09:49:47 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
};
|