improve open poly offsetting. change gerber trace 3d interpetation

This commit is contained in:
Stewart Allen 2024-07-01 20:52:49 -04:00
commit 619468ee00
4 changed files with 77 additions and 24 deletions

View file

@ -1495,7 +1495,6 @@ class Polygon {
toClipper(inout) { toClipper(inout) {
let poly = this, let poly = this,
cur = [],
out = inout || []; out = inout || [];
out.push(poly.points.map(p => p.toClipper())); out.push(poly.points.map(p => p.toClipper()));
if (poly.inner) { if (poly.inner) {
@ -1519,6 +1518,37 @@ class Polygon {
return POLY.expand([this], -offset, this.getZ(), output); return POLY.expand([this], -offset, this.getZ(), output);
} }
/**
* ofsetting an open line uses a different procedure and options
*
* @param {number} distance
* @param {'square'|'round'|'miter'} type
* @returns {Polygon[]}
*/
offset_open(distance, type = 'miter') {
if (this.isOpen()) {
let cjnt = clib.JoinType,
cety = clib.EndType,
coff = new clib.ClipperOffset(),
ctre = new clib.PolyTree(),
entt = {
'square' : cety.etOpenSquare,
'round' : cety.etOpenRound,
'miter' : cety.etOpenSquare
}[type] || cety.etOpenSquare,
jntt = {
'square': cjnt.jtSquare,
'round': cjnt.jtRound,
'miter': cjnt.jtMiter
}[type] || cjnt.jtMiter;
coff.AddPaths(this.toClipper(), jntt, entt);
coff.Execute(ctre, distance * config.clipper);
return POLY.fromClipperTree(ctre, this.getZ(), null, null, 0);
} else {
return this.offset(distance);
}
}
/** /**
* todo need something more clever for polygons that overlap with * todo need something more clever for polygons that overlap with
* todo differing resolutions (like circles) * todo differing resolutions (like circles)

View file

@ -34,7 +34,7 @@ const POLYS = base.polygons = {
offset, offset,
trimTo, trimTo,
expand, expand,
expand_lines, // expand_lines,
points, points,
length, length,
route, route,
@ -508,18 +508,18 @@ function sumCirc(polys) {
* @param {number} distance offset * @param {number} distance offset
* @param {number} [z] defaults to 0 * @param {number} [z] defaults to 0
*/ */
function expand_lines(poly, distance, z) { // function expand_lines(poly, distance, z) {
let fact = config.clipper, // let fact = config.clipper,
cjnt = clib.JoinType, // cjnt = clib.JoinType,
cety = clib.EndType, // cety = clib.EndType,
coff = new clib.ClipperOffset(), // coff = new clib.ClipperOffset(),
ctre = new clib.PolyTree(); // ctre = new clib.PolyTree();
coff.AddPaths(poly.toClipper(), cjnt.jtMiter, cety.etOpenSquare); // coff.AddPaths(poly.toClipper(), cjnt.jtMiter, cety.etOpenSquare);
coff.Execute(ctre, distance * fact); // coff.Execute(ctre, distance * fact);
return fromClipperTree(ctre, z, null, null, 0); // return fromClipperTree(ctre, z, null, null, 0);
} // }
/** /**
* @param {Polygon[]} polys * @param {Polygon[]} polys

View file

@ -123,6 +123,11 @@ CAM.init = function(kiri, api) {
const layers = new kiri.Layers(); const layers = new kiri.Layers();
for (let poly of open) { for (let poly of open) {
layers.setLayer("open", {line: 0xff8800}, false).addPoly(poly); layers.setLayer("open", {line: 0xff8800}, false).addPoly(poly);
let diam = poly.tool?.shape?.diameter;
if (diam) {
const exp = poly.offset_open(diam, 'round');
layers.setLayer("open2", {line: 0xff5555}, false).addPolys(exp);
}
} }
for (let poly of closed) { for (let poly of closed) {
layers.setLayer("close", {line: 0xff0000}, false).addPoly(poly); layers.setLayer("close", {line: 0xff0000}, false).addPoly(poly);

View file

@ -44,7 +44,7 @@ function toMesh(text, opt = { z: 1 }) {
return []; return [];
} }
// copper traces // copper pads
const mid = []; const mid = [];
for (let poly of flat.filter(p => p.depth === 1)) { for (let poly of flat.filter(p => p.depth === 1)) {
mid.push(poly.extrude(z1, z0 - z1)); mid.push(poly.extrude(z1, z0 - z1));
@ -55,10 +55,24 @@ function toMesh(text, opt = { z: 1 }) {
return top[0]; return top[0];
} }
// inner polys for traces which we will punch thru for vias // copper traces (expand first since open)
const open_exp = open.map(poly => {
const diam = poly.tool?.shape?.diameter;
return diam ? poly.offset_open(diam, 'round') : null;
}).filter(p => p).flat();
// union open trace expansions
const opn = [];
for (let poly of POLYS.union(open_exp)) {
const tool = poly.tool;
opn.push(poly.extrude(z0));
}
// inner polys for traces which we add back to the top
// and (optionally) remove from the bottom for making vias
const low = []; const low = [];
for (let poly of flat.filter(p => p.depth === 2)) { for (let poly of flat.filter(p => p.depth === 2)) {
low.push(poly.extrude(z0)); low.push(poly.extrude(z1, z0 - z1));
} }
// convert vertex arrays to csg mesh definitions // convert vertex arrays to csg mesh definitions
@ -66,17 +80,21 @@ function toMesh(text, opt = { z: 1 }) {
const midMesh = mid.map(v => CSG.fromPositionArray(v)); const midMesh = mid.map(v => CSG.fromPositionArray(v));
// subtract mid from top // subtract mid from top
const v0Mesh = CSG.subtract(topMesh, ...midMesh); let meshOut = CSG.subtract(topMesh, ...midMesh);
if (low.length === 0) { if (opn.length) {
return CSG.toPositionArray(v0Mesh); // add back raised traces (before removing vias)
const opnMesh = opn.map(v => CSG.fromPositionArray(v))
meshOut = CSG.union(meshOut, ...opnMesh);
} }
// subtract low (vias) from remaining if (low.length) {
const lowMesh = low.map(v => CSG.fromPositionArray(v)) // subtract low (vias) from remaining
const v1Mesh = CSG.subtract(v0Mesh, ...lowMesh); const lowMesh = low.map(v => CSG.fromPositionArray(v))
meshOut = CSG.union(meshOut, ...lowMesh);
}
return CSG.toPositionArray(v1Mesh); return CSG.toPositionArray(meshOut);
} }
function parse(text) { function parse(text) {