improve open poly offsetting. change gerber trace 3d interpetation
This commit is contained in:
parent
903a0007d6
commit
619468ee00
4 changed files with 77 additions and 24 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue