progress on printmanager

This commit is contained in:
Rick Companje 2015-04-27 23:38:01 +02:00
parent 0c2f774376
commit 7f4965400c
12 changed files with 736 additions and 290 deletions

View File

@ -11,8 +11,15 @@ var API = function() {
var _wifiboxURL = 'http://192.168.5.1/d3dapi/';
var _wifiboxCGIBinURL = 'http://192.168.5.1/cgi-bin/d3dapi/';
var _timeoutTime = 10000;
var _isBusy = false;
function setURL(url,cgiUrl) {
_wifiboxURL = url;
_wifiboxCGIBinURL = cgiUrl || url;
}
function post(cmd,data,success,fail) {
_isBusy = true;
$.ajax({
url: _wifiboxURL + cmd,
type: "POST",
@ -20,6 +27,7 @@ var API = function() {
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
_isBusy = false;
if(response.status == "error" || response.status == "fail") {
console.log('API.post fail',cmd)
if (fail) fail(response);
@ -29,18 +37,21 @@ var API = function() {
}
}
}).fail(function(jqXHR, textStatus) {
_isBusy = false;
console.log('API.post fail',cmd,jqXHR,textStatus);
if (fail) fail(jqXHR,textStatus);
});
}
function get(cmd,success,fail) {
_isBusy = true;
$.ajax({
url: _wifiboxURL + cmd,
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
success: function(response) {
_isBusy = false;
if (response.status == "error" || response.status == "fail") {
console.log('API.get fail',cmd,response);
if (fail) fail(response);
@ -50,14 +61,21 @@ var API = function() {
}
}
}).fail(function() {
_isBusy = false;
console.log('API.get fail',cmd);
if (fail) fail();
});
}
function getBusy() {
return _isBusy;
}
return {
get: get,
post: post
post: post,
getBusy: getBusy,
setURL: setURL,
}
}();

View File

@ -7,7 +7,12 @@
*/
function ConfigAPI() {
var className = 'ConfigAPI';
function init() {
console.log(className,'init is deprecated');
}
function loadAll(success,fail) {
API.get('config/all',success,fail);
};
@ -73,6 +78,7 @@ function ConfigAPI() {
}
return {
init: init,
loadAll: loadAll,
load: load,
save: save,

View File

@ -7,10 +7,15 @@
*/
function PrinterAPI() {
var className = 'PrinterAPI';
this.remainingLines = [];
this.totalLinesAtStart = 0;
this.init = function() {
console.log(className,'init is deprecated');
}
this.state = function(success,fail) {
API.get('printer/state',success,fail);
};
@ -57,8 +62,8 @@ function PrinterAPI() {
var data = {gcode: chunk.join("\n"), first: first, start: start};
_printPartPost(lines,data,function() {
console.log('_printPartPost cb');
cb(); //??? needed
// console.log('_printPartPost cb');
// cb(); //??? needed
});
} else {

View File

@ -182,8 +182,8 @@
<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>
<script src="js/doodle3d-api.js"></script>
<script src="js/doodle3d-client.js"></script>
</body>
</html>

View File

@ -1,6 +1,7 @@
body {
font-family: Helvetica, Abel, Arial;
font-family: Abel, 'sans-serif-thin', Sans-serif, Helvetica, Arial;
font-size: 1em;
margin: 0 0 0 0;
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none; /* mozilla browsers */
@ -12,13 +13,47 @@ button {
font-size: 1em;
}
#toolbar {
padding-top: 10px;
padding-left: 10px;
float: left;
width: 300px;
height: 100%;
}
#btnPrint {
font-size: 30px;
/*width: 100px;*/
/*height: 100px;*/
}
#toolbar h1 {
margin-top: 5px;
font-size: 1.5em;
}
#rightToolbar {
margin-top: 5px;
margin-right: 5px;
float: right;
}
#toolbar button {
display: block;
margin-top: 10px;
margin-right: 10px;
}
#svgContainer {
width: 540px;
height: 540px;
/*margin-top: 10px;*/
background-color: #fff;
width: 640px;
height: 640px;
border: 1px solid black;
margin: 0 auto;
position: relative;
overflow: hidden;
top: 10px;
display: inline-block;
}
#svgContainer svg {
@ -27,8 +62,8 @@ button {
}
#printPreview {
width: 540px;
height: 540px;
width: 640px;
height: 640px;
border: 1px solid black;
margin: 0 auto;
position: relative;
@ -70,6 +105,7 @@ button {
img#logo {
cursor: pointer;
margin-right: 10px;
width: 200px;
}
#buttonsPanel {
@ -79,7 +115,8 @@ img#logo {
span.statusvar {
background-color: #7cf;
margin: 2px 2px 2px 2px;
padding: 5px 5px 2px 5px;
/*padding: 5px 5px 2px 5px;*/
display: block;
}
#preview {

View File

@ -3,45 +3,47 @@
<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>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
</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="toolbar">
<img id="logo" src="../img/logo/doodle3d.png" alt="Doodle3D">
<h1>Management App</h1>
<hr>
<button id="btnRefresh">Refresh</button>
<button id="btnDownload">Download</button>
<button id="btnPrint">Print</button>
<button id="btnStop">Stop</button>
<button id="btnExtrude">Extrude 10mm</button>
<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>
<div id="svgContainer"></div>
<div id="printPreview"></div>
<div id="rightToolbar">
</div>
<!-- <canvas id="printPreview" id="canvas" width="400" height="400"></canvas> -->
<script src="../js/libs/jquery-1-9-1.min.js"></script>
<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/ViewerItem.js"></script>
<script src="js/Viewer.js"></script>
<script src="js/Doodle2gcode.js"></script>
<script src="js/PrintPreview.js"></script>
<script src="js/main.js"></script>
</body>

View File

@ -1,32 +1,40 @@
var Doodle = function(svgData,settings) {
var path = new Path();
var height = 50; //in mm
var height = 10; //in mm
var offset = new Point(0,0);
var scale = 1;
var rotation = 0;
var twist = 0;
var twist = .1;
if (svgData!==undefined) {
if (settings!=undefined) {
if (settings.height!=undefined) height = settings.height;
if (settings.twist!=undefined) twist = settings.twist;
if (settings.scale!=undefined) scale = settings.scale;
if (settings.offset!=undefined) offset = settings.offset;
}
if (svgData!=undefined) {
setFromSvgPathDescription(svgData);
removeShortPaths(); //move this to main.js?
//TODO: determine current offset from boundingbox and store in 'offset' variable
// offset.x += path.getBoundingBox().getX();
// offset.y += path.getBoundingBox().getY();
path.alignCorner(); //set left-top corner of path boundingbox to 0,0
// scale = 1;
// console.log(path.getBoundingBox().getX(),offset);
}
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);
// console.log('svgData',svgData);
svgData+=' '; //add a trailing space

View File

@ -1,17 +1,23 @@
var Doodle2gcode = function() {
var className = "Doodle2gcode";
var speed = 50;
var speed = 100 * 60; //mm/min
var travelSpeed = 150 * 60 //mm/min
var retractionSpeed = 45 * 60 //mm/min
var retractionAmount = 4.5;
var layerHeight = .2;
var filamentDiameter = 2.89;
var nozzleDiameter = .4;
var dimensions = {x:200,y:200,z:200};
var px2mm = .3;
var flow = 1;
var filamentArea = Math.PI * (filamentDiameter/2)*(filamentDiameter/2);
var extrusionPerMM = layerHeight / filamentArea * flow;
var nozzleFilamentRatio = nozzleDiameter / filamentDiameter;
var layerNozzleRatio = layerHeight / nozzleDiameter;
var extrudeFactor = nozzleFilamentRatio * layerNozzleRatio;
var flowRatio = 1;
// var nozzleFilamentRatio = nozzleDiameter / filamentDiameter;
// var layerNozzleRatio = layerHeight / nozzleDiameter;
// var extrudeFactor = nozzleFilamentRatio * layerNozzleRatio;
// var flowRatio = 1;
var extruder = 0;
@ -19,16 +25,13 @@ var Doodle2gcode = function() {
var gcode = "";
extruder = 0;
for (var z=0,layer=0; z<dimensions.z; z+=layerHeight,layer++) {
gcode += ';LAYER:' + layer + '\n';
if (layer==0) gcode += 'M107\nM220 S50\n'; //fan off, print half speed
else if (layer==1) gcode += 'M106 S255\nM220 S100\n' //fan on, print full speed
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);
// console.log(path.getBoundingBox().toString());
gcode += path2gcode(path,z);
}
@ -49,12 +52,12 @@ var Doodle2gcode = function() {
// var org = path.getOffset();
var box = path.getBoundingBox();
// console.log(box.toString());
//center object on origin to apply transformations
path.translate(-box.getX(),-box.getY());
path.translate(-box.getWidth()/2,-box.getHeight()/2);
// path.alignCenter();
path.scale(scale);
path.scale(scaler);
@ -63,8 +66,11 @@ var Doodle2gcode = function() {
// path.rotate(rotation);
path.rotate(twist,box.getCenter());
// path.alignCorner();
path.translate(offset.x,offset.y);
var scaledCenterX = box.getCenter().x * (1-(scale * scaler));
var scaledCenterY = box.getCenter().y * (1-(scale * scaler));
path.translate(offset.x - scaledCenterX, offset.y - scaledCenterY);
return path;
}
@ -76,28 +82,41 @@ var Doodle2gcode = function() {
path.scale(px2mm);
path.translate(0,-dimensions.y);
// G1 X95.054 Y95.154 E4.83242
// G1 F2400 E0.33242 ;retract voor travel
// G0 F9000 X98.641 Y93.617
// ;TYPE:WALL-INNER
// G1 F2400 E4.83242 ;unretract na een travel en voor
// G1 F1200 X98.621 Y93.596 E4.83297
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 += ' ';
//retract + travel + unretract
if (j==0) {
gcode += 'G0 F' + retractionSpeed + ' E' + (extruder-retractionAmount).toFixed(4) + '\n';
gcode += 'G0 F' + travelSpeed + ' X' + x.toFixed(2) + ' Y' + y.toFixed(2) + ' Z' + z.toFixed(2) + '\n';
gcode += 'G1 F' + retractionSpeed + ' E' + extruder.toFixed(4) + '\n';
} else {
gcode += 'G1 '; //gcode command
if (j==1) gcode += 'F' + speed + ' '; //print speed
gcode += 'X' + x.toFixed(2) + ' Y' + y.toFixed(2) + ' ';
if (j>0) {
var dist = points[j-1].distance(points[j]) * px2mm;
extruder += dist * extrudeFactor * flowRatio;
gcode += 'E' + extruder.toFixed(4);
//extrude
if (j>0) {
var dist = points[j-1].distance(points[j]) * px2mm;
extruder += dist * extrusionPerMM;
gcode += 'E' + extruder.toFixed(4);
}
gcode += '\n';
}
gcode += '\n';
}
}
return gcode;

View File

@ -0,0 +1,374 @@
var PrintPreview = function(jqCanvas) {
var canvas = jqCanvas[0];
// === basic wheel reinvention stuff ===
// function $(id) { return document.getElementById(id) }
// comparison function using a key, to pass to .sort()
function keycomp(key) {
return function(a, b) {
var ka = key(a)
var kb = key(b)
if (ka < kb) return -1
if (ka > kb) return 1
return 0
}
}
// return a list transformed by a function
function map(f, list) {
var rv = []
for (var ii = 0; ii < list.length; ii++) rv.push(f(list[ii]))
return rv
}
// === 3d transforms ===
// We represent transforms as a 3x4 list of lists (ahem, array of arrays):
// [[x_from_x, x_from_y, x_from_z, x_off],
// [y_from_x, y_from_y, y_from_z, y_off],
// [z_from_x, z_from_y, z_from_z, z_off]]
// And we only actually multiply points through them in xform.
function translate(x, y, z) {
return [[1, 0, 0, x], [0, 1, 0, y], [0, 0, 1, z]]
}
function identity() { return translate(0, 0, 0) }
// rotation around the Z-axis
function rotate(theta) {
var s = Math.sin(theta)
var c = Math.cos(theta)
return [[c, -s, 0, 0], [s, c, 0, 0], [0, 0, 1, 0]]
}
// exchange two of the X, Y, Z axes --- useful for making rotate() go around
// another axis :)
function transpose_axes(a, b) {
var rv = identity()
var tmp = rv[a]
rv[a] = rv[b]
rv[b] = tmp
return rv
}
// you'd think we'd have a scale() function too, but I haven't needed it yet.
// concatenate two transforms --- the magic that makes it all possible
function concat(x1, x2) {
var rv = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
for (var ii = 0; ii < 3; ii++) {
rv[ii][3] = x2[ii][3]
for (var jj = 0; jj < 3; jj++) {
rv[ii][3] += x1[jj][3] * x2[ii][jj]
for (var kk = 0; kk < 3; kk++) {
rv[ii][jj] += x1[kk][jj] * x2[ii][kk]
}
}
}
return rv
}
// concatenate N transforms. I'd insert a special case for 0 transforms,
// but amusingly this function isn't all that performance-critical.
function concat_n(xforms) {
var rv = identity()
for (var ii = 0; ii < xforms.length; ii++) rv = concat(rv, xforms[ii])
return rv
}
// transform a point.
function xform(xform, p) {
var result_vec = []
for (var ii = 0; ii < 3; ii++) {
var rv = xform[ii][3]
for (var jj = 0; jj < 3; jj++) rv += xform[ii][jj] * p[jj]
result_vec.push(rv)
}
return result_vec
}
// transform multiple points.
function xform_points(xf, points) {
var xp = []
for (var ii = 0; ii < points.length; ii++) {
xp.push(xform(xf, points[ii]))
}
return xp
}
// perspective-transform a point --- into 2d.
function persp(p) { return [p[0] / p[2], p[1] / p[2]] }
// perspective-transform multiple points
function persp_points(points) {
return map(persp, points)
}
// return the normal of a triangle defined by three points.
function normal(p1, p2, p3) {
var v1 = [p1[0]-p2[0], p1[1]-p2[1], p1[2]-p2[2]]
var v2 = [p2[0]-p3[0], p2[1]-p3[1], p2[2]-p3[2]]
var n = [v1[1]*v2[2]-v1[2]*v2[1],
v1[2]*v2[0]-v1[0]*v2[2],
v1[0]*v2[1]-v1[1]*v2[0]]
var mag = Math.sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2])
return [n[0]/mag, n[1]/mag, n[2]/mag]
}
// === 3d shapes ===
// We represent these as an array of three arrays
// [points, lines, polies] where each line is two indices into the points array
// and each poly is three indices into the points array
function dup(array) {
var newarray = new Array(array.length)
for (var ii = 0; ii < array.length; ii++) newarray[ii] = array[ii]
return newarray
}
// transform a shape, returning a new shape
function xform_shape(xf, shape) {
// de-alias new lines and polies
return [xform_points(xf, shape[0]), dup(shape[1]), dup(shape[2])]
}
// add a new shape onto an old shape, mutating the old one
function augment(shape1, shape2) {
var s1p = shape1[0]
var off = s1p.length
for (var ii = 0; ii < shape2[0].length; ii++) s1p.push(shape2[0][ii])
var s2ll = shape2[1].length // in case of aliasing
for (var ii = 0; ii < s2ll; ii++)
shape1[1].push([shape2[1][ii][0] + off, shape2[1][ii][1] + off])
var s2pl = shape2[2].length
for (var ii = 0; ii < s2pl; ii++) {
var tri = shape2[2][ii]
shape1[2].push([tri[0]+off, tri[1]+off, tri[2]+off])
}
}
// given a shape, make a more complicated shape by copying it through transform
// xf n times, and connecting the corresponding points. This is more powerful
// than the usual kind of extrusion, and can be used to create fairly
// interesting shapes --- a snail shell from a circle, for instance.
function extrude_shape(xf, shape, n) {
if (n == null) n = 1
var new_part = shape
var old_line_base = 0 // where the lines to attach the triangles start
for (var ii = 0; ii < n; ii++) {
var new_part = xform_shape(xf, new_part)
var shape_length = shape[0].length
var new_line_base = shape[1].length // for triangles later
augment(shape, new_part)
var new_part_length = new_part[0].length
// connect corresponding points
for (var jj = 0; jj < new_part_length; jj++) {
shape[1].push([shape_length + jj - new_part_length, shape_length + jj])
}
// make triangles
var nlines = new_part[1].length
// var old_line_base = new_line_base - nlines
for (var jj = 0; jj < nlines; jj++) {
var old_line = shape[1][old_line_base + jj]
var new_line = shape[1][new_line_base + jj]
shape[2].push([old_line[0], old_line[1], new_line[0]])
shape[2].push([new_line[1], new_line[0], old_line[1]])
}
old_line_base = new_line_base
}
}
// a shape consisting of a single point
function point_shape(x, y, z) { return [[[x, y, z]], [], []] }
// approximate a circle in the x-y plane around the origin; radius r and n points
function circle(r, n) {
var shape = point_shape(r, 0, 0)
extrude_shape(rotate(Math.atan(1)*8/n), shape, n)
return shape
}
// approximate a torus with major radius r2 and minor radius r1,
// with correspondingly n2 and n1 points around each axis
function make_torus(r1, r2, n1, n2) {
var c = xform_shape(translate(r2, 0, 0), circle(r1, n1))
extrude_shape(concat_n([transpose_axes(1, 2),
rotate(Math.atan(1)*8/n2),
transpose_axes(1, 2)]),
c, n2)
return c
}
// === drawing code ===
// draw a 3d shape on a canvas
// 95% of the run time is in this function and its kids
function draw_shape(canvas, xf, shape, alpha) {
var ctx = canvas.getContext('2d')
var w = canvas.width
var h = canvas.height
// set up coordinate system so canvas is (-1, -1) to (1, 1)
ctx.save()
ctx.translate(w/2, h/2)
ctx.scale(w/2, h/2)
// 1/3 of the time is in these two lines (when not doing polies)
var points3d = xform_points(xf, shape[0])
var points = persp_points(points3d)
var lines = shape[1]
// 2/3 of the time is in this loop (when we're not doing polies)
if (alpha == null) {
ctx.strokeStyle = 'grey'
ctx.lineWidth = 1/(w/2)
ctx.beginPath()
var p1, p2
for (var ii = 0; ii < lines.length; ii++) {
p1 = points[lines[ii][0]]
p2 = points[lines[ii][1]]
ctx.moveTo(p1[0], p1[1])
ctx.lineTo(p2[0], p2[1])
}
ctx.stroke()
}
// when we're doing polies, 90% of our time is spent doing polies
if (alpha != null) {
// Sort polygons by depth so we draw the farthest-away stuff first
// ("painter's algorithm")
var minusdepth = function(p) {
return [-(points3d[p[0]][2] + points3d[p[1]][2] + points3d[p[2]][2]), p]
}
var polies = map(minusdepth, shape[2])
polies.sort(keycomp(function(p) { return p[0] }))
// draw all the polygons
var tri, p1, p2, p3, n, bright
for (var ii = 0; ii < polies.length; ii++) {
tri = polies[ii][1]
if (alpha == '1') {
// light surface
n = normal(points3d[tri[0]], points3d[tri[1]], points3d[tri[2]])
// I'm not sure how to make backface removal work with perspective:
// if (n[2] > 0 && alpha == '1') continue // backface removal
// lighting from (1, -1, -1) direction
bright = parseInt(((n[0]-n[1]-n[2]) / Math.sqrt(3) * 255))
if (bright < 20) bright = 20
} else {
// lighting doesn't make sense if the object is transparent,
// so we color by depth to have some variation in color...
var maxd = polies[polies.length-1][0]
var mind = polies[0][0]
var d = polies[ii][0]
bright = parseInt((d-mind)/(maxd-mind) * 255)
}
ctx.fillStyle = 'rgba(' + bright + ',' + bright + ',' + bright + ',' + alpha + ')';
ctx.beginPath()
p1 = points[tri[0]]
p2 = points[tri[1]]
p3 = points[tri[2]]
ctx.moveTo(p1[0], p1[1])
ctx.lineTo(p2[0], p2[1])
ctx.lineTo(p3[0], p3[1])
// ctx.closePath() seems to be unnecessary
ctx.fill()
}
}
ctx.restore()
}
// clear a canvas
function cls(canvas) {
var ctx = canvas.getContext('2d')
ctx.fillStyle = 'black'
ctx.fillRect(0, 0, canvas.width, canvas.height)
}
// // === drawing of particular shapes. also DOM. ===
// angle = 0
// function unit_cube() {
// var shape = point_shape(0, 0, 0)
// extrude_shape(translate(0,0,1), shape)
// extrude_shape(translate(0,1,0), shape)
// extrude_shape(translate(1,0,0), shape)
// return shape
// }
// // this was where I tested stuff as I wrote this
// function make_some_junk() {
// // make a unit cube centered on the origin
// var shape = xform_shape(translate(-0.5, -0.5, -0.5), unit_cube())
// // add some circles
// augment(shape, circle(0.707, 16))
// augment(shape, xform_shape(transpose_axes(0, 2), circle(0.707, 16)))
// augment(shape, xform_shape(transpose_axes(1, 2), circle(0.707, 16)))
// augment(shape, circle(1, 15))
// // add a disc
// var big_disc = circle(2, 20)
// extrude_shape(translate(0, 0, 0.5), big_disc, 2)
// augment(shape, big_disc)
// return shape
// }
// var some_junk = make_some_junk()
// function draw_some_junk(canvas) {
// var xf = concat_n([transpose_axes(1, 2),
// rotate(angle),
// transpose_axes(1, 2),
// rotate(angle*1.618),
// translate(0, 0, 2.5)])
// draw_shape(canvas, xf, some_junk)
// }
var torus = make_torus(1, 3, 12, 12)
console.log('torus',torus);
function draw() {
// var start = new Date()
// var alpha = null
// if ($('fill').checked) {
// alpha = ($('translucent').checked ? '0.5' : 1)
// }
// if ($('trails').checked) {
// $('canvas').getContext('2d').globalAlpha = 0.33
// } else {
// $('canvas').getContext('2d').globalAlpha = 1
// }
var angle = 0;
var alpha = 1;
draw_shape(canvas,
concat_n([
rotate(0),
transpose_axes(1, 2),
rotate(0), // to reduce periodicity
transpose_axes(1, 2),
translate(0, 0, 6),
// transpose_axes(1, 2),
// rotate(1),
]),
torus, alpha);
// var end = new Date()
// var ms = $('ms')
// if (ms) {
// var msvalue = ms.value + ' ' + (end.getTime() - start.getTime())
// if (msvalue.length > 25) msvalue = msvalue.substr(msvalue.length - 25)
// ms.value = msvalue
// }
}
// function update() {
// if (!$('go').checked) return
// angle += 3.14159 / 30
// cls($('canvas'))
// draw_torus($('canvas'))
// }
// function init(ev) {
// setInterval(update, 100)
// // this doesn't work: $('fill').addEventListener('change', update, true)
// // how do you do what I want to do there?
// cls($('canvas'))
// draw_torus($('canvas'))
// }
// window.addEventListener('load', init, true)
return {
draw: draw,
}
}

View File

@ -1,176 +1,14 @@
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);
var items = [];
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>');
var item = new ViewerItem(doodles[i]);
items.push(item);
var svg = item.getSvg();
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);
}
}

