start to structure tracing code split as client/worker
This commit is contained in:
parent
c2d05ddfd9
commit
563fcb71d0
7 changed files with 116 additions and 147 deletions
1
notes.md
1
notes.md
|
|
@ -4,6 +4,7 @@
|
||||||
* `cnc`
|
* `cnc`
|
||||||
* - tracing (chamfer, engrave)
|
* - tracing (chamfer, engrave)
|
||||||
* - auto feature detection (slicing)
|
* - auto feature detection (slicing)
|
||||||
|
* - compute tolerance from animesh when set to 0
|
||||||
* `laser`
|
* `laser`
|
||||||
* - drag knife support
|
* - drag knife support
|
||||||
* `all`
|
* `all`
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ function send(fn, data, onreply, zerocopy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// code is running in the browser / client context
|
// code is running in the browser / client context
|
||||||
|
const CLIENT =
|
||||||
KIRI.client =
|
KIRI.client =
|
||||||
KIRI.work = {
|
KIRI.work = {
|
||||||
send: send,
|
send: send,
|
||||||
|
|
@ -120,44 +121,37 @@ KIRI.work = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// widget sync
|
||||||
|
sync: function(widget) {
|
||||||
|
let widgets = widget ? [ widget ] : KIRI.api.widgets.all();
|
||||||
|
widgets.forEach(widget => {
|
||||||
|
if (widget.modified) {
|
||||||
|
let vertices = widget.getGeoVertices().buffer.slice(0);
|
||||||
|
send("sync", {
|
||||||
|
id: widget.id,
|
||||||
|
vertices: vertices,
|
||||||
|
position: widget.mesh.position,
|
||||||
|
tracking: widget.track
|
||||||
|
}, done => {
|
||||||
|
widget.modified = false;
|
||||||
|
}, [vertices]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
slice: function(settings, widget, callback) {
|
slice: function(settings, widget, callback) {
|
||||||
let rotation = (Math.PI/180) * (settings.process.sliceRotation || 0);
|
CLIENT.sync(widget);
|
||||||
let centerz;
|
|
||||||
let movez;
|
|
||||||
if (rotation) {
|
|
||||||
let bbox1 = widget.getBoundingBox(true);
|
|
||||||
widget._rotate(0,rotation,0,true);
|
|
||||||
widget.center();
|
|
||||||
let bbox2 = widget.getBoundingBox(true);
|
|
||||||
centerz = (bbox2.max.z - bbox2.min.z)/2;
|
|
||||||
movez = centerz - (bbox1.max.z - bbox1.min.z)/2;
|
|
||||||
}
|
|
||||||
let vertices = widget.getGeoVertices().buffer.slice(0);
|
|
||||||
// snapshot = KIRI.api.view.snapshot;
|
|
||||||
if (rotation) {
|
|
||||||
widget._rotate(0,-rotation,0,true);
|
|
||||||
widget.center();
|
|
||||||
}
|
|
||||||
slicing[widget.id] = callback;
|
slicing[widget.id] = callback;
|
||||||
send("slice", {
|
send("slice", {
|
||||||
id: widget.id,
|
id: widget.id,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
vertices: vertices,
|
rotation: (Math.PI/180) * (settings.process.sliceRotation || 0)
|
||||||
position: widget.mesh.position,
|
|
||||||
tracking: widget.track,
|
|
||||||
// snapshot: snapshot,
|
|
||||||
// for rotation / unrotation
|
|
||||||
state: {
|
|
||||||
rotation: rotation,
|
|
||||||
centerz: centerz,
|
|
||||||
movez: movez
|
|
||||||
}
|
|
||||||
}, function(reply) {
|
}, function(reply) {
|
||||||
if (reply.done || reply.error) {
|
if (reply.done || reply.error) {
|
||||||
delete slicing[widget.id];
|
delete slicing[widget.id];
|
||||||
}
|
}
|
||||||
callback(reply);
|
callback(reply);
|
||||||
}, [vertices]);
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
prepare: function(settings, update, done) {
|
prepare: function(settings, update, done) {
|
||||||
|
|
|
||||||
|
|
@ -302,12 +302,12 @@
|
||||||
PRO.clearSlices = function() {
|
PRO.clearSlices = function() {
|
||||||
let slices = this.slices,
|
let slices = this.slices,
|
||||||
mesh = this.mesh;
|
mesh = this.mesh;
|
||||||
if (slices) {
|
if (slices && mesh) {
|
||||||
slices.forEach(function(slice) {
|
slices.forEach(function(slice) {
|
||||||
mesh.remove(slice.view);
|
mesh.remove(slice.view);
|
||||||
});
|
});
|
||||||
this.slices = null;
|
|
||||||
}
|
}
|
||||||
|
this.slices = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -38,42 +38,56 @@ KIRI.worker = {
|
||||||
send.done();
|
send.done();
|
||||||
},
|
},
|
||||||
|
|
||||||
slice: function(data, send) {
|
// widget sync
|
||||||
let settings = data.settings,
|
sync: function(data, send) {
|
||||||
vertices = new Float32Array(data.vertices),
|
let vertices = new Float32Array(data.vertices),
|
||||||
position = data.position,
|
|
||||||
tracking = data.tracking,
|
|
||||||
points = BASE.verticesToPoints(vertices, { maxpass: 0 }),
|
points = BASE.verticesToPoints(vertices, { maxpass: 0 }),
|
||||||
state = data.state || {},
|
widget = KIRI.newWidget(data.id).setPoints(points);
|
||||||
rotation = state.rotation,
|
|
||||||
centerz = state.centerz,
|
|
||||||
movez = state.movez;
|
|
||||||
|
|
||||||
if (rotation) {
|
|
||||||
state.rotate = new THREE.Matrix4().makeRotationY(-rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
send.data({update:0.05, updateStatus:"slicing"});
|
|
||||||
|
|
||||||
let widget = KIRI.newWidget(data.id).setPoints(points),
|
|
||||||
last = time(),
|
|
||||||
now;
|
|
||||||
|
|
||||||
// do it here so cancel can work
|
// do it here so cancel can work
|
||||||
cache[data.id] = widget;
|
cache[data.id] = widget;
|
||||||
|
|
||||||
// fake mesh object to satisfy printing
|
// fake mesh object to satisfy printing
|
||||||
widget.track = tracking;
|
widget.track = data.tracking;
|
||||||
widget.mesh = {
|
widget.mesh = {
|
||||||
widget: widget,
|
widget: widget,
|
||||||
position: position
|
position: data.position
|
||||||
};
|
};
|
||||||
|
|
||||||
|
send.done(data.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
slice: function(data, send) {
|
||||||
|
let { id, settings, rotation } = data;
|
||||||
|
|
||||||
|
// let centerz;
|
||||||
|
// let movez;
|
||||||
|
// if (rotation) {
|
||||||
|
// let bbox1 = widget.getBoundingBox(true);
|
||||||
|
// widget._rotate(0,rotation,0,true);
|
||||||
|
// widget.center();
|
||||||
|
// let bbox2 = widget.getBoundingBox(true);
|
||||||
|
// centerz = (bbox2.max.z - bbox2.min.z)/2;
|
||||||
|
// movez = centerz - (bbox1.max.z - bbox1.min.z)/2;
|
||||||
|
// }
|
||||||
|
// let vertices = widget.getGeoVertices().buffer.slice(0);
|
||||||
|
// // snapshot = KIRI.api.view.snapshot;
|
||||||
|
// if (rotation) {
|
||||||
|
// widget._rotate(0,-rotation,0,true);
|
||||||
|
// widget.center();
|
||||||
|
// }
|
||||||
|
|
||||||
|
send.data({update:0.05, updateStatus:"slicing"});
|
||||||
|
|
||||||
|
let widget = cache[data.id],
|
||||||
|
last = time(),
|
||||||
|
now;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
widget.slice(settings, function(error) {
|
widget.slice(settings, function(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
delete cache[data.id];
|
// delete cache[id];
|
||||||
send.data({error: error});
|
send.data({error: error});
|
||||||
} else {
|
} else {
|
||||||
const slices = widget.slices || [];
|
const slices = widget.slices || [];
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@
|
||||||
|
|
||||||
api.event.on("cam.trace.add", func.traceAdd = () => {
|
api.event.on("cam.trace.add", func.traceAdd = () => {
|
||||||
alert = api.show.alert("<esc> key cancels editing traces");
|
alert = api.show.alert("<esc> key cancels editing traces");
|
||||||
|
KIRI.client.traces(done => {
|
||||||
|
console.log({got_traces: done});
|
||||||
|
});
|
||||||
api.feature.hover = true;
|
api.feature.hover = true;
|
||||||
});
|
});
|
||||||
api.event.on("cam.trace.done", func.traceDone = () => {
|
api.event.on("cam.trace.done", func.traceDone = () => {
|
||||||
|
|
|
||||||
|
|
@ -21,77 +21,25 @@
|
||||||
DRILL: 7
|
DRILL: 7
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// defer loading until KIRI.client and KIRI.worker exist
|
||||||
* Find top paths to trace when using ball and taper mills
|
KIRI.loader.push(function(API) {
|
||||||
* in waterline outlining and tracing modes.
|
|
||||||
*/
|
if (KIRI.client)
|
||||||
function findTracingPaths(widget, slice, tool, profile, partial) {
|
KIRI.client.traces = function(ondone) {
|
||||||
// for now, only emit completed polys and not segments
|
KIRI.client.sync();
|
||||||
// TODO consider limiting to nup path lengths that are >= tool radius
|
send("traces", {
|
||||||
let only_whole = !partial;
|
settings: API.conf.get()
|
||||||
// check for ball and taper mills paths and add to top[0].inner
|
}, ondone);
|
||||||
let polys = [];
|
};
|
||||||
let nups = [];
|
|
||||||
let cull = [];
|
if (KIRI.worker)
|
||||||
slice.gatherTopPolys([]).forEach(poly => poly.flattenTo(polys));
|
KIRI.worker.traces = function(data, send) {
|
||||||
polys.forEach(poly => {
|
const { settings } = data;
|
||||||
let pz = poly.first().z;
|
const widgets = Object.values(cache);
|
||||||
let mz = -Infinity;
|
widgets.forEach(widget => CAM.traces(settings, widget));
|
||||||
let np = newPolygon().setOpen();
|
send.done(123);
|
||||||
let mp = 0;
|
};
|
||||||
// find top poly segments that are not significantly offset
|
|
||||||
// from tool profile and add to new polygons which accumulate
|
|
||||||
// to the top inner array
|
|
||||||
poly.forEachSegment((p1,p2) => {
|
|
||||||
let nz = getTopoZPathMax(widget, profile, p1.x, p1.y, p2.x, p2.y);
|
|
||||||
if (nz > mz) {
|
|
||||||
mz = nz;
|
|
||||||
}
|
|
||||||
// this # should be computed from topo resolution
|
|
||||||
if (nz - pz < 0.01) {
|
|
||||||
mp++
|
|
||||||
if (np.length) {
|
|
||||||
if (!np.first().isEqual(p2)) {
|
|
||||||
np.append(p2);
|
|
||||||
} else {
|
|
||||||
np.setClosed();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
np.append(p1).append(p2);
|
|
||||||
}
|
|
||||||
} else if (np.length) {
|
|
||||||
if (!only_whole) {
|
|
||||||
nups.append(np);
|
|
||||||
}
|
|
||||||
np = newPolygon().setOpen();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (np.length) {
|
|
||||||
if (np.length === poly.length) {
|
|
||||||
np.setClosed();
|
|
||||||
}
|
|
||||||
// if a trace poly has no interruptions for an endmill
|
|
||||||
// and it's an inner poly, eliminate it from the parent
|
|
||||||
// so it won't be offset.
|
|
||||||
let parent = poly.parent;
|
|
||||||
if (np.isClosed() && parent) {
|
|
||||||
// console.log(slice.z,'cull',poly);
|
|
||||||
if (parent.inner) {
|
|
||||||
parent.inner = parent.inner.filter(p => p !== poly);
|
|
||||||
}
|
|
||||||
if (only_whole) {
|
|
||||||
nups.append(np);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!only_whole) {
|
|
||||||
nups.append(np);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (nups.length) {
|
|
||||||
// console.log(slice.z,'nups',nups.length);
|
|
||||||
slice.tops[0].inner = nups;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -483,31 +483,10 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare for tracing paths
|
// generate tracing offsets from chosen features
|
||||||
if (procTrace) {
|
if (procTrace) {
|
||||||
let traceTool = new CAM.Tool(conf, proc.camTraceTool);
|
// todo
|
||||||
let traceToolDiam = traceTool.fluteDiameter();
|
// slice.camMode = PRO.TRACE;
|
||||||
maxToolDiam = Math.max(maxToolDiam, traceToolDiam);
|
|
||||||
// unique merge of z flats and z line indices
|
|
||||||
let indices = [...new Set(Object.keys(slicer.zFlat)
|
|
||||||
.map(kv => parseFloat(kv).round(5))
|
|
||||||
.appendAll(Object.entries(slicer.zLine).map(ze => {
|
|
||||||
let [ zk, zv ] = ze;
|
|
||||||
return zv > 0 ? parseFloat(zk).round(5) : null;
|
|
||||||
})
|
|
||||||
.filter(v => v !== null)))]
|
|
||||||
.sort((a,b) => b - a);
|
|
||||||
let slices = [];
|
|
||||||
slicer.slice(indices, { each: (data, index, total) => {
|
|
||||||
let slice = data.slice;
|
|
||||||
slice.camMode = PRO.TRACE;
|
|
||||||
slices.push(slice);
|
|
||||||
sliceAll.append(slice);
|
|
||||||
if (true) slice.output()
|
|
||||||
.setLayer("trace", {line: 0x88aa55}, false)
|
|
||||||
.addPolys(slice.topPolys())
|
|
||||||
updateOp(index, total);
|
|
||||||
}, genso: true, emptyok: true, flatoff: 0, edges: true, openok: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (procDrill) {
|
if (procDrill) {
|
||||||
|
|
@ -539,6 +518,36 @@
|
||||||
ondone();
|
ondone();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CAM.traces = function computeTraces(settings, widget) {
|
||||||
|
let slicer = new KIRI.slicer2(widget.getPoints(), {
|
||||||
|
zlist: true,
|
||||||
|
zline: true
|
||||||
|
});
|
||||||
|
let proc = settings.process;
|
||||||
|
let traceTool = new CAM.Tool(settings, proc.camTraceTool);
|
||||||
|
let traceToolDiam = traceTool.fluteDiameter();
|
||||||
|
// widget.maxToolDiam = Math.max(maxToolDiam, traceToolDiam);
|
||||||
|
// unique merge of z flats and z line indices
|
||||||
|
let indices = [...new Set(Object.keys(slicer.zFlat)
|
||||||
|
.map(kv => parseFloat(kv).round(5))
|
||||||
|
.appendAll(Object.entries(slicer.zLine).map(ze => {
|
||||||
|
let [ zk, zv ] = ze;
|
||||||
|
return zv > 0 ? parseFloat(zk).round(5) : null;
|
||||||
|
})
|
||||||
|
.filter(v => v !== null)))]
|
||||||
|
.sort((a,b) => b - a);
|
||||||
|
let traces = [];
|
||||||
|
slicer.slice(indices, { each: (data, index, total) => {
|
||||||
|
let slice = data.slice;
|
||||||
|
traces.push(slice);
|
||||||
|
if (true) slice.output()
|
||||||
|
.setLayer("trace", {line: 0x88aa55}, false)
|
||||||
|
.addPolys(slice.topPolys())
|
||||||
|
// updateOp(index, total);
|
||||||
|
}, genso: true, emptyok: true, flatoff: 0, edges: true, openok: true });
|
||||||
|
widget.traces = traces;
|
||||||
|
};
|
||||||
|
|
||||||
// drilling op
|
// drilling op
|
||||||
function sliceDrill(tool, slices, output) {
|
function sliceDrill(tool, slices, output) {
|
||||||
let drills = [],
|
let drills = [],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue