#usage "Snap parts, junctions, nets in schematic
\n"
"This program snaps parts, junctions and nets of the current "
"schematic to a given grid. "
"If 'Show script' is checked, you can edit the MOVE commands "
"before they are executed.
"
"The program runs in three steps: parts, junctions, nets. "
"After each step you can terminate the program. So, if you "
"only want to move the parts, quit after the first step.
"
"Note: with EAGLE Version 4.0 you need write permission in the library directory.
"
"Author: support@cadsoft.de"
real GridDist = 100.0;
enum {unitINCH, unitMIL, unitMM, unitMIC};
string h, cmd = "";
int unit = unitMIL; // predefined unit, can be changed to unitMM, unitINCH, unitMIC
int show_script;
int Result;
string Status = "";
enum {PART_INSTANCE, JUNCTION_INSTANCE , NET_INSTANCE, NET_INSTANCE2};
int run_instance = PART_INSTANCE;
int n;
real x[], y[]; // previous move coords
int version_4_0 = 0;
// get project path, if in board or schematic, otherwise library path
string get_project_path() {
string s = "", p = "";;
if (library) { library(L) s = L.name;}
if (board) { board(B) s = B.name;}
if (schematic){ schematic(S) s = S.name;}
char c = '/';
int pos = strrchr(s, c);
if (pos >= 0) {
p = strsub(s, 0, pos + 1);
}
return p;
}
string get_ulp_name(void) {
string s = strsub(argv[0], 0, strlen(argv[0])-4);
string p = s;
char c = '/';
int pos = strrchr(s, c);
if (pos >= 0) {
p = strsub(s, pos + 1);
}
return p;
}
real u2unit(int u) {
if (unit == unitMIL) return u2mil(u);
if (unit == unitMM) return u2mm(u);
if (unit == unitINCH) return u2inch(u);
if (unit == unitMIC) return u2mic(u);
}
real snap(int n) { // returns next grid point
return round(u2unit(n) / GridDist) * GridDist;
}
void save_dialog(string cm) {
Result = dlgDialog("Edit Commands") {
dlgVBoxLayout {
dlgLabel("Edit only if you are sure what you do!");
dlgTextEdit(cmd);
}
dlgHBoxLayout {
dlgPushButton("+Execute") dlgAccept();
dlgPushButton("-Quit") dlgReject();
dlgPushButton("+Save") {
string dest = dlgFileSave("Save Script File", get_project_path()+"snap.scr", "*.scr");
if (dest != "") output(dest, "wt") {printf(cmd);}
}
}
};
if (!Result) exit(0);
}
int is_new(void) {
int i;
if (n == 0) return 1;
for (i = 0; i < n; i++) {
if (x[n] == x[i] && y[n] == y[i]) {
return(0);
}
}
return 1;
}
// -------------------------------------------------------------------------------
void snap_schematic (void) {
if (unit == unitMIL) {h = ""; sprintf(h, "GRID MIL FINEST;\n"); cmd += h;}
if (unit == unitMM) {h = ""; sprintf(h, "GRID MM FINEST;\n"); cmd += h;}
if (unit == unitINCH) {h = ""; sprintf(h, "GRID INCH FINEST;\n"); cmd += h;}
if (unit == unitMIC) {h = ""; sprintf(h, "GRID MIC FINEST;\n"); cmd += h;}
if (run_instance == PART_INSTANCE) {
sheet(SH) {
h = ""; sprintf(h, "DISPLAY NONE SYMBOL;\n"); cmd += h;
SH.parts(P) {
Status = "Part: "+P.name; dlgRedisplay();
P.instances(I) {
if (u2unit(I.x) != snap(I.x) || u2unit(I.y) != snap(I.y)) {
h = ""; sprintf(h, "MOVE (%f %f) (%f %f);\n", u2unit(I.x), u2unit(I.y), snap(I.x), snap(I.y)); cmd += h;
}
}
}
}
h = ""; sprintf(h, "GRID LAST;\nDISPLAY ALL -PINS;\n"); cmd += h;
if (show_script) save_dialog(cmd);
if (!version_4_0) {
exit(cmd);
}
else {
output(get_project_path()+"$$$.scr", "wt") printf("%s", cmd);
cmd = "RUN "+get_ulp_name()+" 1"; // call junction instance
h = ""; sprintf(h, " %d", show_script); cmd += h;
exit("SCRIPT "+get_project_path()+"$$$.scr;\n"+cmd);
}
}
//********* 2nd run
if (run_instance == JUNCTION_INSTANCE) {
sheet(SH) {
h = ""; sprintf(h, "DISPLAY NONE NETS;\n"); cmd += h;
SH.nets(N) {
Status = "Net: "+N.name; dlgRedisplay();
N.segments(SEG) {
SEG.junctions(J) {
if (u2unit(J.x) != snap(J.x) || u2unit(J.y) != snap(J.y)) {
h = ""; sprintf(h, "MOVE (%f %f) (%f %f);\n", u2unit(J.x), u2unit(J.y), snap(J.x), snap(J.y)); cmd += h;
}
}
}
}
}
h = ""; sprintf(h, "GRID LAST;\nDISPLAY ALL -PINS;\n"); cmd += h;
if (show_script) save_dialog(cmd);
if (!version_4_0) {
exit(cmd);
}
else {
output(get_project_path()+"$$$.scr", "wt") printf("%s", cmd);
cmd = "RUN "+get_ulp_name()+" 2"; // call net instance
h = ""; sprintf(h, " %d", show_script); cmd += h;
exit("SCRIPT "+get_project_path()+"$$$.scr;\n"+cmd);
}
}
//********* 3rd run
x[0] = 0; y[0] = 0; n = 0;
if (run_instance == NET_INSTANCE) {
sheet(SH) {
h = ""; sprintf(h, "DISPLAY NONE NETS;\n"); cmd += h;
SH.nets(N) {
Status = "Net: "+N.name; dlgRedisplay();
N.segments(SEG) {
SEG.wires(W) {
x[n] = u2unit(W.x1); y[n] = u2unit(W.y1);
if (is_new() && (u2unit(W.x1) != snap(W.x1) || u2unit(W.y1) != snap(W.y1))) {
h = ""; sprintf(h, "MOVE (%f %f) (%f %f);\n", u2unit(W.x1), u2unit(W.y1), snap(W.x1), snap(W.y1)); cmd += h;
n++;
}
}
}
}
}
sheet(SH) {
h = ""; sprintf(h, "DISPLAY NONE NETS;\n"); cmd += h;
SH.nets(N) {
Status = "Net: "+N.name; dlgRedisplay();
N.segments(SEG) {
SEG.wires(W) {
x[n] = u2unit(W.x2); y[n] = u2unit(W.y2);
if (is_new() && (u2unit(W.x2) != snap(W.x2) || u2unit(W.y2) != snap(W.y2))) {
h = ""; sprintf(h, "MOVE (%f %f) (%f %f);\n", u2unit(W.x2), u2unit(W.y2), snap(W.x2), snap(W.y2)); cmd += h;
n++;
}
}
}
}
}
h = ""; sprintf(h, "GRID LAST;\nDISPLAY ALL -PINS;\n"); cmd += h;
if (show_script) save_dialog(cmd);
if (!version_4_0) {
exit(cmd);
}
else {
output(get_project_path()+"$$$.scr", "wt") printf("%s", cmd);
cmd = "RUN "+get_ulp_name()+" 4";
h = ""; sprintf(h, " %d", show_script); cmd += h;
exit("SCRIPT "+get_project_path()+"$$$.scr;\n"+cmd);
}
}
}
//---- main ----------------------------------------------------------------------
if ((EAGLE_VERSION == 4 && EAGLE_RELEASE == 0) || (EAGLE_VERSION == 3 && EAGLE_RELEASE >96))
version_4_0 = 1; // used for workaround
if (!schematic) {
dlgMessageBox(usage + "
ERROR: No schematic!\nThis program can only work in the schematic editor.");
exit(1);
}
show_script = strtol(argv[2]);
if (argv[1] == "") run_instance = PART_INSTANCE;
if (argv[1] == "1") run_instance = JUNCTION_INSTANCE;
if (argv[1] == "2") run_instance = NET_INSTANCE;
if (argv[1] == "3") run_instance = NET_INSTANCE2;
if (argv[1] == "4") {dlgMessageBox("Snap finished", "&OK"); exit(0);}
dlgDialog("Snap") {
if (run_instance == PART_INSTANCE) {
Status = " It is strongly recommended to use only 100 mil grid!
Click Snap to snap parts";
dlgRedisplay();
}
if (run_instance == JUNCTION_INSTANCE) {
Status = " Click Snap to snap Junctions";
dlgRedisplay();
}
if (run_instance == NET_INSTANCE) {
Status = " Click Snap to snap starting point of nets";
dlgRedisplay();
}
if (run_instance == NET_INSTANCE2) {
Status = " Click Snap to snap ending point of nets";
dlgRedisplay();
}
dlgHBoxLayout {
dlgHBoxLayout {
dlgGroup("Unit") {
dlgRadioButton("&inch", unit);
dlgRadioButton("&mil", unit);
dlgRadioButton("&mm", unit);
dlgRadioButton("&mic", unit);
dlgSpacing(20);
dlgLabel("Snap grid ");
dlgRealEdit(GridDist, 0.0001, 1000);
}
}
dlgSpacing(10);
dlgVBoxLayout {
dlgSpacing(10);
dlgCheckBox("&Show script", show_script);
dlgLabel(Status, 1);
dlgHBoxLayout {
dlgPushButton("+&Snap") {Status = "Busy...";
dlgRedisplay();
snap_schematic();
}
dlgPushButton("-&Cancel") exit(0);
}
dlgSpacing(7);
}
}
};