improve thin wall detection
This commit is contained in:
parent
8dae3e7617
commit
8a4e5a053f
7 changed files with 51 additions and 40 deletions
|
|
@ -447,7 +447,6 @@ var gs_base_polygons = exports;
|
|||
* @param {Polygon[]} polys
|
||||
* @param {number} dist1 first offset distance
|
||||
* @param {number} dist2 2nd thru last offset distance
|
||||
* @param {number} over additional offset over then under
|
||||
* @param {Polygon[]} out optional collector
|
||||
* @param {number} count offset passes (0 == until no space left)
|
||||
* @param {Function} collector receives output of each pass
|
||||
|
|
@ -455,7 +454,7 @@ var gs_base_polygons = exports;
|
|||
* @param {number} [z] defaults to 0
|
||||
* @returns {Polygon[]} last offset
|
||||
*/
|
||||
function expand2(polys, dist1, dist2, over, out, count, collector, thins, z) {
|
||||
function expand2(polys, dist1, dist2, out, count, collector, thins, z) {
|
||||
// prepare alignments for clipper lib
|
||||
alignWindings(polys);
|
||||
polys.forEach(function(poly) {
|
||||
|
|
@ -470,7 +469,8 @@ var gs_base_polygons = exports;
|
|||
cety = clib.EndType,
|
||||
coff = new clib.ClipperOffset(),
|
||||
ctre = new clib.PolyTree(),
|
||||
orig = polys;
|
||||
orig = polys,
|
||||
over = dist1 * 0.45;
|
||||
|
||||
// inset
|
||||
polys.forEach(function(poly) {
|
||||
|
|
@ -489,7 +489,7 @@ var gs_base_polygons = exports;
|
|||
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
||||
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
||||
});
|
||||
coff.Execute(ctre, (-over) * fact);
|
||||
coff.Execute(ctre, -over * fact);
|
||||
polys = fromClipperTree(ctre, z);
|
||||
|
||||
// detect possible thin walls
|
||||
|
|
@ -499,7 +499,7 @@ var gs_base_polygons = exports;
|
|||
diff = Math.abs(1 - (circ1 / circ2));
|
||||
|
||||
if (diff > 0.2) {
|
||||
thins(orig, polys, diff);
|
||||
thins(orig, out.length ? polys : null, diff, -over);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ var gs_base_polygons = exports;
|
|||
if (out) out.appendAll(polys);
|
||||
if (collector) collector(polys, count);
|
||||
if ((count === 0 || count > 1) && polys.length > 0) {
|
||||
expand2(polys, dist2 || dist1, dist2, over, out, count > 0 ? count-1 : 0, collector, thins, z);
|
||||
expand2(polys, dist2 || dist1, dist2, out, count > 0 ? count-1 : 0, collector, thins, z);
|
||||
}
|
||||
|
||||
return polys;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ var gs_kiri_codec = exports;
|
|||
poly: encode(this.poly, state),
|
||||
traces: encode(this.traces, state),
|
||||
inner: encode(this.inner, state),
|
||||
// thinner: encode(this.thinner, state),
|
||||
solids: encode(this.solids, state),
|
||||
fill_lines: encodePointArray(this.fill_lines),
|
||||
fill_sparse: encode(this.fill_sparse, state)
|
||||
|
|
@ -131,6 +132,7 @@ var gs_kiri_codec = exports;
|
|||
|
||||
top.traces = decode(v.traces, state);
|
||||
top.inner = decode(v.inner, state);
|
||||
// top.thinner = decode(v.thinner, state);
|
||||
top.solids = decode(v.solids, state);
|
||||
top.fill_lines = decodePointArray(v.fill_lines,state);
|
||||
top.fill_sparse = decode(v.fill_sparse, state);
|
||||
|
|
|
|||
|
|
@ -216,19 +216,27 @@ var gs_kiri_fdm = exports;
|
|||
polys = [],
|
||||
preout = [];
|
||||
|
||||
// compute first brim
|
||||
widgets.forEach(function(widget) {
|
||||
var tops = [];
|
||||
// collect top outer polygons
|
||||
widget.slices[0].tops.forEach(function(top) {
|
||||
tops.push(top.poly.clone());
|
||||
});
|
||||
// nest and offset tops
|
||||
POLY.nest(tops).forEach(function(poly) {
|
||||
poly.offset(-process.outputBrimOffset+device.nozzleSize/2).forEach(function(brim) {
|
||||
poly.offset(-process.outputBrimOffset + device.nozzleSize/2).forEach(function(brim) {
|
||||
brim.move(widget.mesh.position);
|
||||
brims.push(brim);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// if brim is offset, the expand and shrink to cause brims to merge
|
||||
if (process.outputBrimOffset && brims.length) {
|
||||
|
||||
}
|
||||
|
||||
POLY.union(brims).forEach(function(brim) {
|
||||
POLY.trace2count(brim, polys, -device.nozzleSize, process.outputBrimCount, 0);
|
||||
});
|
||||
|
|
@ -329,7 +337,7 @@ var gs_kiri_fdm = exports;
|
|||
seekMMM = process.outputSeekrate * 60,
|
||||
retDist = process.outputRetractDist,
|
||||
retSpeed = process.outputRetractSpeed * 60,
|
||||
retDwell = Math.round((process.outputRetractDwell || 0) * 1000),
|
||||
retDwell = process.outputRetractDwell || 0,
|
||||
// ratio of nozzle area to filament area times
|
||||
// ratio of slice height to filament max noodle height
|
||||
emitPerMM = print.extrudePerMM(device.nozzleSize, device.filamentSize, process.sliceHeight),
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ var gs_kiri_print = exports;
|
|||
// if dist to new segment is less than thinWall
|
||||
// and segment length is less than thinWall then
|
||||
// just extrude to midpoint of next segment. this is
|
||||
// to avoid shaking printer to death.
|
||||
// to avoid shaking the printer to death.
|
||||
if (find.d <= thinWall && len <= thinWall) {
|
||||
p2 = p1.midPointTo(p2);
|
||||
addOutput(preout, p2, fillMult * (find.d / thinWall), printSpeed);
|
||||
|
|
@ -646,7 +646,7 @@ var gs_kiri_print = exports;
|
|||
checkBisect(startPoint, p1, bounds);
|
||||
}
|
||||
|
||||
// bridge ends of fill if they're close together
|
||||
// bridge ends of fill when they're close together
|
||||
if (dist < thinWall) {
|
||||
addOutput(preout, p1, fillMult, printSpeed);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ var gs_kiri_slice = exports;
|
|||
tops.forEach(function(top) {
|
||||
layer.poly(top.poly, colors[0], true, open);
|
||||
if (top.inner) layer.poly(top.inner, 0x999999, true, null);
|
||||
// if (top.thinner) layer.poly(top.thinner, 0x559999, true, null);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -357,18 +358,13 @@ var gs_kiri_slice = exports;
|
|||
*/
|
||||
function cullIntersections(r1, r2) {
|
||||
if (!(r1 && r2 && r1.length && r2.length)) return;
|
||||
if (r2.length > r1.length) {
|
||||
var r3 = r1;
|
||||
r1 = r2;
|
||||
r2 = r3;
|
||||
}
|
||||
var valid = r1.slice();
|
||||
outer: for (var i=0; i<r2.length; i += 2) {
|
||||
for (var j=0; j<r1.length; j += 2) {
|
||||
if (UTIL.intersect(r1[j], r1[j+1], r2[i], r2[i+1])) continue outer;
|
||||
var valid = r2.slice();
|
||||
outer: for (var i=0; i<r1.length; i += 2) {
|
||||
for (var j=0; j<r2.length; j += 2) {
|
||||
if (UTIL.intersect(r1[i], r1[i+1], r2[j], r2[j+1], BASE.key.SEGINT)) continue outer;
|
||||
}
|
||||
valid.push(r2[i]);
|
||||
valid.push(r2[i+1]);
|
||||
valid.push(r1[i]);
|
||||
valid.push(r1[i+1]);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
|
@ -392,6 +388,7 @@ var gs_kiri_slice = exports;
|
|||
|
||||
slice.tops.forEach(function(top) {
|
||||
if (opt.vase) top.poly = top.poly.clone(false);
|
||||
// top.thinner = [];
|
||||
top.traces = [];
|
||||
top.inner = [];
|
||||
var last = [],
|
||||
|
|
@ -412,7 +409,6 @@ var gs_kiri_slice = exports;
|
|||
[top.poly],
|
||||
-offset1,
|
||||
-offsetN,
|
||||
-offset1,
|
||||
top.traces,
|
||||
count,
|
||||
// on each new offset trace ...
|
||||
|
|
@ -428,12 +424,17 @@ var gs_kiri_slice = exports;
|
|||
});
|
||||
},
|
||||
// thin wall probe
|
||||
function(p1, p2) {
|
||||
var pall = POLY.nest([].appendAll(p1).appendAll(p2).clone(true)),
|
||||
pnew = POLY.expand(pall, -offset1, z, null, 1),
|
||||
r1 = fillArea(pnew, 45, offsetN, [], 0, offsetN * 2),
|
||||
r2 = fillArea(pnew, 135, offsetN, [], 0, offsetN * 2),
|
||||
function(p1, p2, diff, dist) {
|
||||
var pall = POLY.nest(POLY.flatten([].appendAll(p1).appendAll(p2)).clone()),
|
||||
pnew1 = POLY.expand(pall, -dist, z, null, 1),
|
||||
r1 = fillArea(pnew1, 45, offsetN, [], 0, offset1),
|
||||
r2 = fillArea(pnew1, 135, offsetN, [], 0, offset1),
|
||||
rall = top.thin_fill.appendAll(cullIntersections(r1, r2)),
|
||||
pnew2 = POLY.expand(pnew1, -dist, z, null, 1),
|
||||
r1 = fillArea(pnew2, 45, offsetN, [], 0, offset1),
|
||||
r2 = fillArea(pnew2, 135, offsetN, [], 0, offset1),
|
||||
rall = top.thin_fill.appendAll(cullIntersections(r1, r2));
|
||||
// top.thinner.appendAll(pnew1).appendAll(pnew2);
|
||||
},
|
||||
z);
|
||||
} else {
|
||||
|
|
|
|||
22
js/kiri.js
22
js/kiri.js
|
|
@ -255,9 +255,9 @@ self.kiri.license = exports.LICENSE;
|
|||
|
||||
sliceHeight: 0.25,
|
||||
sliceShells: 2,
|
||||
sliceShellSpacing: 0.9,
|
||||
sliceShellSpacing: 1,
|
||||
sliceFillAngle: 45,
|
||||
sliceFillOverlap: 0.5,
|
||||
sliceFillOverlap: 0.3,
|
||||
sliceFillSpacing: 1.0,
|
||||
sliceFillSparse: 0.5,
|
||||
|
||||
|
|
@ -278,20 +278,20 @@ self.kiri.license = exports.LICENSE;
|
|||
firstSliceHeight: 0.25,
|
||||
firstLayerRate: 30,
|
||||
|
||||
outputTemp: 230,
|
||||
outputTemp: 220,
|
||||
outputFanMax: 255,
|
||||
outputBedTemp: 0,
|
||||
outputFeedrate: 100,
|
||||
outputFinishrate: 60,
|
||||
outputSeekrate: 150,
|
||||
outputShellMult: 1.0,
|
||||
outputFillMult: 1.25,
|
||||
outputSparseMult: 1.5,
|
||||
outputShellMult: 1.1,
|
||||
outputFillMult: 1.2,
|
||||
outputSparseMult: 1.3,
|
||||
outputRetractOver: 5.0,
|
||||
outputRetractDist: 0.5,
|
||||
outputRetractSpeed: 20,
|
||||
outputRetractDwell: 0.2,
|
||||
outputWipeSpeed: 20,
|
||||
outputRetractDwell: 50,
|
||||
outputWipeSpeed: 50,
|
||||
outputWipeDistance: 0,
|
||||
outputBrimCount: 2,
|
||||
outputBrimOffset: 3,
|
||||
|
|
@ -1011,6 +1011,7 @@ self.kiri.license = exports.LICENSE;
|
|||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState === 4) {
|
||||
var status = ajax.status;
|
||||
STATS.add('op-'+status);
|
||||
if (status >= 200 && status < 300) {
|
||||
hideModal();
|
||||
} else {
|
||||
|
|
@ -1062,6 +1063,7 @@ self.kiri.license = exports.LICENSE;
|
|||
xhtr.onreadystatechange = function() {
|
||||
if (xhtr.readyState === 4) {
|
||||
var status = xhtr.status;
|
||||
STATS.add('gp-'+status);
|
||||
if (status >= 200 && status < 300) {
|
||||
var json = js2o(xhtr.responseText);
|
||||
gridprint_tracker(host,json.key);
|
||||
|
|
@ -1435,7 +1437,7 @@ self.kiri.license = exports.LICENSE;
|
|||
function layoutPlatform(event, space) {
|
||||
var layout = (viewMode === VIEWS.ARRANGE),
|
||||
modified = false,
|
||||
gap = space || 1,
|
||||
gap = space || (1 + settings.process.sliceSupportExtra),
|
||||
topZ = MODE === MODES.CAM ? camTopZ : 0;
|
||||
|
||||
setViewMode(VIEWS.ARRANGE);
|
||||
|
|
@ -2402,7 +2404,7 @@ self.kiri.license = exports.LICENSE;
|
|||
// outputRetractOver: UC.newInput("retract over", {title:"move threshold that\ntriggers retraction\n0 to disable", convert:UC.toFloat, modes:FDM}),
|
||||
outputRetractDist: UC.newInput("retract dist", {title:"amount to retract filament", convert:UC.toFloat, modes:FDM}),
|
||||
outputRetractSpeed: UC.newInput("retract rate", {title:"speed of filament\nretraction in mm/s", convert:UC.toInt, modes:FDM}),
|
||||
outputRetractDwell: UC.newInput("retract dwell", {title:"time between re-engaging\nfilament and movement\nin seconds", convert:UC.toFloat, modes:FDM}),
|
||||
outputRetractDwell: UC.newInput("retract dwell", {title:"time between re-engaging\nfilament and movement\nin milliseconds", convert:UC.toInt, modes:FDM}),
|
||||
outputWipeSpeed: UC.newInput("wipe speed", {title:"speed while wiping\nnozzle in mm/s", convert:UC.toInt, modes:FDM}),
|
||||
outputWipeDistance: UC.newInput("wipe distance", {title:"distance to wipe nozzle after\neach enclosed island completes\nin millimeters. 0 to disable", convert:UC.toInt, modes:FDM}),
|
||||
outputShortPoly: UC.newInput("short outline", {title:"poly perimeter length\ntriggers short slowdown\nin millimeters", bound:UC.bound(0,200), convert:UC.toFloat, modes:FDM}),
|
||||
|
|
|
|||
4
notes.md
4
notes.md
|
|
@ -59,10 +59,8 @@
|
|||
|
||||
# FDM todo
|
||||
|
||||
* fix thin wall support fill artifacts with complex nested polys
|
||||
* post re-engage dwell (on first layer?)
|
||||
* add support expand value to multi-part spacing (which defaults to 1mm)
|
||||
* add lay-flat auto-rotation or from selected face
|
||||
* determine start point from gcode preamble
|
||||
* add rafts, manual supports
|
||||
* check for support / brim intersections on first layer
|
||||
* solid fill every other line, two passes. minimize heat/sag. better fill between
|
||||
|
|
|
|||
Loading…
Reference in a new issue