add gbr to loader classes
This commit is contained in:
parent
9adfe33cfb
commit
fdfea41a48
8 changed files with 179 additions and 129 deletions
|
|
@ -1851,8 +1851,8 @@ class Polygon {
|
|||
return this;
|
||||
}
|
||||
|
||||
// turn 2d polygon into closed 3d mesh faces
|
||||
extrude(z = 1) {
|
||||
// turn 2d polygon into a 2.5D ribbon extruded in Z
|
||||
ribbonZ(z = 1) {
|
||||
let poly = this.clone().setClockwise();
|
||||
let faces = [];
|
||||
let points = poly.points;
|
||||
|
|
@ -1870,6 +1870,25 @@ class Polygon {
|
|||
return faces;
|
||||
}
|
||||
|
||||
// extrude poly (with inner voids) into 3d mesh
|
||||
extrude(z = 1) {
|
||||
let obj = [];
|
||||
let earcut = this.earcut();
|
||||
for (let poly of earcut) {
|
||||
for (let point of poly.points) {
|
||||
obj.push(point.x, point.y, z);
|
||||
}
|
||||
for (let point of poly.points.reverse()) {
|
||||
obj.push(point.x, point.y, 0);
|
||||
}
|
||||
}
|
||||
obj.appendAll(this.ribbonZ(z));
|
||||
for (let inner of this.inner || []) {
|
||||
obj.appendAll(inner.ribbonZ(z));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
// split long straight lines into segments no longer than max
|
||||
// and return a new polygon
|
||||
segment(max = 1) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// dep: kiri-mode.cam.driver
|
||||
// use: kiri-mode.cam.animate
|
||||
// use: kiri-mode.cam.animate2
|
||||
// use: load.gbr
|
||||
gapp.register("kiri-mode.cam.client", [], (root, exports) => {
|
||||
|
||||
const { base, kiri } = root;
|
||||
|
|
@ -116,102 +117,7 @@ CAM.init = function(kiri, api) {
|
|||
}
|
||||
|
||||
api.event.on("cam.parse.gerber", gerber => {
|
||||
let fact = 1000000;
|
||||
let tools = {};
|
||||
let tool;
|
||||
let poly;
|
||||
let polys = [];
|
||||
let circs = [];
|
||||
let rects = [];
|
||||
let last = {};
|
||||
let bounds = base.newBounds();
|
||||
let p = TracespaceParser.createParser();
|
||||
p.feed(gerber);
|
||||
let r = p.results();
|
||||
let c = r.children
|
||||
.filter(c => {
|
||||
switch (c.type) {
|
||||
case 'toolDefinition':
|
||||
tools[c.code] = c.shape;
|
||||
break;
|
||||
case 'toolChange':
|
||||
tool = { code: c.code, shape: tools[c.code] };
|
||||
break;
|
||||
case 'graphic':
|
||||
c.tool = tool;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map(r => {
|
||||
return {
|
||||
type: r.graphic,
|
||||
tool: r.tool,
|
||||
x: parseInt(r.coordinates.x),
|
||||
y: parseInt(r.coordinates.y)
|
||||
};
|
||||
})
|
||||
.map(r => {
|
||||
const { x, y, tool, type } = r;
|
||||
const pos = { x:x/fact, y:y/fact, z: 0};
|
||||
bounds.update(pos);
|
||||
switch (type) {
|
||||
case 'move':
|
||||
if (true && poly && last.x === x && last.y === y && last.tool === tool) {
|
||||
// console.log('continuation');
|
||||
} else {
|
||||
poly = base.newPolygon().setOpen().add(pos.x, pos.y, 0);
|
||||
poly.tool = tool;
|
||||
polys.push(poly);
|
||||
}
|
||||
break;
|
||||
case 'segment':
|
||||
poly.add(pos.x, pos.y, 0);
|
||||
break;
|
||||
case 'shape':
|
||||
poly = undefined;
|
||||
let { shape } = tool;
|
||||
switch (shape.type) {
|
||||
case 'obround':
|
||||
if (shape.xSize === shape.ySize) {
|
||||
circs.push(base.newPolygon().centerCircle(pos, shape.xSize / 2, 20));
|
||||
} else {
|
||||
console.log('TODO', shape);
|
||||
}
|
||||
break;
|
||||
case 'circle':
|
||||
circs.push(base.newPolygon().centerCircle(pos, shape.diameter / 2, 20));
|
||||
break;
|
||||
case 'rectangle':
|
||||
rects.push(base.newPolygon().centerRectangle(pos, shape.xSize, shape.ySize));
|
||||
break;
|
||||
default:
|
||||
console.log('TODO', shape);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
last = { x, y, tool };
|
||||
return r;
|
||||
});
|
||||
const { minx, maxx, miny, maxy } = bounds;
|
||||
for (let poly of [...polys, ...circs, ...rects]) {
|
||||
poly.move({
|
||||
x: -((maxx-minx)/2 + minx),
|
||||
y: -((maxy-miny)/2 + miny),
|
||||
z: 0
|
||||
});
|
||||
}
|
||||
const open = [];
|
||||
const closed = [];
|
||||
for (let poly of polys) {
|
||||
if (poly.appearsClosed()) {
|
||||
closed.push(...poly.simplify());
|
||||
} else {
|
||||
open.push(poly);
|
||||
}
|
||||
}
|
||||
console.log({ open, closed, circs, rects });
|
||||
const { open, closed, circs, rects } = load.GBR.parse(gerber);
|
||||
const widget = api.widgets.all()[0];
|
||||
const stack = new kiri.Stack(widget.mesh);
|
||||
const layers = new kiri.Layers();
|
||||
|
|
@ -228,7 +134,6 @@ CAM.init = function(kiri, api) {
|
|||
layers.setLayer("rects", {line: 0x0000ff}, false).addPoly(poly);
|
||||
}
|
||||
stack.addLayers(layers);
|
||||
console.log(r, tools);
|
||||
});
|
||||
|
||||
api.event.on("widget.add", widget => {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const POLY = polygons;
|
|||
|
||||
let debug = self.debug === true,
|
||||
ccvalue = this.navigator ? navigator.hardwareConcurrency || 0 : 0,
|
||||
concurrent = self.Worker && ccvalue > 3 ? ccvalue - 1 : 0,
|
||||
concurrent = Math.min(4, self.Worker && ccvalue > 3 ? ccvalue - 1 : 0),
|
||||
current = self.worker = {
|
||||
print: null,
|
||||
snap: null,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
// dep: kiri.selection
|
||||
// use: kiri.tools
|
||||
// use: kiri.pack
|
||||
// use: ext.gerber
|
||||
gapp.register("kiri.init", [], (root, exports) => {
|
||||
|
||||
const { base, kiri } = root;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
// dep: load.stl
|
||||
// dep: load.obj
|
||||
// dep: load.3mf
|
||||
// dep: load.gbr
|
||||
// use: kiri-mode.cam.tool
|
||||
gapp.register("kiri.platform", [], (root, exports) => {
|
||||
|
||||
|
|
@ -753,18 +754,18 @@ function platformLoadFiles(files, group) {
|
|||
const file = files[i],
|
||||
reader = new FileReader(),
|
||||
lower = files[i].name.toLowerCase(),
|
||||
israw = lower.indexOf(".raw") > 0 || lower.indexOf('.') < 0,
|
||||
isstl = lower.indexOf(".stl") > 0,
|
||||
isobj = lower.indexOf(".obj") > 0,
|
||||
is3mf = lower.indexOf(".3mf") > 0,
|
||||
issvg = lower.indexOf(".svg") > 0,
|
||||
ispng = lower.indexOf(".png") > 0,
|
||||
isjpg = lower.indexOf(".jpg") > 0,
|
||||
isgcode = lower.indexOf(".gcode") > 0 || lower.indexOf(".nc") > 0,
|
||||
isset = lower.indexOf(".b64") > 0 || lower.indexOf(".km") > 0,
|
||||
iskmz = lower.indexOf(".kmz") > 0,
|
||||
isini = lower.indexOf(".ini") > 0,
|
||||
isgrb = lower.indexOf(".grb");
|
||||
israw = lower.endsWith(".raw") || lower.indexOf('.') < 0,
|
||||
isstl = lower.endsWith(".stl"),
|
||||
isobj = lower.endsWith(".obj"),
|
||||
is3mf = lower.endsWith(".3mf"),
|
||||
issvg = lower.endsWith(".svg"),
|
||||
ispng = lower.endsWith(".png"),
|
||||
isjpg = lower.endsWith(".jpg"),
|
||||
isgcode = lower.endsWith(".gcode") || lower.endsWith(".nc"),
|
||||
isset = lower.endsWith(".b64") || lower.endsWith(".km"),
|
||||
iskmz = lower.endsWith(".kmz"),
|
||||
isini = lower.endsWith(".ini"),
|
||||
isgbr = lower.endsWith(".gbr");
|
||||
reader.file = files[i];
|
||||
reader.onloadend = function(e) {
|
||||
function load_dec() {
|
||||
|
|
@ -818,11 +819,17 @@ function platformLoadFiles(files, group) {
|
|||
} else {
|
||||
odon();
|
||||
}
|
||||
} else if (isgrb && api.conf.get().controller.devel) {
|
||||
} else if (isgbr && api.conf.get().controller.devel) {
|
||||
if (api.mode.is_cam()) {
|
||||
api.event.emit('cam.parse.gerber', e.target.result);
|
||||
} else {
|
||||
api.alerts.show('Gerber import not availabe in this device mode');
|
||||
let mesh = load.GBR.toMesh(e.target.result);
|
||||
platform.add(
|
||||
newWidget(undefined, group)
|
||||
.loadVertices(mesh.toFloat32(), true)
|
||||
.saveToCatalog(e.target.file.name)
|
||||
);
|
||||
// api.alerts.show('Gerber import not availabe in this device mode');
|
||||
}
|
||||
} else if (is3mf) {
|
||||
let odon = function(models) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ if (load.File) return;
|
|||
// dep: load.svg
|
||||
// dep: load.url
|
||||
// dep: load.png
|
||||
// dep: load.gbr
|
||||
gapp.register('load.file', []);
|
||||
|
||||
const types = {
|
||||
|
|
@ -48,6 +49,10 @@ const types = {
|
|||
resolve({ mesh: data, file });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
gbr(data, file, resolve, reject, opt = {}) {
|
||||
resolve([{ mesh: load.GBR.toMesh(data).toFloat32(), file }])
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
128
src/load/gbr.js
Normal file
128
src/load/gbr.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
// use: geo.bounds
|
||||
// use: geo.polygon
|
||||
// use: geo.polygons
|
||||
// use: ext.gerber
|
||||
gapp.register("load.gbr", (root, exports) => {
|
||||
|
||||
const { load } = root;
|
||||
|
||||
load.GBR = {
|
||||
parse,
|
||||
toMesh
|
||||
};
|
||||
|
||||
function toMesh(text, opt = { z: 3 }) {
|
||||
const { open, closed, circs, rects } = parse(text);
|
||||
const nest = base.polygons.nest([...closed, ...circs, ...rects], true);
|
||||
console.log({ nest });
|
||||
const obj = [];
|
||||
for (let poly of nest) {
|
||||
obj.appendAll(poly.extrude(opt.z || 3));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function parse(text) {
|
||||
let fact = 1000000;
|
||||
let tools = {};
|
||||
let tool;
|
||||
let poly;
|
||||
let polys = [];
|
||||
let circs = [];
|
||||
let rects = [];
|
||||
let last = {};
|
||||
let bounds = base.newBounds();
|
||||
let p = TracespaceParser.createParser();
|
||||
p.feed(text);
|
||||
let r = p.results();
|
||||
let c = r.children
|
||||
.filter(c => {
|
||||
switch (c.type) {
|
||||
case 'toolDefinition':
|
||||
tools[c.code] = c.shape;
|
||||
break;
|
||||
case 'toolChange':
|
||||
tool = { code: c.code, shape: tools[c.code] };
|
||||
break;
|
||||
case 'graphic':
|
||||
c.tool = tool;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map(r => {
|
||||
return {
|
||||
type: r.graphic,
|
||||
tool: r.tool,
|
||||
x: parseInt(r.coordinates.x),
|
||||
y: parseInt(r.coordinates.y)
|
||||
};
|
||||
})
|
||||
.map(r => {
|
||||
const { x, y, tool, type } = r;
|
||||
const pos = { x:x/fact, y:y/fact, z: 0};
|
||||
bounds.update(pos);
|
||||
switch (type) {
|
||||
case 'move':
|
||||
if (true && poly && last.x === x && last.y === y && last.tool === tool) {
|
||||
// console.log('continuation');
|
||||
} else {
|
||||
poly = base.newPolygon().setOpen().add(pos.x, pos.y, 0);
|
||||
poly.tool = tool;
|
||||
polys.push(poly);
|
||||
}
|
||||
break;
|
||||
case 'segment':
|
||||
poly.add(pos.x, pos.y, 0);
|
||||
break;
|
||||
case 'shape':
|
||||
poly = undefined;
|
||||
let { shape } = tool;
|
||||
switch (shape.type) {
|
||||
case 'obround':
|
||||
if (shape.xSize === shape.ySize) {
|
||||
circs.push(base.newPolygon().centerCircle(pos, shape.xSize / 2, 20));
|
||||
} else {
|
||||
console.log('TODO', shape);
|
||||
}
|
||||
break;
|
||||
case 'circle':
|
||||
circs.push(base.newPolygon().centerCircle(pos, shape.diameter / 2, 20));
|
||||
break;
|
||||
case 'rectangle':
|
||||
rects.push(base.newPolygon().centerRectangle(pos, shape.xSize, shape.ySize));
|
||||
break;
|
||||
default:
|
||||
console.log('TODO', shape);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
last = { x, y, tool };
|
||||
return r;
|
||||
});
|
||||
const { minx, maxx, miny, maxy } = bounds;
|
||||
for (let poly of [...polys, ...circs, ...rects]) {
|
||||
poly.move({
|
||||
x: -((maxx-minx)/2 + minx),
|
||||
y: -((maxy-miny)/2 + miny),
|
||||
z: 0
|
||||
});
|
||||
}
|
||||
const open = [];
|
||||
const closed = [];
|
||||
for (let poly of polys) {
|
||||
if (poly.appearsClosed()) {
|
||||
closed.push(...poly.simplify());
|
||||
} else {
|
||||
open.push(poly);
|
||||
}
|
||||
}
|
||||
// const nest = base.polygons.nest([...closed, ...circs, ...rects], true);
|
||||
// console.log({ nest });
|
||||
return { open, closed, circs, rects };
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -74,20 +74,7 @@ function parse(text, opt = { soup: true }) {
|
|||
|
||||
let z = parseFloat(depth.value);
|
||||
for (let poly of nest) {
|
||||
let obj = [];
|
||||
let earcut = poly.earcut();
|
||||
for (let poly of earcut) {
|
||||
for (let point of poly.points) {
|
||||
obj.push(point.x, point.y, z);
|
||||
}
|
||||
for (let point of poly.points.reverse()) {
|
||||
obj.push(point.x, point.y, 0);
|
||||
}
|
||||
}
|
||||
obj.appendAll(poly.extrude(z));
|
||||
for (let inner of poly.inner || []) {
|
||||
obj.appendAll(inner.extrude(z));
|
||||
}
|
||||
let obj = poly.extrude(z);
|
||||
objs.push(obj);
|
||||
// invert y
|
||||
for (let i=1, l=obj.length; i<l; i += 3) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue