working on printmanager + api improvements

This commit is contained in:
Rick Companje 2015-04-25 17:26:12 +02:00
parent 1aa0417c33
commit 0c2f774376
28 changed files with 1559 additions and 143 deletions

View File

@ -16,7 +16,7 @@ module.exports = function(grunt) {
},
js: {
src: [
'js/api/*.js',
//'js/api/*.js',
'js/settings/FormPanel.js',
'js/settings/*.js',
'js/*.js',
@ -24,6 +24,10 @@ module.exports = function(grunt) {
'!js/main.js',
'js/main.js', ],
dest: 'www/js/<%= pkg.name %>.js'
},
api: {
src: [ 'js/api/*.js'],
dest: 'www/js/doodle3d-api.js'
}
},
uglify: {
@ -37,7 +41,8 @@ module.exports = function(grunt) {
},
js: {
files: {
'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js']
'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js'],
'www/js/doodle3d-api.min.js' : ['www/js/doodle3d-api.js']
}
},
jslibs: {
@ -91,7 +96,7 @@ module.exports = function(grunt) {
watch: {
javascript: {
files: ["js/**", '!www/js/<%= pkg.name %>.min.js', '!www/js/<%= pkg.name %>.js'],
tasks: ["concat:js", "uglify:js"]
tasks: ["concat:api", "concat:js", "uglify:js"],
// tasks: ["jshint", "concat", "uglify"]
},
javascriptLibs: {

64
js/api/API.js Normal file
View File

@ -0,0 +1,64 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
var API = function() {
var _wifiboxURL = 'http://192.168.5.1/d3dapi/';
var _wifiboxCGIBinURL = 'http://192.168.5.1/cgi-bin/d3dapi/';
var _timeoutTime = 10000;
function post(cmd,data,success,fail) {
$.ajax({
url: _wifiboxURL + cmd,
type: "POST",
data: data,
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
console.log('API.post fail',cmd)
if (fail) fail(response);
} else {
if (success) success(response.data);
else console.log('API.post:',cmd,'success cb undefined')
}
}
}).fail(function(jqXHR, textStatus) {
console.log('API.post fail',cmd,jqXHR,textStatus);
if (fail) fail(jqXHR,textStatus);
});
}
function get(cmd,success,fail) {
$.ajax({
url: _wifiboxURL + cmd,
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if (response.status == "error" || response.status == "fail") {
console.log('API.get fail',cmd,response);
if (fail) fail(response);
} else {
if (success) success(response.data);
else console.log('API.get:',cmd,'success cb undefined')
}
}
}).fail(function() {
console.log('API.get fail',cmd);
if (fail) fail();
});
}
return {
get: get,
post: post
}
}();

View File

@ -8,92 +8,77 @@
function ConfigAPI() {
var _wifiboxURL;
var _wifiboxCGIBinURL;
var _timeoutTime = 3000;
var _saveSettingsTimeoutTime = 8000;
var _self = this;
function loadAll(success,fail) {
API.get('config/all',success,fail);
};
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
//console.log("ConfigAPI:init");
_wifiboxURL = wifiboxURL;
_wifiboxCGIBinURL = wifiboxCGIBinURL;
function load(key,success,fail) {
API.get('config/?'+key+'=',success,fail)
};
function save(newSettings,success,fail) {
API.post('config',{data:newSettings},success,fail);
};
function resetAll(success,fail) {
API.post('config/resetall',{},success,fail)
};
function getSetting(key,success,fail) {
API.get('config/?'+key+'=',function(response) {
if (success) success(response[key]);
},fail);
}
function getStartCode(success,fail) {
loadAll(function(data) {
var startcode = subsituteVariables(data['printer.startcode'],data);
if (success) success(startcode);
},fail);
}
function getEndCode(success,fail) {
loadAll(function(data) {
var endcode = subsituteVariables(data['printer.endcode'],data);
if (success) success(endcode);
},fail);
}
function subsituteVariables(gcode,settings) {
//,temperature,bedTemperature,preheatTemperature,preheatBedTemperature
var temperature = settings["printer.temperature"];
var bedTemperature = settings["printer.bed.temperature"];
var preheatTemperature = settings["printer.heatup.temperature"];
var preheatBedTemperature = settings["printer.heatup.bed.temperature"];
var printerType = settings["printer.type"];
var heatedbed = settings["printer.heatedbed"];
switch (printerType) {
case "makerbot_replicator2": printerType = "r2"; break;
case "makerbot_replicator2x": printerType = "r2x"; break;
case "makerbot_thingomatic": printerType = "t6"; break;
case "makerbot_generic": printerType = "r2"; break;
case "_3Dison_plus": printerType = "r2"; break;
}
var heatedBedReplacement = (heatedbed)? "" : ";";
gcode = gcode.replace(/{printingTemp}/gi ,temperature);
gcode = gcode.replace(/{printingBedTemp}/gi ,bedTemperature);
gcode = gcode.replace(/{preheatTemp}/gi ,preheatTemperature);
gcode = gcode.replace(/{preheatBedTemp}/gi ,preheatBedTemperature);
gcode = gcode.replace(/{printerType}/gi ,printerType);
gcode = gcode.replace(/{if heatedBed}/gi ,heatedBedReplacement);
return gcode;
}
return {
loadAll: loadAll,
load: load,
save: save,
resetAll: resetAll,
getSetting: getSetting,
getStartCode: getStartCode,
getEndCode: getEndCode,
}
this.loadAll = function(completeHandler,failedHandler) {
//console.log("ConfigAPI:loadAll");
$.ajax({
url: _wifiboxURL + "/config/all",
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.load = function(targetSettings,completeHandler,failedHandler) {
//console.log("ConfigAPI:load");
$.ajax({
url: _wifiboxURL + "/config/",
type: "GET",
dataType: 'json',
data: targetSettings,
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.save = function(newSettings,completeHandler,failedHandler) {
//console.log("ConfigAPI:save");
$.ajax({
url: _wifiboxCGIBinURL + "/config",
type: "POST",
data: newSettings,
dataType: 'json',
timeout: _saveSettingsTimeoutTime,
success: function(response){
//console.log("ConfigAPI:save response: ",response);
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.resetAll = function(completeHandler,failedHandler) {
//console.log("ConfigAPI:resetAll");
$.ajax({
url: _wifiboxCGIBinURL + "/config/resetall",
type: "POST",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
}

14
js/api/InfoAPI.js Normal file
View File

@ -0,0 +1,14 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function InfoAPI() {
this.status = function(success,fail) {
API.get('info/status',success,fail);
};
}

View File

@ -5,42 +5,84 @@
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function PrinterAPI() {
var _wifiboxURL;
var _wifiboxCGIBinURL;
var _timeoutTime = 3000;
var _self = this;
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
//console.log("PrinterAPI:init");
//console.log(" wifiboxURL: ",wifiboxURL);
//console.log(" wifiboxCGIBinURL: ",wifiboxCGIBinURL);
_wifiboxURL = wifiboxURL;
_wifiboxCGIBinURL = wifiboxCGIBinURL;
}
function PrinterAPI() {
this.remainingLines = [];
this.totalLinesAtStart = 0;
this.state = function(success,fail) {
API.get('printer/state',success,fail);
};
this.listAll = function(completeHandler,failedHandler) {
//console.log("PrinterAPI:listAll");
//console.log(" _wifiboxURL: ",_wifiboxURL);
$.ajax({
url: _wifiboxURL + "/printer/listall",
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
//console.log("PrinterAPI response: ",response);
if(response.status == "error" || response.status == "fail") {
//console.log("PrinterAPI:listAll failed: ",response);
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
this.listAll = function(success,fail) {
API.get('printer/listall',success,fail);
};
this.temperature = function(success,fail) {
API.get('printer/temperature',success,fail);
};
this.progress = function(success,fail) {
API.get('printer/progress',success,fail);
}
function _printPartPost(lines,data,cb) {
API.post('printer/print',data,function(response) {
console.log('print part success',response);
setTimeout(function() {
_printPart(lines,false,false,cb);
},10);
},function(jqXHR,textStatus) {
console.log('print fail jqHXR:',jqXHR,"textStatus:",textStatus);
if (textStatus=="timeout") {
console.log('TIMEOUT, waiting to try again');
setTimeout(function() {
console.log('now try again');
_printPartPost(lines,data,cb);
},5000);
} else {
console.log("_printPartPost FATAL error:",textStatus);
}
}).fail(function() {
//console.log("PrinterAPI:listAll failed");
if(failedHandler) failedHandler();
});
}
function _printPart(lines,first,start,cb) {
var chunk = lines.splice(0,500);
console.log('printPart',chunk.length,lines.length);
if (chunk.length>0) {
var data = {gcode: chunk.join("\n"), first: first, start: start};
_printPartPost(lines,data,function() {
console.log('_printPartPost cb');
cb(); //??? needed
});
} else {
console.log('no more print parts');
cb(); //finished
}
}
this.print = function(gcode,start,first,success,fail) {
//need a check here for state??
this.remainingLines = gcode.split("\n");
this.totalLinesAtStart = this.remainingLines.length;
// console.log('remainingLines.length',this.remainingLines.length);
_printPart(this.remainingLines,true,true,function() {
console.log('done sending');
});
};
this.stop = function(endcode,success,fail) {
//need a check here for state??
// console.log('remainingLines',this.remainingLines.length);
this.remainingLines.length = 0; //clear array
totalLinesAtStart = 0;
API.post('printer/stop',{gcode:endcode},success,fail);
}
}

15
js/api/SketchAPI.js Normal file
View File

@ -0,0 +1,15 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function SketchAPI() {
this.load = function(id,success,fail) {
API.get('sketch/?id='+id,success,fail);
}
}

View File

@ -310,7 +310,6 @@ function oopsUndo() {
}
function previewUp(redrawLess) {
// console.log("f:previewUp()");
if (numLayers < maxNumLayers) {
numLayers++;
}

View File

@ -1,7 +1,6 @@
body {
font-family: Helvetica, Abel, Arial;
font-size: 1em;
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none; /* mozilla browsers */
-khtml-user-select: none; /* webkit (konqueror) browsers */
@ -12,7 +11,7 @@ button {
font-size: 1em;
}
div.item {
.item {
width:150px;
height:130px;
border:1px solid black;
@ -22,14 +21,10 @@ div.item {
margin-right: 5px;
}
div.item.selected {
.item.selected {
background-color: #7cf;
}
div.item input[type='checkbox'] {
position: absolute;
}
#frmUpload {
display: inline;
}
@ -41,9 +36,11 @@ input[type='file'] {
#txtInfo {
float: right;
margin-top: 5px;
/*display: inline-block;*/
}
img#logo {
cursor: pointer;
}
}

View File

@ -6,25 +6,22 @@
</head>
<body>
<span id="txtInfo"></span>
<img id="logo" src="../img/logo/doodle3d.png" height="25">
<hr>
<button id="btnSelectAll">Select all</button>
<button id="btnDeselectAll">Deselect all</button>
<button id="btnDelete">Delete</button>
<button id="btnDownload">Download</button> <!-- <a id="link" href="#">Download</a> -->
<button id="btnPrint">Print...</button>
<button id="btnRefresh">Refresh</button>
<form id="frmUpload"><button id="btnUpload">Upload</button><input id="uploads" type="file" accept="image/svg+xml" multiple/></form>
<span id="txtInfo"></span>
<hr>
<form>
<div id="svgContainer"></div>
</form>
<script src="../js/libs/jquery-1-9-1.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>

View File

@ -24,6 +24,8 @@ $("#btnSelectAll").click(selectAll);
$("#btnDeselectAll").click(deselectAll);
$("#uploads").change(upload);
$("#btnDownload").click(download);
$("#btnRefresh").click(refresh);
$("#btnPrint").click(print);
$("#btnUpload").click(function(e) {
e.preventDefault();
@ -60,6 +62,7 @@ $.get(api+'list', function(data) { //?id=00003
console.log(status);
});
function onLogoClick() {
location.href='/'+location.search;
}
@ -93,15 +96,14 @@ function addItem(id,svgData,doPrepend) {
else if (svgData.indexOf("CDATA")==-1) path = "";
else path = svgData.split('d="')[1].split('"')[0];
var item = $('<div class="item" data="'+id+'" title="'+id+'">');
var item = $('<li class="item ui-widget-content" data="'+id+'" title="'+id+'"></li>');
var svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 640 540"><path fill="none" stroke="black" stroke-width="2" d="'+path+'"></path></svg>';
item.append(svg);
item.click(function() {
$(this).toggleClass('selected');
console.log($(this).attr("data"));
updateButtonStates();
})
item.append(svg);
if (doPrepend) $('#svgContainer').prepend(item);
else $('#svgContainer').append(item);
@ -173,8 +175,10 @@ function updateButtonStates() {
$("#btnDeselectAll").attr("disabled",isBusy || noSelection);
$("#btnSelectAll").attr("disabled",isBusy || numItems==0);
$("#btnUpload").attr("disabled",isBusy || !noSelection);
$("#btnDelete").text("Delete" + (noSelection ? "" : " ("+numSelected+")"));
$("#btnDownload").text("Download" + (noSelection ? "" : " ("+numSelected+")"));
$("#btnPrint").attr("disabled",isBusy || noSelection);
// $("#btnDelete").text("Delete" + (noSelection ? "" : " ("+numSelected+")"));
// $("#btnDownload").text("Download" + (noSelection ? "" : " ("+numSelected+")"));
// $("#btnPrint").text("Print" + (noSelection ? "..." : " ("+numSelected+")..."));
}
function uploadFile(files, index, next) {
@ -265,3 +269,15 @@ function download() {
});
}
function refresh() {
location.reload();
}
function print() {
var ids = [];
$('.item.selected').each(function() {
ids.push($(this).attr('data'));
});
location.href = '/printmanager/' + location.search + "&ids=" + ids.join();
}

View File

@ -182,6 +182,7 @@
<script src="js/libs/jquery-coolfieldset.min.js"></script>
<script src="js/libs/FileSaver.min.js"></script>
<script src="js/libs/jquery-fastclick.min.js"></script>
<script src="js/doodle3d-api.min.js"></script>
<script src="js/doodle3d-client.min.js"></script>
</body>

6
www/js/patch.patch Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,90 @@
body {
font-family: Helvetica, Abel, Arial;
font-size: 1em;
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none; /* mozilla browsers */
-khtml-user-select: none; /* webkit (konqueror) browsers */
-ms-user-select: none; /* IE10+ */
}
button {
font-size: 1em;
}
#svgContainer {
width: 540px;
height: 540px;
border: 1px solid black;
margin: 0 auto;
position: relative;
overflow: hidden;
display: inline-block;
}
#svgContainer svg {
border: 1px solid lightgrey;
position: absolute;
}
#printPreview {
width: 540px;
height: 540px;
border: 1px solid black;
margin: 0 auto;
position: relative;
display: inline-block;
}
/*#svgContainer {
width: 640px;
height: 640px;
border: 1px solid black;
display: inline-block;
}*/
/*.item {
padding: 0.5em;
display: inline-block;
position: absolute;
margin-right: 5px;
margin-bottom: 5px;
cursor: pointer;
}
.item.selected {
background-color: rgba(102, 206, 255, 0.4);
}
.item.crosshair {
cursor: crosshair;
}*/
#frmUpload {
display: inline;
}
#txtInfo {
float: right;
}
img#logo {
cursor: pointer;
margin-right: 10px;
}
#buttonsPanel {
float: right;
}
span.statusvar {
background-color: #7cf;
margin: 2px 2px 2px 2px;
padding: 5px 5px 2px 5px;
}
#preview {
display: inline-block;
border: 1px solid black;
width: 640px;
height: 540px;
}

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>Doodle3D</title>
<link href="css/style.css" rel="stylesheet" media="screen">
<link href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/css/base/jquery.ui.all.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.2/css/lightness/jquery-ui-1.10.2.custom.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.2/jquery.ui.touch-punch.min.js"></script>
</head>
<body>
<img id="logo" src="../img/logo/doodle3d.png" height="25" alt="Doodle3D">PrintManager
<button id="btnRefresh">Refresh</button>
<!-- <button id="btnPlus">+</button>
<button id="btnMin">-</button> -->
<button id="btnPrepare">Prepare</button>
<button id="btnPrint">Print</button>
<button id="btnStop">Stop</button>
<input type="file" name="file"/>
<span class="statusvar" id="lblState"></span>
<span class="statusvar" id="lblNozzle"></span>
<span class="statusvar" id="lblBed"></span>
<span class="statusvar" id="txtInfo"></span>
<span class="statusvar" id="lblBufferProgress"></span>
<span class="statusvar" id="lblPrintProgress"></span>
<hr>
<div id="svgContainer"></div>
<div id="printPreview"></div>
<script src="../js/doodle3d-api.js"></script>
<script src="js/touchSwipe.min.js"></script>
<script src="js/Point.js"></script>
<script src="js/Rectangle.js"></script>
<script src="js/Polyline.js"></script>
<script src="js/Path.js"></script>
<script src="js/Svg.js"></script>
<script src="js/Doodle.js"></script>
<script src="js/Viewer.js"></script>
<script src="js/Doodle2gcode.js"></script>
<script src="js/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,177 @@
var Doodle = function(svgData,settings) {
var path = new Path();
var height = 50; //in mm
var offset = new Point(0,0);
var scale = 1;
var rotation = 0;
var twist = 0;
if (svgData!==undefined) {
setFromSvgPathDescription(svgData);
removeShortPaths(); //move this to main.js?
//TODO: determine current offset from boundingbox and store in 'offset' variable
path.alignCorner(); //set left-top corner of path boundingbox to 0,0
}
if (settings!==undefined) {
if (settings.height!==undefined) height = settings.height;
if (settings.twist!==undefined) twist = settings.twist;
}
function setFromSvgPathDescription(svgData) {
// if (!svgData) svgData = "";
// else if (typeof(svgData)!='string') svgData = "";
// // else if (svgData.indexOf("CDATA")==-1) svgData = "";
// else svgData = svgData.split('d="')[1].split('"')[0];
console.log('svgData',svgData);
svgData+=' '; //add a trailing space
//Parse Path Description
var mode = '', x=0, y=0, p=0;
var path = new Path();
var skipSpace = function() {
while (svgData.charAt(p) == ' ') p++;
}
var parser = function() {
while (true) {
skipSpace();
if (p==svgData.length) {
return true;
}
var c = svgData.charAt(p);
if (c == 'M' || c == 'm' || c == 'L' || c == 'l') { //new command letter
mode = c;
} else if (c == '"') { //end of command chain
return true;
} else { //something else, must be a pair of coordinates...
var tx = 0, ty = 0, numberEnd = 0, len = 0;
numberEnd = svgData.indexOf(',', p);
////// RC: if instead of a comma a space is used between a pair use that as a separator
//var firstSpace = svgData.indexOf(' ', p);
//if (firstSpace<numberEnd) numberEnd=firstSpace;
if (numberEnd == -1) { console.log("parsePathDescription:could not find *COMMA* in coordinate pair pos:",p,'of',svgData.length,svgData.substr(p)); return false; }
len = numberEnd - p;
tx = parseFloat(svgData.substr(p, len));
p += len + 1;
skipSpace();
numberEnd = svgData.indexOf(' ', p);
if (numberEnd == -1) { console.log("parsePathDescription:could not find *SPACE* after coordinate pair",p,'of',svgData.length); return false; }
len = numberEnd - p;
ty = parseFloat(svgData.substr(p, len));
p += len;
if (mode == 'M' || mode == 'L') {
x = tx; y = ty;
} else if (mode == 'm' || mode == 'l') {
x += tx; y += ty;
} else {
console.log("parsePathDescription: found coordinate pair but mode was never set");
return false;
}
var isMove = mode == 'm' || mode == 'M';
if (isMove) path.moveTo(x,y);
else path.lineTo(x,y);
}
p++;
}
}
parser();
setPath(path);
}
function getSvgPathDescription() {
var d = "";
var polylines = path.getPolylines();
for (var i=0; i<polylines.length; i++) {
var points = polylines[i].getPoints();
for (var j=0; j<points.length; j++) {
d += (j==0 ? "M" : "L");
d += Math.round(points[j].x) + "," + Math.round(points[j].y) + " ";
}
}
return d;
// return '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="640" height="540"><path xmlns="http://www.w3.org/2000/svg" fill="none" stroke="black" stroke-width="2" d="'+d+'"></path></svg>';
}
function removeShortPaths(minLength,minPoints) {
if (!minLength) minLength = 10;
if (!minPoints) minPoints = 1;
path.setPolylines(path.getPolylines().filter(function(polyline) {
return polyline.getPoints().length>minPoints && polyline.getPerimeter()>minLength;
}));
}
function getPath() {
return path;
}
function setPath(newPath) {
path = newPath
}
function getSettings() {
return settings;
}
function getHeight() {
return height;
}
function getTwist() {
return twist;
}
function getScale() {
return scale;
}
function setScale(_scale) {
scale = _scale;
}
function getOffset() {
return offset;
}
function setOffset(_offset) {
offset = _offset;
}
function getRotation() {
return rotation;
}
function getScaleFunction(f) {
return 1; //Math.sin(f*2*Math.PI)/4+1;
}
return {
getPath: getPath,
setPath: setPath,
getSettings: getSettings,
setFromSvgPathDescription: setFromSvgPathDescription,
getSvgPathDescription: getSvgPathDescription,
getHeight: getHeight,
getRotation: getRotation,
getTwist: getTwist,
getScaleFunction: getScaleFunction,
getScale: getScale,
setScale: setScale,
getOffset: getOffset,
setOffset: setOffset,
}
}

View File

@ -0,0 +1,109 @@
var Doodle2gcode = function() {
var className = "Doodle2gcode";
var speed = 50;
var layerHeight = .2;
var filamentDiameter = 2.89;
var nozzleDiameter = .4;
var dimensions = {x:200,y:200,z:200};
var px2mm = .3;
var nozzleFilamentRatio = nozzleDiameter / filamentDiameter;
var layerNozzleRatio = layerHeight / nozzleDiameter;
var extrudeFactor = nozzleFilamentRatio * layerNozzleRatio;
var flowRatio = 1;
var extruder = 0;
function generate(doodles) {
var gcode = "";
extruder = 0;
for (var z=0,layer=0; z<dimensions.z; z+=layerHeight,layer++) {
for (var i=0; i<doodles.length; i++) {
var path = getDoodlePathAtHeight(doodles[i],z);
// var path = new Path();
// path.moveTo(0,0);
// path.lineTo(100,0);
// path.lineTo(100,100);
// path.lineTo(0,100);
// path.lineTo(0,0);
gcode += path2gcode(path,z);
}
}
return gcode;
}
function getDoodlePathAtHeight(doodle,z) {
if (z>doodle.getHeight()) return new Path(); //return empty path, doodle not visible in this slice
var zz = z/doodle.getHeight(); //0..1
var rotation = doodle.getRotation();
var twist = zz * doodle.getTwist();
var offset = doodle.getOffset();
var scale = doodle.getScale();
var scaler = doodle.getScaleFunction(zz);
var path = doodle.getPath().clone();
// var org = path.getOffset();
var box = path.getBoundingBox();
// console.log(box.toString());
path.translate(-box.getX(),-box.getY());
path.translate(-box.getWidth()/2,-box.getHeight()/2);
// path.alignCenter();
path.scale(scale);
path.scale(scaler);
path.translate(box.getX(),box.getY());
path.translate(box.getWidth()/2,box.getHeight()/2);
// path.rotate(rotation);
path.rotate(twist,box.getCenter());
// path.alignCorner();
path.translate(offset.x,offset.y);
return path;
}
function path2gcode(path,z) {
var gcode = '';
var polylines = path.getPolylines();
path.scale(px2mm);
path.translate(0,-dimensions.y);
for (var i=0; i<polylines.length; i++) {
var points = polylines[i].getPoints();
for (var j=0; j<points.length; j++) {
var x = points[j].x;
var y = -points[j].y;
gcode += (j==0 ? 'G0' : 'G1');
gcode += ' ';
gcode += 'X' + x.toFixed(2);
gcode += ' ';
gcode += 'Y' + y.toFixed(2);
gcode += ' ';
gcode += 'Z' + z.toFixed(2);
gcode += ' ';
if (j>0) {
var dist = points[j-1].distance(points[j]) * px2mm;
extruder += dist * extrudeFactor * flowRatio;
gcode += 'E' + extruder.toFixed(4);
}
gcode += '\n';
}
}
return gcode;
}
return {
generate: generate,
}
}

104
www/printmanager/js/Path.js Normal file
View File

@ -0,0 +1,104 @@
var Path = function() {
var className = "Path";
var polylines = [];
function translate(x,y) {
for (var i = 0; i < polylines.length; i++) {
polylines[i].translate(x,y);
}
}
function rotate(radians,pivot) {
for (var i = 0; i < polylines.length; i++) {
var points = polylines[i].getPoints();
for (var j = 0; j < points.length; j++) {
points[j].rotate(radians,pivot)
}
}
}
function scale(scale) {
for (var i = 0; i < polylines.length; i++) {
// console.log(className,'scale',scale);
polylines[i].scale(scale);
}
}
function moveTo(x,y) {
polylines.push(new Polyline(x,y));
}
function lineTo(x,y) {
if (polylines.length==0) moveTo(x,y);
else polylines[polylines.length-1].addVertex(x,y);
}
function getBoundingBox() {
var box = new Rectangle(0,0,0,0);
for (var i = 0; i < polylines.length; i++) {
if (i==0) box = polylines[i].getBoundingBox();
else box.growToIncludeRectangle(polylines[i].getBoundingBox());
}
return box;
}
function getWidth() {
return this.getBoundingBox().getWidth();
}
function getHeight() {
return this.getBoundingBox().getHeight();
}
function getPolylines() {
return polylines;
}
function setPolylines(_polylines) {
polylines = _polylines;
}
function clone() {
var p = new Path();
for (var i=0; i<polylines.length; i++) {
// console.log(className,'clone poly#',i,"/",polylines.length,polylines[i].toString(),"||||",polylines[i].clone().toString());
p.getPolylines().push(polylines[i].clone());
}
// console.log(className,'p.toString()',p.toString());
return p;
}
function alignCorner() {
var box = getBoundingBox();
translate(-box.getX(),-box.getY());
}
function alignCenter() {
var box = getBoundingBox();
// console.log(className,'alignCenter',box.toString());
translate(-box.getX(),-box.getY());
translate(-box.getWidth()/2,-box.getHeight()/2);
}
function toString() {
return polylines.join(" --- ");
}
return {
translate: translate,
rotate: rotate,
scale: scale,
moveTo: moveTo,
lineTo: lineTo,
getBoundingBox: getBoundingBox,
getWidth: getWidth,
getHeight: getHeight,
getPolylines: getPolylines,
setPolylines: setPolylines,
clone: clone,
alignCenter: alignCenter,
alignCorner: alignCorner,
toString: toString
}
}

View File

@ -0,0 +1,37 @@
var Point = function(x,y) {
if (x===undefined) x = 0;
if (y===undefined) y = 0;
if (isNaN(x) || isNaN(y)) {
console.warning("Point x or y isNaN: ",x,y);
}
this.x = x;
this.y = y;
}
// Point.prototype.clone = function() { //not used since it easy to clone a point using 'new Point(org.x,org.y)'
// return new Point(this.x, this.y);
// }
Point.prototype.distance = function(p) {
var x1 = this.x;
var y1 = this.y;
var x2 = p.x;
var y2 = p.y;
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
Point.prototype.rotate = function(radians,pivot) {
if (pivot===undefined) pivot = new Point(0,0);
var x = this.x;
var y = this.y;
var xrot = ((x-pivot.x)*Math.cos(radians) - (y-pivot.y)*Math.sin(radians)) + pivot.x;
this.y = ((x-pivot.x)*Math.sin(radians) + (y-pivot.y)*Math.cos(radians)) + pivot.y;
this.x = xrot;
}
Point.prototype.toString = function(p) {
return this.x.toFixed(2) + "," + this.y.toFixed(2);
}

View File

@ -0,0 +1,84 @@
var Polyline = function(x,y) {
var className = "Polyline";
var points = [new Point(x,y)];
function translate(x,y) {
for (var i = 0; i < points.length; i++) {
points[i].x += x;
points[i].y += y;
}
}
function rotate(degrees) {
console.log('rotate: to be implemented')
}
function scale(scale) {
for (var i = 0; i < points.length; i++) {
points[i].x *= scale;
points[i].y *= scale;
}
}
function addVertex(x,y) {
var p = new Point(x,y);
points.push(p);
}
function getBoundingBox() {
var box = new Rectangle(0,0,0,0);
for (var i=0; i<points.length; i++) {
if (i==0) box.set(points[i].x,points[i].y,0,0);
else box.growToIncludePoint(points[i]);
}
return box;
}
function getWidth() {
return getBoundingBox().getWidth();
}
function getHeight() {
return getBoundingBox().getHeight();
}
function getPoints() {
return points;
}
function getPerimeter() {
var len = 0;
for (var i = 1; i < points.length; i++) {
len += points[i-1].distance(points[i]);
}
return len;
}
function clone() {
var p = new Polyline(points[0].x,points[0].y);
for (var i=1; i<points.length; i++) {
p.getPoints().push(new Point(points[i].x, points[i].y));
}
return p;
}
function toString() {
return points.join(", ");
}
return {
translate: translate,
rotate: rotate,
scale: scale,
addVertex: addVertex,
getBoundingBox: getBoundingBox,
getPerimeter: getPerimeter,
getWidth: getWidth,
getHeight: getHeight,
getPoints: getPoints,
clone: clone,
toString: toString,
}
}

View File

@ -0,0 +1,64 @@
var Rectangle = function(_x,_y,_w,_h) {
var x,y,w,h;
set(_x,_y,_w,_h);
function set(_x,_y,_w,_h) {
x = _x;
y = _y;
w = _w;
h = _h;
}
function growToIncludeRectangle(rect) {
growToIncludePoint(new Point(rect.getMinX(),rect.getMinY()));
growToIncludePoint(new Point(rect.getMaxX(),rect.getMaxY()));
}
function growToIncludePoint(p) {
var x0 = Math.min(getMinX(),p.x);
var x1 = Math.max(getMaxX(),p.x);
var y0 = Math.min(getMinY(),p.y);
var y1 = Math.max(getMaxY(),p.y);
var w = x1 - x0;
var h = y1 - y0;
set(x0,y0,w,h);
}
function getCenter() {
var cx = (getMaxX()-getMinX()) / 2;
var cy = (getMaxY()-getMinY()) / 2;
return new Point(cx,cy);
}
function getX() { return x; }
function getY() { return y; }
function getWidth() { return w; }
function getHeight() { return h; }
function getMinX() { return Math.min(x, x + w); }
function getMaxX() { return Math.max(x, x + w); }
function getMinY() { return Math.min(y, y + h); }
function getMaxY() { return Math.max(y, y + h); }
function toString() {
return 'x:' + x + ", y:" + y + ", w:" + w + ", h:" + h;
}
return {
getMinX: getMinX,
getMaxX: getMaxX,
getMinY: getMinY,
getMaxY: getMaxY,
getWidth: getWidth,
getHeight: getHeight,
set: set,
growToIncludeRectangle: growToIncludeRectangle,
growToIncludePoint: growToIncludePoint,
toString: toString,
getX: getX,
getY: getY,
getCenter: getCenter,
}
}

149
www/printmanager/js/Svg.js Normal file
View File

@ -0,0 +1,149 @@
// var Svg = function() {
// // var pathElement;
// var svgElement;
// var path;
// this.load = function(svgData) {
// if (!svgData) svgData = "";
// else if (typeof(svgData)!='string') svgData = "";
// // else if (svgData.indexOf("CDATA")==-1) svgData = "";
// else svgData = svgData.split('d="')[1].split('"')[0];
// svgElement = $('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="640" height="540"><path xmlns="http://www.w3.org/2000/svg" fill="none" stroke="black" stroke-width="2" d="'+svgData+'"></path></svg>');
// var pathElement = $(svgElement).find('path');
// var pathDescription = pathElement.attr('d');
// var path = parsePathDescription(pathDescription);
// var box = path.getBoundingBox();
// console.log(box.toString());
// var polylines = path.getPolylines();
// for (var i=0; i<polylines.length; i++) {
// var len = polylines[i].getPerimeter();
// // console.log(i,len,);
// if (len<10 || polylines[i].getPoints().length<6) {
// console.log('removing polyline ',i);
// polylines.splice(i,1);
// }
// }
// var box = path.getBoundingBox();
// path.translate(-box.getX()+1,-box.getY()+1);
// svgElement.attr('width',box.getWidth()+2);
// svgElement.attr('height',box.getHeight()+2);
// // var indices = path.getPointIndicesByDistance(367,433,50);
// // console.log('indices',indices);
// // svgElement.append('<circle xmlns="http://www.w3.org/2000/svg" version="1.1" cx="60" cy="60" r="50"/>');
// // var points = path.getPoints();
// // for (var i=0; i<points.length; i++) {
// // path.removePoint(i);
// // if (i>400) break;
// // }
// // console.log(points.length);
// // console.log(path.getPoints().length);
// // path.removePoint(502);
// // path.removePoint(503);
// var d = getPathDescription(path);
// pathElement.attr('d',d); //update
// }
// function getPathDescription(path) {
// var d = "";
// var polylines = path.getPolylines();
// for (var i=0; i<polylines.length; i++) {
// var points = polylines[i].getPoints();
// for (var j=0; j<points.length; j++) {
// // console.log(i,points.length);
// d += (j==0 ? "M" : "L");
// d += Math.round(points[j].x) + "," + Math.round(points[j].y) + " ";
// }
// }
// return d;
// }
// function parsePathDescription(svgData) {
// var mode = '', x=0, y=0, p=0;
// var path = new Path();
// var skipSpace = function() {
// while (svgData.charAt(p) == ' ') p++;
// }
// var parser = function() {
// while (true) {
// skipSpace();
// if (p==svgData.length) {
// return true;
// }
// var c = svgData.charAt(p);
// if (c == 'M' || c == 'm' || c == 'L' || c == 'l') { //new command letter
// mode = c;
// } else if (c == '"') { //end of command chain
// return true;
// } else { //something else, must be a pair of coordinates...
// var tx = 0, ty = 0, numberEnd = 0, len = 0;
// numberEnd = svgData.indexOf(',', p);
// ////// RC: if instead of a comma a space is used between a pair use that as a separator
// var firstSpace = svgData.indexOf(' ', p);
// if (firstSpace<numberEnd) numberEnd=firstSpace;
// if (numberEnd == -1) { console.log("parsePathDescription:could not find *COMMA* in coordinate pair"); return false; }
// len = numberEnd - p;
// tx = parseFloat(svgData.substr(p, len));
// p += len + 1;
// skipSpace();
// numberEnd = svgData.indexOf(' ', p);
// if (numberEnd == -1) { console.log("parsePathDescription:could not find *SPACE* after coordinate pair"); return false; }
// len = numberEnd - p;
// ty = parseFloat(svgData.substr(p, len));
// p += len;
// if (mode == 'M' || mode == 'L') {
// x = tx; y = ty;
// } else if (mode == 'm' || mode == 'l') {
// x += tx; y += ty;
// } else {
// console.log("parsePathDescription: found coordinate pair but mode was never set");
// return false;
// }
// var isMove = mode == 'm' || mode == 'M';
// if (isMove) path.moveTo(x,y);
// else path.lineTo(x,y);
// }
// p++;
// }
// }
// parser();
// return path;
// }
// this.getElement = function() {
// return svgElement;
// }
// this.getPath = function() {
// }
// }

View File

@ -0,0 +1,180 @@
var Viewer = function(viewer) {
var className = "Viewer";
var doodles = [];
//Object houd data bij van svg transformaties
//(alle svg's worden automatisch hier in gezet, positie is relatief aan zijn html parent)
// x -> x positie
// y -> y positie
// scale -> scale
// svg -> svg object
var svgsData = [];
console.log(className,viewer);
function setDoodles(_doodles) {
doodles = _doodles;
console.log(className,'items',doodles);
for (var i=0; i<doodles.length; i++) {
var doodle = doodles[i];
var path = doodle.getPath();
var svgData = doodle.getSvgPathDescription();
var box = path.getBoundingBox();
var svg = $('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="640" height="540"><path xmlns="http://www.w3.org/2000/svg" fill="none" stroke="black" stroke-width="2" d="'+svgData+'"></path></svg>');
viewer.append(svg);
var box = path.getBoundingBox();
var viewbox = box.getX() + " " + box.getY() + " " + box.getWidth() + " " + box.getHeight();
svg[0].setAttribute("viewBox", viewbox); //changig the viewBox with jQuery doesn't work (may be because of capital B)
svg.attr('width',box.getWidth()+2);
svg.attr('height',box.getHeight()+2);
initTouch(svg,doodle)
}
}
function initTouch(svg,doodle) {
// $("svg").each(function () {
// var svg = $(this);
// var data = {
// x: 0,
// y: 0,
// scale: 1,
// };
// svgsData.push(data);
var startX;
var startY;
var touchX;
var touchY;
var offsetX = 0;
var offsetY = 0;
var handleGesture = false;
var offsetZoom = 1;
var zoom = 1;
var mouseDown = false;
svg.on("mousedown", function (e) {
var event = e.originalEvent;
mouseDown = true;
touchX = startX = event.pageX;
touchY = startY = event.pageY;
});
$(document).on("mousemove", function (e) {
if (mouseDown) {
var event = e.originalEvent;
touchX = event.pageX;
touchY = event.pageY;
var dX = touchX - startX;
var dY = touchY - startY;
svg.css({
left: offsetX + dX,
top: offsetY + dY
});
}
});
svg.on("mouseup", function (e) {
var event = e.originalEvent;
mouseDown = false;
offsetX = offsetX + touchX - startX;
offsetY = offsetY + touchY - startY;
setData();
});
svg.on("touchstart", function (e) {
var event = e.originalEvent;
event.preventDefault();
if (event.touches.length === 1) {
var touch = event.touches[0];
touchX = startX = touch.pageX;
touchY = startY = touch.pageY;
}
else {
handleGesture = true;
}
});
svg.on("touchmove", function (e) {
var event = e.originalEvent;
event.preventDefault();
if (event.touches.length === 1 && !handleGesture) {
var touch = event.touches[0];
touchX = touch.pageX;
touchY = touch.pageY;
var dX = touchX - startX;
var dY = touchY - startY;
svg.css({
left: offsetX + dX,
top: offsetY + dY
});
}
});
svg.on("touchend", function (e) {
var event = e.originalEvent;
if (event.touches.length === 0) {
if (handleGesture) {
handleGesture = false;
}
else {
offsetX = offsetX + touchX - startX;
offsetY = offsetY + touchY - startY;
setData();
}
}
});
svg.swipe({
pinchStatus: function (event, phase, direction, distance , duration , fingerCount, pinchZoom) {
if (phase === "cancel" || phase === "end") {
offsetZoom = offsetZoom*zoom;
setData();
}
else {
zoom = pinchZoom;
svg.css({transform: "scale(" + offsetZoom*zoom + ")"});
}
},
fingers: 2,
pinchThreshold: 0
});
function setData () {
var offset = {
x: offsetX - svg.width()*offsetZoom/2 + svg.width()/2,
y: offsetY - svg.height()*offsetZoom/2 + svg.height()/2
}
doodle.setScale(offsetZoom);
doodle.setOffset(offset);
// data.scale = offsetZoom;
// data.x = offsetX - svg.width()*offsetZoom/2 + svg.width()/2;
// data.y = offsetY - svg.height()*offsetZoom/2 + svg.height()/2;
// console.log(data);
}
}
return {
setDoodles: setDoodles,
}
}

13
www/printmanager/js/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
/*!
* jQuery UI Touch Punch 0.2.3
*
* Copyright 20112014, Dave Furfero
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Depends:
* jquery.ui.widget.js
* jquery.ui.mouse.js
*/
!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);

198
www/printmanager/js/main.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
www/printmanager/js/svg.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
www/printmanager/js/touchSwipe.min.js vendored Executable file

File diff suppressed because one or more lines are too long