You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
11 KiB
Plaintext
382 lines
11 KiB
Plaintext
15 years ago
|
#usage "<qt><b>Copy Wire (Polygon Wire) to any layer</b><p>"
|
||
|
"This ULP copies copper wire and/or polygon from layer (1 or 16) of selected signals into "
|
||
|
"the solderstop layers or any layer in order to keep it free from solder stop layer.<p>"
|
||
|
"Use:<br><nobr>"
|
||
|
"run copy-wire-to-solder-mask.ulp [signalname] [signalname] <br>"
|
||
|
"run copy-wire-to-solder-mask.ulp $nameoff$<br>"
|
||
|
"run copy-wire-to-solder-mask.ulp -p [signalname] [signalname]<br>"
|
||
|
"run copy-wire-to-solder-mask.ulp +p [signalname] [signalname]<br>"
|
||
|
"run copy-wire-to-solder-mask.ulp -p -f [signalname] [signalname]<br>"
|
||
|
"run copy-wire-to-solder-mask.ulp +p +f [signalname] [signalname]<br>"
|
||
|
"$nameoff$ switches off the checking of net names<p>"
|
||
|
"Options are case sensitive.<br>"
|
||
|
"<b>$nameoff$</b> copy all signals.<br>"
|
||
|
"<b>-p</b> copies also polygons.<br>"
|
||
|
"<b>+p</b> copies only polygons.<br>"
|
||
|
"<b>-f</b> copies only polygon contour as polygon.<br>"
|
||
|
"<b>-f</b> copies polygon contour and filling as wire.<br>"
|
||
|
"</nobr>"
|
||
|
"<author>Author: support@cadsoft.de</author></qt>"
|
||
|
|
||
|
// THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED.
|
||
|
|
||
|
string Version = "ULP-Version: 1.5"; // 2008-04-23 check is a polygon placed
|
||
|
// changed menu to copy to any layer
|
||
|
// 2009-01-28 check polygon filling on orphan alf@cadsoft.de
|
||
|
// 2009-04-23 check menu parameter
|
||
|
// 2009-06-30 correct polygon export
|
||
|
|
||
|
|
||
|
int NameOff = 0; // 0 = copy by signal name
|
||
|
// 1 = copy without signal name (all)
|
||
|
int PolygonOn = 0; // copy also polygon
|
||
|
int onlyPolygon = 0;
|
||
|
int fillPolygon = 0; // copy only polygon contour or copy polygon filling as wire 2006.01.20 alf
|
||
|
int Player[];
|
||
|
string poly[];
|
||
|
int cntp = 0;
|
||
|
string isRatsnest;
|
||
|
string isLayer = "Top/Bottom"; // default layer
|
||
|
int isLayerNb = 0;
|
||
|
string toLayer = "t/bStop"; // default do Stop-Layer
|
||
|
int Lused[]; // 2009-04-23
|
||
|
|
||
|
string signals[] = { "" };
|
||
|
string chsignals[] = { "" };
|
||
|
int chngsig = 0;
|
||
|
int lastSigCh = -1;
|
||
|
int decs;
|
||
|
|
||
|
int index[];
|
||
|
int x1[], y1[], x2[], y2[], layer[];
|
||
|
int Wwidth[];
|
||
|
int n = 1;
|
||
|
|
||
|
string cmd;
|
||
|
string c;
|
||
|
|
||
|
int nbIslayer;
|
||
|
int nbTolayer;
|
||
|
|
||
|
int test = 0; // 2009-06-30 for test menu
|
||
|
|
||
|
|
||
|
// *************************************
|
||
|
string check(void) { // 2009-04-23 alf@cadsoft.de
|
||
|
int isLfound = 0;
|
||
|
int toLfound = 0;
|
||
|
nbIslayer = strtol(isLayer);
|
||
|
nbTolayer = strtol(toLayer);
|
||
|
|
||
|
if (isLayer == "Top/Bottom") isLfound = -1;
|
||
|
else {
|
||
|
board(B) B.layers(L) {
|
||
|
if (nbIslayer == L.number || isLayer == L.name) {
|
||
|
isLfound = L.number;
|
||
|
nbIslayer = L.number;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (toLayer == "t/bStop") toLfound = -1;
|
||
|
else {
|
||
|
board(B) B.layers(L) {
|
||
|
if (nbTolayer == L.number || toLayer == L.name) {
|
||
|
toLfound = L.number;
|
||
|
nbTolayer = L.number;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (isLfound == -1);
|
||
|
else if (!isLfound) return "!Select a available layer number or name for <i>Copy layer</i>.";
|
||
|
else if (!Lused[isLfound]) return "!Not used layer <i>Copy layer</i> " + isLayer + ".";
|
||
|
|
||
|
if (toLfound == -1);
|
||
|
else if (!toLfound) return "!Select a available layer number or name for <i>to layer</i>.";
|
||
|
else if (!Lused[toLfound]) return "!Not used layer <i>to layer</i> " + toLayer + ".";
|
||
|
|
||
|
if (!NameOff && lastSigCh < 0 ) {
|
||
|
return "!No signal selected";
|
||
|
}
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
|
||
|
int found(string fnam) {
|
||
|
int fnd = 0;
|
||
|
do {
|
||
|
if (chsignals[fnd] == fnam) {
|
||
|
return 1;
|
||
|
break;
|
||
|
}
|
||
|
++fnd;
|
||
|
} while (chsignals[fnd]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void changeLayer(int l) {
|
||
|
if (toLayer == "t/bStop") {
|
||
|
if (l == 1) sprintf(c, "CHANGE LAYER 29;\n");
|
||
|
if (l == 16) sprintf(c, "CHANGE LAYER 30;\n");
|
||
|
cmd+= c;
|
||
|
}
|
||
|
if (isLayer == "Top/Bottom") { // 2009-06-30
|
||
|
if (l == 1) {
|
||
|
sprintf(c, "CHANGE LAYER 29;\n");
|
||
|
cmd+= c;
|
||
|
}
|
||
|
if (l == 16) {
|
||
|
sprintf(c, "CHANGE LAYER 30;\n");
|
||
|
cmd+= c;
|
||
|
}
|
||
|
}
|
||
|
else if (l == isLayerNb) {
|
||
|
sprintf(c, "CHANGE LAYER %s;\n", toLayer); // 2009-04-23
|
||
|
cmd+= c;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
int delfromList(int selct) {
|
||
|
if (lastSigCh >= 0) {
|
||
|
lastSigCh--;
|
||
|
for (int r = selct; r <= lastSigCh; r++) {
|
||
|
chsignals[r] = chsignals[r + 1];
|
||
|
}
|
||
|
chsignals[lastSigCh + 1] = "";
|
||
|
}
|
||
|
return selct;
|
||
|
}
|
||
|
|
||
|
|
||
|
void AddList(string SigName) {
|
||
|
int nofound = 1;
|
||
|
for (int r = 0; r <= lastSigCh; r++) {
|
||
|
if (chsignals[r] == SigName) {
|
||
|
nofound = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (nofound) {
|
||
|
lastSigCh++;
|
||
|
if (lastSigCh > 0) {
|
||
|
for (int x = lastSigCh; x > 0; x--) {
|
||
|
chsignals[x] = chsignals[x - 1];
|
||
|
}
|
||
|
}
|
||
|
chsignals[0] = SigName;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void AddArgument(int n) {
|
||
|
do {
|
||
|
AddList(strupr(argv[n]));
|
||
|
n++;
|
||
|
} while(argv[n]);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void menue() {
|
||
|
if (argc > 1) {
|
||
|
if (argv[1] == "-p" || argv[1] == "+p" || argv[1] == "$nameoff$") {
|
||
|
if (argv[1] == "-p") PolygonOn = 1;
|
||
|
if (argv[1] == "+p") onlyPolygon = 1;
|
||
|
if (argv[2] == "-f") fillPolygon = 0; // 2006.01.20 alf
|
||
|
if (argv[2] == "+f") fillPolygon = 1;
|
||
|
if (argv[1] == "$nameoff$") { NameOff = 1; AddArgument(2); }
|
||
|
else if (argv[2] == "$nameoff$") { NameOff = 1; AddArgument(3); }
|
||
|
else AddArgument(2);
|
||
|
if (argv[2] == "$nameoff$") { NameOff = 1; AddArgument(3); }
|
||
|
else if (argv[3] == "$nameoff$") { NameOff = 1; AddArgument(4); }
|
||
|
else AddArgument(3);
|
||
|
}
|
||
|
else AddArgument(1);
|
||
|
}
|
||
|
else {
|
||
|
string slist[];
|
||
|
int Result = dlgDialog("Copy wire to layer") {
|
||
|
dlgLabel(Version);
|
||
|
dlgHBoxLayout dlgSpacing(250);
|
||
|
dlgCheckBox("Copy &all (without signal name)", NameOff);
|
||
|
dlgSpacing(10);
|
||
|
dlgStretch(0);
|
||
|
dlgLabel("Add &signal to list");
|
||
|
dlgComboBox(signals, chngsig) { AddList(signals[chngsig]); dlgRedisplay();}
|
||
|
dlgSpacing(30);
|
||
|
dlgLabel("&Delete signal from list");
|
||
|
dlgComboBox(chsignals, decs) decs = delfromList(decs);
|
||
|
dlgGroup("Polygon") {
|
||
|
dlgCheckBox("Copy &polygon with signal name", PolygonOn);
|
||
|
dlgCheckBox("Copy &only polygons", onlyPolygon);
|
||
|
dlgHBoxLayout {
|
||
|
dlgRadioButton("Copy only &contour", fillPolygon);
|
||
|
dlgRadioButton("Copy with &filling", fillPolygon);
|
||
|
}
|
||
|
}
|
||
|
dlgHBoxLayout {
|
||
|
dlgLabel("Copy &layer ");
|
||
|
dlgStringEdit(isLayer);
|
||
|
dlgLabel(" &to layer ");
|
||
|
dlgStringEdit(toLayer);
|
||
|
dlgStretch(1);
|
||
|
}
|
||
|
dlgHBoxLayout {
|
||
|
dlgPushButton("+OK") {
|
||
|
string error = check(); // 2009-04-23 alf@cadsoft.de
|
||
|
if(error) dlgMessageBox(error);
|
||
|
else dlgAccept();
|
||
|
}
|
||
|
dlgPushButton("-Cancel") dlgReject();
|
||
|
dlgStretch(1);
|
||
|
dlgPushButton("&Help") dlgMessageBox(usage, "OK");
|
||
|
}
|
||
|
dlgStretch(0);
|
||
|
};
|
||
|
if (Result == 0) exit (0);
|
||
|
}
|
||
|
isLayerNb = nbIslayer; // 2009-04-23
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// main
|
||
|
if (board) board(B) {
|
||
|
B.layers(L) Lused[L.number] = L.used;
|
||
|
isRatsnest = "! Start RATSNEST first!";
|
||
|
int cntPoly = 0;
|
||
|
B.signals(S) {
|
||
|
S.polygons(P) {
|
||
|
cntPoly++;
|
||
|
P.fillings(F) { // check if run RATSNEST
|
||
|
isRatsnest = "";
|
||
|
break;
|
||
|
}
|
||
|
if (isRatsnest) { // check a orphan 2009-01-28 alf@cadsoft.de
|
||
|
P.wires(W) {
|
||
|
sprintf(isRatsnest, "Start RATSNEST and check polygon on (%.4f %.4f) mm!", u2mm(W.x1), u2mm(W.y1) );
|
||
|
dlgMessageBox(isRatsnest, "OK");
|
||
|
sprintf(isRatsnest, "GRID MM;\nWIN (%.4f %.4f);\nGRID LAST;\n", u2mm(W.x1), u2mm(W.y1) );
|
||
|
exit(isRatsnest);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (cntPoly) {
|
||
|
if (isRatsnest) {
|
||
|
dlgMessageBox(isRatsnest, "OK");
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
int s = 0;
|
||
|
B.signals(S) {
|
||
|
signals[s] = S.name;
|
||
|
s++;
|
||
|
}
|
||
|
menue();
|
||
|
|
||
|
sprintf(c, "GRID MM;\nSET WIRE_BEND 2;\nSET UNDO OFF;\n");
|
||
|
cmd+= c;
|
||
|
B.signals(S) {
|
||
|
if (found(S.name) || NameOff || onlyPolygon) {
|
||
|
if (!onlyPolygon) {
|
||
|
S.wires(W) {
|
||
|
if ((isLayer == "Top/Bottom" && (W.layer == 1 || W.layer == 16)) || isLayerNb == W.layer) { // 2009-04-23 alf
|
||
|
x1[n] = W.x1;
|
||
|
y1[n] = W.y1;
|
||
|
x2[n] = W.x2;
|
||
|
y2[n] = W.y2;
|
||
|
Wwidth[n] = W.width;
|
||
|
layer[n] = W.layer;
|
||
|
++n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( (PolygonOn && NameOff) || (onlyPolygon && !NameOff && found(S.name)) || (PolygonOn && !NameOff && found(S.name)) ) {
|
||
|
S.polygons(POL) {
|
||
|
if (isLayer && (POL.layer == 1 || POL.layer == 16) || isLayerNb == POL.layer) { // 2009-06-30 alf
|
||
|
string p;
|
||
|
int startx, starty;
|
||
|
int first = 1;
|
||
|
Player[cntp] = POL.layer;
|
||
|
POL.contours(W) {
|
||
|
if (first) {
|
||
|
first = 0;
|
||
|
startx = W.x1;
|
||
|
starty = W.y1;
|
||
|
sprintf(poly[cntp], "WIRE %.4f (%.4f %.4f) (%.4f %.4f)", // 2009-06-30
|
||
|
u2mm(W.width),
|
||
|
u2mm(W.x1), u2mm(W.y1),
|
||
|
u2mm(W.x2), u2mm(W.y2)
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
sprintf(p, " (%.4f %.4f)", u2mm(W.x2), u2mm(W.y2) );
|
||
|
poly[cntp] += p;
|
||
|
if (startx == W.x2 && starty == W.y2) {
|
||
|
sprintf(p, " (%.4f %.4f);\n", u2mm(startx), u2mm(starty) );
|
||
|
poly[cntp] += p;
|
||
|
cntp++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (fillPolygon) { // Polygon filling with wire 2009-06-30
|
||
|
POL.fillings(W) {
|
||
|
x1[n] = W.x1;
|
||
|
y1[n] = W.y1;
|
||
|
x2[n] = W.x2;
|
||
|
y2[n] = W.y2;
|
||
|
Wwidth[n] = W.width;
|
||
|
layer[n] = W.layer;
|
||
|
++n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
sort(n, index, layer);
|
||
|
int dl = 0;
|
||
|
for (int i = 1; i < n; i++) {
|
||
|
if(dl != layer[index[i]]) {
|
||
|
dl = layer[index[i]];
|
||
|
changeLayer(dl);
|
||
|
}
|
||
|
sprintf(c, "WIRE %.4f (%.4f %.4f) (%.4f %.4f);\n", u2mm(Wwidth[index[i]]),
|
||
|
u2mm(x1[index[i]]), u2mm(y1[index[i]]), u2mm(x2[index[i]]), u2mm(y2[index[i]]) );
|
||
|
cmd+= c;
|
||
|
}
|
||
|
sort(cntp, index, Player);
|
||
|
for ( i = 0; i < cntp; ++i) {
|
||
|
if(dl != Player[index[i]]) {
|
||
|
dl = Player[index[i]];
|
||
|
changeLayer(dl);
|
||
|
}
|
||
|
sprintf(c, "WIRE %.4f (%.4f %.4f) (%.4f %.4f);\n", u2mm(Wwidth[index[i]]),
|
||
|
u2mm(x1[index[i]]), u2mm(y1[index[i]]), u2mm(x2[index[i]]), u2mm(y2[index[i]]) );
|
||
|
cmd+= poly[index[i]];
|
||
|
}
|
||
|
sprintf(c, "SET UNDO ON;\nGRID LAST;\n");
|
||
|
cmd+= c;
|
||
|
if (test) { // 2009-06-30
|
||
|
dlgDialog("test") {
|
||
|
dlgTextEdit(cmd);
|
||
|
dlgHBoxLayout {
|
||
|
dlgPushButton("OK") dlgAccept();
|
||
|
dlgPushButton("Cancel") { dlgReject(); exit(-9); }
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
exit (cmd);
|
||
|
}
|
||
|
|
||
|
else dlgMessageBox("! Start this ULP in a Board", "OK");
|
||
|
|