fixes #12. add start of thin wall detection

This commit is contained in:
Stewart Allen 2017-12-31 11:27:21 -05:00
commit 9fff3c50b5
6 changed files with 116 additions and 18 deletions

View file

@ -28,6 +28,7 @@ var gs_base_polygons = exports;
subtract : subtract,
flatten : flatten,
trimTo : trimTo,
expand2 : expand2,
expand : expand,
union : union,
nest : nest,
@ -429,6 +430,67 @@ var gs_base_polygons = exports;
return polys;
}
/**
* by "over" expanding then contracting, this causes shells that are too
* close together to merge and cancel out. it's a more expensive operation
* but prevents shells that are too close together to extrude properly.
*
* @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
* @param {number} [z] defaults to 0
* @returns {Polygon[]} last offset
*/
function expand2(polys, dist1, dist2, over, out, count, collector, z) {
// prepare alignments for clipper lib
alignWindings(polys);
polys.forEach(function(poly) {
if (poly.inner) setWinding(poly.inner, !poly.isClockwise());
});
var fact = CONF.clipper,
clib = self.ClipperLib,
clip = clib.Clipper,
cpft = clib.PolyFillType,
cjnt = clib.JoinType,
cety = clib.EndType,
coff = new clib.ClipperOffset(),
ctre = new clib.PolyTree();
// inset
polys.forEach(function(poly) {
var clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
});
coff.Execute(ctre, (dist1 + over) * fact);
polys = fromClipperTree(ctre, z);
// outset
coff = new clib.ClipperOffset();
ctre = new clib.PolyTree();
polys.forEach(function(poly) {
var clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
});
coff.Execute(ctre, (-over) * fact);
polys = fromClipperTree(ctre, z);
// process
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, z);
}
return polys;
}
/**
* @param {Polygon} poly input
* @param {Polygon[]} traces output

View file

@ -711,7 +711,7 @@ var gs_kiri_cam = exports;
shellFinish;
if (sliceDepth <= 0.05) {
return ondone(null);
return ondone("invalid slice depth");
}
// cut outside traces at the right points

View file

@ -107,7 +107,10 @@ var gs_kiri_fdm = exports;
slice.index > slices.length - spro.sliceTopLayers-1 ||
spro.sliceFillSparse > 0.95
) && !spro.sliceVase;
slice.doShells(spro.sliceShells, firstOffset, shellOffset, fillOffset, spro.sliceVase);
slice.doShells(spro.sliceShells, firstOffset, shellOffset, fillOffset, {
vase: spro.sliceVase,
thin: spro.detectThinWalls
});
if (solid) slice.doSolidLayerFill(fillSpacing, sliceFillAngle);
sliceFillAngle += 90.0;
}, "offsets");

View file

@ -30,8 +30,7 @@ var gs_kiri_laser = exports;
var proc = settings.process;
if (proc.laserSliceHeight < 0) {
DBUG.log("invalid slice height");
return ondone(false);
return ondone("invalid slice height");
}
SLICER.sliceWidget(widget, {height: proc.laserSliceHeight}, function(slices) {
@ -40,7 +39,7 @@ var gs_kiri_laser = exports;
slice.doShells(1, -proc.laserOffset);
onupdate(0.80 + (index/slices.length) * 0.20);
});
ondone(true);
ondone();
}, function(update) {
onupdate(0.0 + update * 0.80)
});

View file

@ -358,12 +358,14 @@ var gs_kiri_slice = exports;
* @param {number} offset1 first offset
* @param {number} offsetN all subsequent offsets
* @param {number} fillOffset
* @param {Obejct} options
*/
PRO.doShells = function(count, offset1, offsetN, fillOffset, vase) {
var slice = this;
PRO.doShells = function(count, offset1, offsetN, fillOffset, options) {
var slice = this,
opt = options || {};
slice.tops.forEach(function(top) {
if (vase) top.poly = top.poly.clone(false);
if (opt.vase) top.poly = top.poly.clone(false);
top.traces = [];
top.inner = [];
var last = [];
@ -374,17 +376,46 @@ var gs_kiri_slice = exports;
last = [top.poly].clone(true);
top.traces = last;
} else {
POLY.expand([top.poly], -offset1, top.poly.getZ(), top.traces, count, -offsetN, function(polys, countNow) {
last = polys;
// mark each poly with depth (offset #) starting at 0
polys.forEach(function(p) {
p.depth = count - countNow;
if (p.inner) p.inner.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - countNow);
if (opt.thin) {
POLY.expand2(
[top.poly],
-offset1,
-offsetN,
-offset1,
top.traces,
count,
function(polys, countNow) {
last = polys;
// mark each poly with depth (offset #) starting at 0
polys.forEach(function(p) {
p.depth = count - countNow;
if (p.inner) p.inner.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - countNow);
});
});
},
top.poly.getZ());
} else {
POLY.expand(
[top.poly],
-offset1,
top.poly.getZ(),
top.traces,
count,
-offsetN,
function(polys, countNow) {
last = polys;
// mark each poly with depth (offset #) starting at 0
polys.forEach(function(p) {
p.depth = count - countNow;
if (p.inner) p.inner.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - countNow);
});
});
});
});
});
}
}
}

View file

@ -82,6 +82,7 @@ self.kiri.license = exports.LICENSE;
outputFinishFactor: 1,
outputAccelComp: 1,
outputOuterFirst: 1,
detectThinWalls: 1,
outputWipeSpeed: 1,
outputWipeDistance: 1,
outputClockwise: 1,
@ -281,6 +282,7 @@ self.kiri.license = exports.LICENSE;
outputFinishFactor: 0,
outputAccelComp: false,
outputOuterFirst: false,
detectThinWalls: false,
// --- LASER ---
@ -2369,6 +2371,7 @@ self.kiri.license = exports.LICENSE;
outputFinishFactor: UC.newInput("finish factor", {title:"% of nozzle diameter to\nshorten finish path by\nvalues of 0-1", bound:UC.bound(0.0,1), convert:UC.toFloat, modes:FDM}),
outputAccelComp: UC.newBoolean("acceleration", onBooleanClick, {title: "acceleration compensation\nexperimental", modes:FDM}),
outputOuterFirst: UC.newBoolean("outer first", onBooleanClick, {title: "output outermost shell first", modes:FDM}),
detectThinWalls: UC.newBoolean("thin wall", onBooleanClick, {title: "thin wall detection\nexperimental", modes:FDM}),
});
function toolUpdate(a,b,c) {