View File

@ -0,0 +1,136 @@
var ViewerItem = function(doodle) {
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" d="'+svgData+'"></path></svg>');
var viewbox = box.getX() + " " + box.getY() + " " + box.getWidth() + " " + box.getHeight();
var xDown = 0, yDown = 0;
var xCur = 0, yCur = 0;
var dragging = false;
var prevDist = 0;
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);
updateView();
function updateView() {
var box = path.getBoundingBox();
var scaledCenterX = box.getCenter().x * (1-doodle.getScale());
var scaledCenterY = box.getCenter().y * (1-doodle.getScale());
svg[0].setAttribute("stroke-width", 1/doodle.getScale());
svg.css({
transform: "scale(" + doodle.getScale() + ")",
left: doodle.getOffset().x - scaledCenterX + xCur - xDown,
top: doodle.getOffset().y - scaledCenterY + yCur - yDown
});
}
function getDoodle() {
return doodle;
}
function getSvg() {
return svg;
}
function startDrag(x,y) {
if (!dragging) {
dragging = true;
xDown = x;
yDown = y;
updateDrag(x,y);
}
}
function updateDrag(x,y) {
xCur = x;
yCur = y;
updateView();
}
function stopDrag() {
if (dragging) {
dragging = false;
doodle.getOffset().x += xCur - xDown;
doodle.getOffset().y += yCur - yDown;
xCur = 0;
yCur = 0;
xDown = 0;
yDown = 0;
}
}
function distance(x1,y1,x2,y2) {
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
function zoomBy(f) {
var newScale = doodle.getScale()+f;
var box = path.getBoundingBox();
var anchorpoint = box.getCenter();
if (newScale*box.getWidth()<100) return;
if (newScale*box.getHeight()<100) return;
doodle.setScale(newScale);
doodle.getOffset().x -= f*anchorpoint.x;
doodle.getOffset().y -= f*anchorpoint.y;
updateView();
}
svg.on("mousedown", function (e) {
startDrag(e.originalEvent.pageX,e.originalEvent.pageY);
});
$(document).on("mousemove", function (e) {
if (dragging) {
updateDrag(e.originalEvent.pageX,e.originalEvent.pageY);
}
});
svg.on("mouseup", function (e) {
stopDrag();
});
$(document).on("mouseup", function (e) {
stopDrag();
});
svg.on("touchstart", function (e) {
var event = e.originalEvent;
event.preventDefault();
var touch = event.touches[0];
startDrag(touch.pageX,touch.pageY); //drag
if (event.touches.length === 2) { //zoom
var touch2 = event.touches[1];
prevDist = distance(touch.pageX,touch.pageY,touch2.pageX,touch2.pageY);
}
});
svg.on("touchmove", function (e) {
var event = e.originalEvent;
event.preventDefault();
if (dragging) {
var touch = event.touches[0];
updateDrag(touch.pageX,touch.pageY);
if (event.touches.length === 2) {
var touch2 = event.touches[1];
var dist = distance(touch.pageX,touch.pageY,touch2.pageX,touch2.pageY);
var scaler = (dist-prevDist) / 100; //100 is an arbitrary scaler
zoomBy(scaler);
prevDist = dist;
}
}
});
svg.on("touchend", function (e) {
var event = e.originalEvent;
stopDrag();
});
return {
getDoodle: getDoodle,
getSvg: getSvg,
}
}

File diff suppressed because one or more lines are too long