Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 79 additions & 21 deletions lib/gerber/gerberparser.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
function parseGerber(e, name) {
console.log(Gerber.render(e))
// console.log(Gerber.render(e)) // Added for debugging Gerber render output
var t, n = !0;
signalBottomPrimitives = mergeAllPrimitives(Gerber.render(e), "#90ffa0");
// console.log(signalBottomPrimitives)
// console.log(signalBottomPrimitives) // Added for debugging merged primitives
var gerber = new THREE.Object3D()

// console.log(signalBottomPrimitives)
Expand Down Expand Up @@ -505,6 +505,39 @@ var GCode = {
}
}
};
/**
* Approximates an arc by generating a series of line segments.
* Used for converting Gerber circular interpolation commands into polygonal paths.
* @param {number} startX - Starting X coordinate
* @param {number} startY - Starting Y coordinate
* @param {number} endX - Ending X coordinate
* @param {number} endY - Ending Y coordinate
* @param {number} I - X offset to arc center from start point
* @param {number} J - Y offset to arc center from start point
* @param {string} mode - "CWCIRCULAR" or "CCWCIRCULAR" for clockwise/counterclockwise
* @param {number} numSegments - Number of segments to approximate the arc
* @returns {Array} Array of {X, Y} points approximating the arc
*/
function approximateArc(startX, startY, endX, endY, I, J, mode, numSegments) {
var centerX = startX + I;
var centerY = startY + J;
var radius = Math.sqrt((startX - centerX)**2 + (startY - centerY)**2);
var startAngle = Math.atan2(startY - centerY, startX - centerX);
var endAngle = Math.atan2(endY - centerY, endX - centerX);
var sweepAngle = endAngle - startAngle;
if (mode === "CWCIRCULAR" && sweepAngle > 0) sweepAngle -= 2 * Math.PI;
if (mode === "CCWCIRCULAR" && sweepAngle < 0) sweepAngle += 2 * Math.PI;
var segments = [];
for (var i = 0; i <= numSegments; i++) {
var angle = startAngle + (sweepAngle * i / numSegments);
segments.push({
X: centerX + radius * Math.cos(angle),
Y: centerY + radius * Math.sin(angle)
});
}
return segments;
}

