Skip to content

Commit

Permalink
visucam: added drag knives support (operation-> simple engraving)
Browse files Browse the repository at this point in the history
  • Loading branch information
nraynaud committed Jan 13, 2016
1 parent 20830ab commit 10d4cef
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 13 deletions.
34 changes: 34 additions & 0 deletions webapp/cnc/cam/cam.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,40 @@ define(['cnc/maths/bezier', 'clipper', 'cnc/cam/toolpath', 'libs/simplify', 'cnc
*/
contourAreaPositive: function (inside, climbMilling) {
return (!!climbMilling) ^ (!inside);
},

addCornerActions: function (clipperPolyline, clipperRadius, toleranceAngleRadians) {
if (clipperRadius == 0 || clipperPolyline.length == 0)
return clipperPolyline;
var result = [];
result.push(clipperPolyline[0]);
//previous point is not always at i-1, because repeated points in the polygon are skipped
var previousPoint = clipperPolyline[0];
for (var i = 1; i < clipperPolyline.length - 1; i++) {
previousPoint = clipperPolyline[i - 1];
var point = clipperPolyline[i];
if (previousPoint.sqDistance(point) == 0)
// you don't want to play with atan2() if a point is repeated
continue;
var incomingVector = point.sub(previousPoint);
var nextPoint = clipperPolyline[i + 1];
var angle = point.angle(previousPoint, nextPoint);
var overshoot = point.add(incomingVector.normalized().scale(clipperRadius));
result.push(overshoot);
if (Math.abs(angle) > toleranceAngleRadians) {
var arcPoints = 100 / (2 * Math.PI) * Math.abs(angle);
var incomingAngle = incomingVector.atan2();
for (var j = 0; j <= arcPoints; j++) {
var a = incomingAngle + angle / arcPoints * j;
var pt = point.add(util.polarPoint(clipperRadius, a));
result.push(pt);
}
}
previousPoint = point;
}
if (clipperPolyline.length > 1)
result.push(clipperPolyline[clipperPolyline.length - 1]);
return result;
}
};

Expand Down
14 changes: 12 additions & 2 deletions webapp/cnc/cam/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ define(['RSVP', 'cnc/cam/cam', 'cnc/cam/toolpath', 'cnc/cam/pocket', 'cnc/util',
indices = [];
positions = [];
}

for (var i = 0; i < polygons.length; i++) {
if (currentOffset > 32000)
flushResult();
Expand Down Expand Up @@ -112,16 +113,25 @@ define(['RSVP', 'cnc/cam/cam', 'cnc/cam/toolpath', 'cnc/cam/pocket', 'cnc/util',
label: 'Simple Engraving',
specialTemplate: 'operationSimpleEngraving',
properties: {
bottom_Z: attr('number', {defaultValue: -5})
bottom_Z: attr('number', {defaultValue: -5}),
dragknife_corner_action: attr('boolean', {defaultValue: false}),
dragknife_swivel_radius: attr('number', {defaultValue: 0.25}),
dragknife_min_angle: attr('number', {defaultValue: 20})
},
computeToolpath: function (op, missedAreaCallback, leaveStockCallback) {
noExtraPolys(missedAreaCallback, leaveStockCallback);
return new RSVP.Promise(function (resolve, reject) {
var z = op.bottom_Z;
var safetyZ = op.job.safetyZ;
var polygons = op.outline.clipperPolyline;
var toolpath = [];
var machine = new cam.Machine(null);
var polygons = op.outline.clipperPolyline;
if (op.dragknife_corner_action)
polygons = polygons.map(function (poly) {
return machine.addCornerActions(poly,
machine.clipperScale * op.dragknife_swivel_radius,
op.dragknife_min_angle / 180 * Math.PI)
});
for (var i = 0; i < polygons.length; i++)
if (polygons[i].length) {
var path = new tp.GeneralPolylineToolpath();
Expand Down
32 changes: 26 additions & 6 deletions webapp/cnc/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,35 @@ define(function () {
return new Point(Math.round(this.x), Math.round(this.y), Math.round(this.z));
},
sqDistance: function (p) {
if (p == null)
p = new Point(0, 0, 0);
var dx = this.x - p.x;
var dy = this.y - p.y;
var dz = this.z - p.z;
return dx * dx + dy * dy + dz * dz;
var d = p == null ? this : this.sub(p);
return d.x * d.x + d.y * d.y + d.z * d.z;
},
distance: function (p) {
return Math.sqrt(this.sqDistance(p));
},
lerp: function (p, alpha) {
return this.add(p.sub(this).scale(alpha));
},
normalized: function () {
return this.scale(1 / this.distance());
},
atan2: function () {
return Math.atan2(this.y, this.x);
},
angle: function (fromPoint, toPoint) {
//stolen from http://stackoverflow.com/questions/1211212/how-to-calculate-an-angle-from-three-points#comment47211790_1211212

var v1 = this.sub(fromPoint);
var v2 = toPoint.sub(this);
var dot = v1.x * v2.x + v1.y * v2.y;
var cross = v1.x * v2.y - v1.y * v2.x;
var res = Math.atan2(cross, dot);
var twoPi = 2 * Math.PI;
if (res < -twoPi)
return res + twoPi;
if (res > twoPi)
return res - twoPi;
return res;
}
};
[
Expand Down Expand Up @@ -194,6 +211,9 @@ define(function () {

return {
Point: Point,
polarPoint: function (r, theta) {
return new Point(r * Math.cos(theta), r * Math.sin(theta));
},
toggleClass: toggleClass,
//variadic, just pass x,y,z ...
length: function () {
Expand Down
61 changes: 57 additions & 4 deletions webapp/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,14 +1011,67 @@ function program1(depth0,data) {
Ember.TEMPLATES["operationSimpleEngraving"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
var buffer = '', helper, options, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;

var buffer = '', stack1, helper, options, helperMissing = helpers.helperMissing, escapeExpression = this.escapeExpression, self = this;

function program1(depth0, data) {

var buffer = '', helper, options;
data.buffer.push("\n <tr>\n <th title=\"Distance between swivel axis and blade tip, it's often 0.25mm for Roland blades\">Blade Offset:</th>\n <td class=\"input-group input-group-sm\">");
data.buffer.push(escapeExpression((helper = helpers['number-input'] || (depth0 && depth0['number-input']), options = {
hash: {
'numericValue': ("dragknife_swivel_radius")
},
hashTypes: {'numericValue': "ID"},
hashContexts: {'numericValue': depth0},
contexts: [],
types: [],
data: data
}, helper ? helper.call(depth0, options) : helperMissing.call(depth0, "number-input", options))));
data.buffer.push(" <span\n class=\"input-group-addon\">mm</span></td>\n </tr>\n <tr>\n <th title=\"Angles smaller than that will just drag the blade directly\">Tolerance Angle:</th>\n <td class=\"input-group input-group-sm\">");
data.buffer.push(escapeExpression((helper = helpers['number-input'] || (depth0 && depth0['number-input']), options = {
hash: {
'numericValue': ("dragknife_min_angle")
},
hashTypes: {'numericValue': "ID"},
hashContexts: {'numericValue': depth0},
contexts: [],
types: [],
data: data
}, helper ? helper.call(depth0, options) : helperMissing.call(depth0, "number-input", options))));
data.buffer.push(" <span\n class=\"input-group-addon\">°</span></td>\n </tr>\n");
return buffer;
}

data.buffer.push("<tr>\n <th>engraving Z:</th>\n <td class=\"input-group input-group-sm\">");
data.buffer.push("<tr>\n <th>Engraving Z:</th>\n <td class=\"input-group input-group-sm\">");
data.buffer.push(escapeExpression((helper = helpers['number-input'] || (depth0 && depth0['number-input']),options={hash:{
'numericValue': ("bottom_Z")
},hashTypes:{'numericValue': "ID"},hashContexts:{'numericValue': depth0},contexts:[],types:[],data:data},helper ? helper.call(depth0, options) : helperMissing.call(depth0, "number-input", options))));
data.buffer.push(" <span\n class=\"input-group-addon\">mm</span></td>\n</tr>\n");
data.buffer.push(" <span\n class=\"input-group-addon\">mm</span></td>\n</tr>\n<tr>\n <th>Swivel Drag Knife:</th>\n <td class=\"input-group input-group-sm\">");
data.buffer.push(escapeExpression((helper = helpers.input || (depth0 && depth0.input), options = {
hash: {
'type': ("checkbox"),
'checked': ("dragknife_corner_action")
},
hashTypes: {'type': "STRING", 'checked': "ID"},
hashContexts: {'type': depth0, 'checked': depth0},
contexts: [],
types: [],
data: data
}, helper ? helper.call(depth0, options) : helperMissing.call(depth0, "input", options))));
data.buffer.push("</td>\n</tr>\n");
stack1 = helpers['if'].call(depth0, "dragknife_corner_action", {
hash: {},
hashTypes: {},
hashContexts: {},
inverse: self.noop,
fn: self.program(1, program1, data),
contexts: [depth0],
types: ["ID"],
data: data
});
if (stack1 || stack1 === 0) {
data.buffer.push(stack1);
}
return buffer;

});
Expand Down
18 changes: 17 additions & 1 deletion webapp/templates/operationSimpleEngraving.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
<tr>
<th>engraving Z:</th>
<th>Engraving Z:</th>
<td class="input-group input-group-sm">{{number-input numericValue=bottom_Z}} <span
class="input-group-addon">mm</span></td>
</tr>
<tr>
<th>Swivel Drag Knife:</th>
<td class="input-group input-group-sm">{{input type="checkbox" checked=dragknife_corner_action}}</td>
</tr>
{{#if dragknife_corner_action}}
<tr>
<th title="Distance between swivel axis and blade tip, it's often 0.25mm for Roland blades">Blade Offset:</th>
<td class="input-group input-group-sm">{{number-input numericValue=dragknife_swivel_radius}} <span
class="input-group-addon">mm</span></td>
</tr>
<tr>
<th title="Angles smaller than that will just drag the blade directly">Tolerance Angle:</th>
<td class="input-group input-group-sm">{{number-input numericValue=dragknife_min_angle}} <span
class="input-group-addon">°</span></td>
</tr>
{{/if}}

0 comments on commit 10d4cef

Please sign in to comment.