#usage "Snap objects in a board\n" "

" "Snaps components, wires and vias of the current " "board to a given grid. " "If 'Show script' is checked, you can edit the MOVE commands " "before they are executed. So you are able to exclude certain " "elements from the snap procedure." "

" "Author: support@cadsoft.de" // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED real GridDist = 50.0; enum {unitINCH, unitMIL, unitMM, unitMIC}; string h, cmd = ""; int unit = unitMIL; // predefined unit, can be changed to unitMM, unitINCH, unitMIC int show_script = 1; // predefined value for button "Show script" int Result; string Status = ""; // 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; } 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; } int n = 0, x[], y[], l[], UsedLayers[]; int isNew(int X, int Y, int L) { for (int i = 0; i < n; i++) { if (x[i] == X && y[i] == Y && (l[i] == L || l[i] == LAYER_VIAS )) return 0; } return 1; } void Move(int Layer) { if (UsedLayers[Layer]) { h = ""; sprintf(h, "DISPLAY NONE %d;\n", Layer); cmd += h; // Snap the signal wires and vias: for (int i = 0; i < n; i++) { if (l[i] == Layer && (u2unit(x[i]) != snap(x[i]) || u2unit(y[i]) != snap(y[i]))) { h = ""; sprintf(h, "MOVE (%f %f) (%f %f);\n", u2unit(x[i]), u2unit(y[i]), snap(x[i]), snap(y[i])); cmd += h; } } } } void snap_to_grid (void) { board(B) { // Collect all (unique!) signal wire and via coordinates: B.signals(S) { Status = "Signal: "+S.name; dlgRedisplay(); S.vias(V) { UsedLayers[LAYER_VIAS] = 1; x[n] = V.x; y[n] = V.y; l[n] = LAYER_VIAS; n++; } S.wires(W) { UsedLayers[W.layer] = 1; if (isNew(W.x1, W.y1, W.layer)) { x[n] = W.x1; y[n] = W.y1; l[n] = W.layer; n++; } if (isNew(W.x2, W.y2, W.layer)) { x[n] = W.x2; y[n] = W.y2; l[n] = W.layer; n++; } } } // Remember the active layers: int ActiveLayers[]; B.layers(L) { ActiveLayers[L.number] = L.visible; } 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; } // Go through the used layers (this avoids problems with wires on different // layers that are selected at the same coordinates): for (int u = LAYER_TOP; u <= LAYER_BOTTOM; u++) Move(u); Move(LAYER_VIAS); // Reactivate the active layers: h = ""; sprintf(h, "DISPLAY"); cmd += h; for (int j = 1; j < 256; j++) if (ActiveLayers[j]) { h = ""; sprintf(h, " %d", j); cmd += h; } h = ""; sprintf(h, ";\n"); cmd += h; // Snap the elements: B.elements(E) { Status = "Element: "+E.name; dlgRedisplay(); if (u2unit(E.x) != snap(E.x) || u2unit(E.y) != snap(E.y)) { if (show_script) { h = ""; sprintf(h, "SHOW %s;\n", E.name); cmd += h; } h = ""; sprintf(h, "MOVE %s (%f %f);\n", E.name, snap(E.x), snap(E.y)); cmd += h; } } h = ""; sprintf(h, "GRID LAST;\n"); cmd += h; } } //---- main ---------------------------------------------------------------------- if (project.board && project.schematic) { project.board(B) { project.schematic(S) { dlgMessageBox("Good -- you have both open!\nBoard = " + B.name + ", Schematic = " + S.name); B.elements(E) { if (E.package.name == "2,54/0,8") { h = ""; sprintf(h, "%s@%d, %d", E.name, E.x, E.y); dlgMessageBox(h); } } } } } exit(0); if (!board) { dlgMessageBox(usage + "


ERROR: No board!

\nThis program can only work in the board editor."); exit(1); } dlgDialog("Snap Packages/Wires/Vias") { 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_to_grid(); dlgAccept(); } dlgPushButton("-&Cancel") exit(0); } dlgSpacing(7); } } }; Result = 1; if (show_script) { Result = dlgDialog("Edit Commands") { dlgVBoxLayout { dlgLabel("Edit only if you are sure what you do!"); dlgTextEdit(cmd); } dlgHBoxLayout { dlgPushButton("+Execute") {snap_to_grid(); 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); exit(cmd);