var apertureScale = 1,
Gerber = {
render: function(D) {
Expand Down Expand Up @@ -613,24 +646,40 @@ var apertureScale = 1,
return e
}

function s(D, X, Y, e, t) {
for (var i = 0; i < t.primitives.length; i++) {
var s = t.primitives[i],
a = r({
X: D + s.offsetX,
Y: X + s.offsetY
}, {
X: Y + s.offsetX,
Y: e + s.offsetY
}, s.polygon),
o = translatePolygon(D + s.offsetX, X + s.offsetY, s.polygon),
f = translatePolygon(Y + s.offsetX, e + s.offsetY, s.polygon),
l = mergePolygons(a, mergePolygons(o, f));
fillPolygon(n, 0, 0, l)
// Modified function to accept mode, I, J parameters and handle arc approximation by recursively calling itself with linear segments
function s(D, X, Y, e, t, mode, I, J) {
if (!t || !t.primitives) {
console.warn("No valid aperture for stroke operation");
return;
}
if (mode !== "LINEAR") {
var points = approximateArc(D, X, Y, e, I, J, mode, 10);
for (var seg = 1; seg < points.length; seg++) {
s(points[seg-1].X, points[seg-1].Y, points[seg].X, points[seg].Y, t, "LINEAR", 0, 0);
}
} else {
for (var i = 0; i < t.primitives.length; i++) {
var prim = t.primitives[i],
a = r({
X: D + prim.offsetX,
Y: X + prim.offsetY
}, {
X: Y + prim.offsetX,
Y: e + prim.offsetY
}, prim.polygon),
o = translatePolygon(D + prim.offsetX, X + prim.offsetY, prim.polygon),
f = translatePolygon(Y + prim.offsetX, e + prim.offsetY, prim.polygon),
l = mergePolygons(a, mergePolygons(o, f));
fillPolygon(n, 0, 0, l)
}
}
}

function a(D, X, Y) {
if (!Y || !Y.primitives) {
console.warn("No valid aperture for flash operation");
return;
}
for (var e = 0; e < Y.primitives.length; e++) {
var t = Y.primitives[e];
fillPolygon(n, D + t.offsetX, X + t.offsetY, t.polygon)
Expand All @@ -647,6 +696,7 @@ var apertureScale = 1,
}
var n = [];
D = D.replace(/\r/g, "").replace(/\n/g, "").replace(/%+/g, "%");
// console.log("Gerber D starts with:", D.substring(0, 200)); // Added for debugging input data
for (var f = D.split("%"), l = {
integerDigits: 3,
fractionDigits: 3,
Expand All @@ -670,6 +720,7 @@ var apertureScale = 1,
} else
for (var w = S.split("*"), $ = 0; $ < w.length; $++) {
var N = w[$];
N = N.trim(); // Trim whitespace to handle commands with leading spaces from string splitting
if (0 === N.indexOf("IN") && (p = N.substr(2)),
N = N.replace(/\s/g, ""),
0 === N.indexOf("G01") && (m = "LINEAR"),
Expand Down Expand Up @@ -804,17 +855,24 @@ var apertureScale = 1,
G = y[DD],
G || (G = y.D10)
}
if (N.match(/^((G55)?D0?[1-3]$|X[\-0-9]+|Y[\-0-9]+)/)) {
var XD = N.match(/^(G[0-9]+)?(X([\-0-9]+))?(Y([\-0-9]+))?(D0?[1-3])?$/);
// Updated condition to match coordinate commands more broadly while excluding non-coordinate commands like apertures and format specs
if ((N.match(/D[0-9]+/) || N.match(/X[\-0-9]+/) || N.match(/Y[\-0-9]+/)) && !N.match(/^(G54)?D/) && !N.match(/^FS/) && !N.match(/^AD/)) {
var XD = N.match(/^(G[0-9]+)?(X([\-0-9]+))?(Y([\-0-9]+))?(I([\-0-9]+))?(J([\-0-9]+))?(D[0-9]+)?$/); // Changed regex to match any D followed by digits instead of restricting to D01-D03
// if (!XD) console.log("XD null for N:", N); // Added for debugging regex match failures
var I_val = 0, J_val = 0; // Variables to capture I and J offsets for arc centers
XD[3] && (A = X(XD[3]) * O.a),
XD[5] && (b = X(XD[5]) * O.b),
XD[6] && (x = XD[6]),
x.match(/D0?1/) ? s(P, C, A, b, G) : x.match(/D0?2/) || x.match(/D0?3/) && a(A, b, G),
XD[10] && (x = XD[10]), // Updated index from XD[6] to XD[10] due to added I and J regex groups
XD[7] && (I_val = X(XD[7]) * O.a),
XD[9] && (J_val = X(XD[9]) * O.b),
// Updated call to s() to pass mode, I_val, J_val for arc handling
x.match(/D0?1/) ? s(P, C, A, b, G || y.D10, m, I_val, J_val) : x.match(/D0?2/) || x.match(/D0?3/) && a(A, b, G || y.D10),
P = A,
C = b
}
}
}
// console.log("n.length:", n.length); // Added for debugging number of parsed primitives
return n
},
sampleFile: "G75*G70*%OFA0B0*%%FSLAX24Y24*%%IPPOS*%%LPD*%%AMOC8*5,1,8,0,0,1.08239X$1,22.5*%%ADD10C,0.0160*%%ADD11C,0.0650*%%ADD12R,0.0650X0.0650*%%ADD13R,0.0740X0.0740*%%ADD14C,0.0740*%%ADD15C,0.0520*%%ADD16C,0.0520*%%ADD17OC8,0.0560*%%ADD18C,0.0750*%%ADD19C,0.0660*%%ADD20C,0.0315*%D10*X019633Y004585D02*X019633Y005506D01*X019940Y005813D01*X020247Y005506D01*X020247Y004585D01*X020861Y004585D02*X020861Y005813D01*X020554Y005813D01*X020247Y005506D01*X021475Y005506D02*X021475Y004892D01*X021782Y004585D01*X022395Y004585D01*X022702Y004892D01*X022702Y005506D01*X022395Y005813D01*X021782Y005813D01*X021475Y005506D01*X023316Y005813D02*X024237Y005813D01*X024544Y005506D01*X024544Y004892D01*X024237Y004585D01*X023316Y004585D01*X025158Y004585D02*X025465Y004585D01*X025465Y004892D01*X025158Y004892D01*X025158Y004585D01*X026079Y004892D02*X026079Y005199D01*X026385Y005506D01*X027306Y005506D01*X027920Y006120D02*X028227Y006427D01*X028841Y006427D01*X029148Y006120D01*X029148Y004892D01*X028841Y004585D01*X028227Y004585D01*X027920Y004892D01*X027306Y004585D02*X026385Y004585D01*X026079Y004892D01*X026385Y005506D02*X026079Y005813D01*X026079Y006120D01*X026385Y006427D01*X027306Y006427D01*X027306Y004585D01*X029762Y005506D02*X030069Y005199D01*X030989Y005199D01*X030989Y004585D02*X030989Y006427D01*X030069Y006427D01*X029762Y006120D01*X029762Y005506D01*X031603Y005506D02*X032831Y005506D01*X033445Y005813D02*X034366Y005813D01*X034673Y005506D01*X034673Y004892D01*X034366Y004585D01*X033445Y004585D01*X033445Y006427D01*X035593Y006427D02*X035593Y006734D01*X035593Y005813D02*X035593Y004585D01*X035900Y004585D02*X035286Y004585D01*X036514Y004892D02*X036514Y005506D01*X036821Y005813D01*X037742Y005813D01*X037742Y003971D01*X037742Y004585D02*X036821Y004585D01*X036514Y004892D01*X035900Y005813D02*X035593Y005813D01*X038356Y005506D02*X038356Y004585D01*X039276Y004585D01*X039583Y004892D01*X039276Y005199D01*X038356Y005199D01*X038356Y005506D02*X038663Y005813D01*X039276Y005813D01*X040197Y006120D02*X040197Y005506D01*X040504Y005199D01*X041425Y005199D01*X040811Y005199D02*X040197Y004585D01*X041425Y004585D02*X041425Y006427D01*X040504Y006427D01*X040197Y006120D01*D11*X031005Y012505D03*X031005Y013505D03*X029005Y013505D03*X029005Y012505D03*X029005Y015505D03*X031005Y015505D03*X030505Y022505D03*X029505Y022505D03*X032505Y026005D03*D12*X032505Y024005D03*D13*X026005Y023505D03*D14*X025005Y023505D03*X024005Y023505D03*X023005Y023505D03*X022005Y023505D03*X021005Y023505D03*X021005Y026005D03*X020005Y026005D03*X020505Y027505D03*X022505Y026005D03*X025505Y026005D03*X025505Y027505D03*X027505Y027005D03*X029505Y027005D03*X029505Y024005D03*X027505Y023005D03*X033505Y029505D03*X041505Y029505D03*X026005Y015505D03*X026005Y014505D03*X027505Y012505D03*X022505Y012505D03*D15*X022505Y017245D02*X022505Y017765D01*X023505Y017765D02*X023505Y017245D01*X024505Y017245D02*X024505Y017765D01*X025505Y017765D02*X025505Y017245D01*X026505Y017245D02*X026505Y017765D01*X027505Y017765D02*X027505Y017245D01*X028505Y017245D02*X028505Y017765D01*X029505Y017765D02*X029505Y017245D01*X030505Y017245D02*X030505Y017765D01*X031505Y017765D02*X031505Y017245D01*X032505Y017245D02*X032505Y017765D01*X033505Y017765D02*X033505Y017245D01*X034505Y017245D02*X034505Y017765D01*X034505Y020245D02*X034505Y020765D01*X033505Y020765D02*X033505Y020245D01*X032505Y020245D02*X032505Y020765D01*X031505Y020765D02*X031505Y020245D01*X030505Y020245D02*X030505Y020765D01*X029505Y020765D02*X029505Y020245D01*X028505Y020245D02*X028505Y020765D01*X027505Y020765D02*X027505Y020245D01*X026505Y020245D02*X026505Y020765D01*X025505Y020765D02*X025505Y020245D01*X024505Y020245D02*X024505Y020765D01*X023505Y020765D02*X023505Y020245D01*X022505Y020245D02*X022505Y020765D01*X021505Y020765D02*X021505Y020245D01*X021505Y017765D02*X021505Y017245D01*D16*X038505Y017005D03*X039505Y017005D03*X040505Y017005D03*X041505Y017005D03*X041505Y014005D03*X040505Y014005D03*X039505Y014005D03*X038505Y014005D03*D17*X034505Y013505D03*X034505Y012505D03*X034505Y011505D03*X034505Y010505D03*X033505Y010505D03*X033505Y011505D03*X033505Y012505D03*X033505Y013505D03*X033505Y014505D03*X033505Y015505D03*X034505Y015505D03*X034505Y014505D03*D18*X038105Y013005D03*X041805Y013005D03*X041805Y018005D03*X038105Y018005D03*D19*X023835Y029505D02*X023175Y029505D01*X023175Y030505D02*X023835Y030505D01*X023835Y031505D02*X023175Y031505D01*D20*X023505Y031505D02*X024005Y031505D01*X027505Y028005D01*X027505Y027005D01*X025505Y027505D02*X025505Y026005D01*X023505Y025005D02*X023505Y024505D01*X023005Y024005D01*X023005Y023505D01*X024005Y023505D02*X024005Y023005D01*X023505Y022505D01*X023005Y022505D01*X021505Y021005D01*X021505Y020505D01*X021005Y019505D02*X020505Y020005D01*X020505Y021005D01*X022005Y022505D01*X022005Y023505D01*X022005Y025505D01*X022505Y026005D01*X023505Y025005D02*X034505Y025005D01*X033505Y026005D01*X032505Y026005D01*X031005Y027005D02*X033505Y029505D01*X031005Y027005D02*X029505Y027005D01*X029505Y024005D02*X029505Y022505D01*X029505Y020505D01*X029505Y020005D01*X031005Y018505D01*X035505Y018505D01*X037005Y017005D01*X035505Y015505D01*X034505Y015505D01*X033505Y015505D01*X033505Y014505D02*X034505Y014505D01*X038005Y014505D01*X038505Y014005D01*X038505Y013505D01*X038005Y013005D01*X038105Y013005D01*X038505Y012005D02*X036505Y012005D01*X035005Y013505D01*X034505Y013505D01*X033505Y013505D01*X033505Y012505D02*X034505Y012505D01*X035005Y012505D01*X036505Y011005D01*X038505Y011005D01*X040505Y013005D01*X040505Y014005D01*X039505Y014005D02*X039505Y013005D01*X038505Y012005D01*X038505Y010005D02*X036505Y010005D01*X035005Y011505D01*X034505Y011505D01*X033505Y011505D01*X032005Y011505D01*X027005Y011505D01*X025005Y013505D01*X025005Y015005D01*X025505Y015505D01*X026005Y015505D01*X027005Y015505D01*X028505Y017005D01*X028505Y017505D01*X029505Y017505D02*X029505Y016005D01*X029005Y015505D01*X029005Y013505D01*X029005Y012505D02*X031005Y012505D01*X032005Y011505D01*X033505Y010505D02*X023005Y010505D01*X021505Y012005D01*X021505Y017505D01*X019505Y019505D01*X019505Y022005D01*X021005Y023505D01*X021005Y026005D01*X020005Y026005D02*X020005Y027005D01*X020505Y027505D01*X023505Y029505D02*X023505Y025005D01*X025005Y023505D02*X025005Y023005D01*X023505Y021505D01*X023005Y021505D01*X022505Y021005D01*X022505Y020505D01*X021005Y019505D02*X029005Y019505D01*X029505Y020005D01*X030505Y020505D02*X030505Y022505D01*X037005Y022505D01*X034505Y025005D01*X032505Y024005D02*X029505Y024005D01*X027505Y023005D02*X026505Y022005D01*X026505Y020505D01*X023505Y017505D02*X023505Y013505D01*X022505Y012505D01*X026005Y014505D02*X027505Y013005D01*X027505Y012505D01*X031005Y013505D02*X031005Y015505D01*X030505Y016005D01*X030505Y017505D01*X032005Y019505D02*X031505Y020005D01*X031505Y020505D01*X032505Y020505D02*X032505Y021005D01*X033005Y021505D01*X037005Y021505D01*X040505Y018005D01*X040505Y017005D01*X039505Y017005D02*X039505Y018005D01*X038005Y019505D01*X032005Y019505D01*X037005Y017005D02*X038005Y018005D01*X038105Y018005D01*X038005Y018005D02*X038505Y017505D01*X038505Y017005D01*X041505Y017005D02*X041505Y014005D01*X041505Y013005D01*X041805Y013005D01*X041505Y013005D02*X038505Y010005D01*X034505Y010505D02*X033505Y010505D01*X041505Y017005D02*X041505Y018005D01*X041805Y018005D01*X041505Y018005D02*X037005Y022505D01*X041505Y029505D02*X038505Y032505D01*X023005Y032505D01*X022005Y031505D01*X023005Y030505D01*X023505Y030505D01*M02*"
Expand Down Expand Up @@ -904,4 +962,4 @@ var apertureScale = 1,
// diameter: .3,
// angle: 45,
// depth: .2
// }];
// }];