#require 4.1105 #usage "Draw outlines and drills/holes centers.\n" "
" "Generates necessary patterns for Roland DG MDX-15/20 on new layers" "
" "Usage: RUN outlines_drills.ulp " "
" "CAUTION:" "
" " New layer number must be one of 100..200, though the name is arbitrary. This program overwites existing data of a layer ( of which number 100..200) with no warnings. When specify the range in diameter of drilles/holes, Min, Max valuses must be over 0mm and not over 100mm." "
" "This program is based on outlines.ulp by cadsoft." "
"
"
\n" + Details); exit(1); } void Error(string Message, string Details) { dlgMessageBox("" + "ERROR: " + Message + "
\n" + Details); } void Contents(string Message, string Details) { dlgMessageBox("" + "Check: " + Message + "
\n" + Details); } // Board check if (!board) Fatal("No board!", "This program can only work in the board editor."); // Effective in the second routine if (argv[1]) { Process = argv[1]; if (argv[2]) { Width = strtod(argv[2]); if (Width <= 0) Fatal("Illegal Width: " + argv[2], "The Width must be greater than zero."); if (argv[3]) { Layer = strtol(argv[3]); if (Layer < 0 || Layer > 16) Fatal("Illegal layer: " + argv[3], "The object layer must be one of 1..16 or 0 to use the current layer."); if (argv[4]) { FileName = argv[4]; } } } } if (argv[6]) { myLNumber = strtol(argv[6]); if (argv[7]) { myLName =argv[7]; if (argv[8]) { Flag_MillHoles =strtol(argv[8]); if (argv[9]) { Flag_SpecifiedRange = strtol(argv[9]); } } } } if (argv[10]) { minDiam =strtod(argv[10]); if (argv[11]) { maxDiam =strtod(argv[11]); } } if (!FileName) board(B) FileName = filesetext(B.name, DefaultSuffix); // Different output Processes enum { proOutlines = 1, proDrill_Points }; string ProcessNames[] = {"Select a Drawing", "Outlines", "Drills/Holes" }; int SelectedProcess; // 1 or 2 void ProcessInit() { // Do anything necessary to initialize the output Process switch (SelectedProcess) { case proOutlines: printf("layer %d %s;\nset wire_bend 2; grid mm; change width %f;\n", myLNumber, myLName, Width); break; case proDrill_Points: break; } } void ProcessDraw(int x1, int y1, int x2, int y2, int state) { switch (SelectedProcess) { case proOutlines: if (state == 0) printf("wire (%f %f) (%f %f)", u2mm(x1), u2mm(y1), u2mm(x2), u2mm(y2)); else { printf(" (%f %f)", u2mm(x2), u2mm(y2)); if (state == 2) printf(";\n"); } break; case proDrill_Points: if (state == 0) printf("PU; PA %f %f; PD; PA %f %f;", u2mm(x1), u2mm(y1), u2mm(x2), u2mm(y2)); else { printf(" PA %f %f", u2mm(x2), u2mm(y2)); if (state == 2) printf("\n"); } break; } } void ProcessEnd(void) { // Do anything necessary to end output to the Process switch (SelectedProcess) { case proOutlines: break; case proDrill_Points: printf("PU;\n"); break; } } // The actual outlines generator // string OutlinesSignalName = "_OUTLINES_"; string Pass2 = "PASS_2"; int InPass2 = argv[5] == Pass2; void GenerateOutlines(void) { board(B) { real f = 20, // mm frame x1 = u2mm(B.area.x1) - f, y1 = u2mm(B.area.y1) - f, x2 = u2mm(B.area.x2) + f, y2 = u2mm(B.area.y2) + f; B.signals(S) { if (S.name == OutlinesSignalName) Fatal("There is already a signal named " + OutlinesSignalName + " in this board!", "Please make sure that there is no such signal in this board."); } string Cmd; sprintf(Cmd, "grid mm;\n" "window fit;\n" "change isolate 0;\n" "change rank 6;\n" "change pour solid;\n" "change orphans on;\n" "layer %d;\n" "polygon %s %f (%f %f) (%f %f) (%f %f) (%f %f) (%f %f);\n" "ratsnest;\n" , Layer, OutlinesSignalName, Width, x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); string Cmd2; sprintf(Cmd2, "run '%s' '%s' '%f' '%d' '%s' '%s' '%d' '%s' '%d' '%d' '%f' '%f';",argv[0], Process, Width, Layer, FileName, Pass2, myLNumber, myLName, Flag_MillHoles, Flag_SpecifiedRange, minDiam, maxDiam); Cmd += Cmd2; exit(Cmd); } } void WriteOutlines(void) { board(B) { output(FileName) { string Cmd; B.signals(S) { if (S.name == OutlinesSignalName) { S.polygons(P) { int x1 = INT_MAX, y1 = INT_MAX, x2 = INT_MIN, y2 = INT_MIN; int x0, y0, first = 1; int FrameWire; int State; P.wires(W) { x1 = min(x1, W.x1); x2 = max(x2, W.x1); y1 = min(y1, W.y1); y2 = max(y2, W.y1); } ProcessInit(); P.contours(W) { if (first) { // a new partial polygon is starting x0 = W.x1; y0 = W.y1; FrameWire = (x1 == x0 || x2 == x0) && (y1 == y0 || y2 == y0); State = 0; first = 0; } else if (W.x2 == x0 && W.y2 == y0) { // this was the last wire of the partial polygon, // so the next wire (if any) will be the first wire // of the next partial polygon State = 2; first = 1; } else State = 1; if (!FrameWire) ProcessDraw(W.x1, W.y1, W.x2, W.y2, State); } ProcessEnd(); sprintf(Cmd, "delete (%f %f) (%f %f); window fit;\n" "LAYER %d %s ;\n" "display NONE %d ;\n" "change layer %d ;\n" "GROUP ALL ;\n" "delete (> %f %f) ;\n" ";SCR '" + FileName + "';\n" "grid inch ;\n" "SET CONFIRM YES ;\n" "REMOVE %s ;\n" "SET CONFIRM OFF ;\n" , u2mm(x1), u2mm(y1), u2mm(x2), u2mm(y2), myLNumber,myLName, myLNumber, myLNumber, u2mm(x1), u2mm(y1), FileName); } break; } } exit(Cmd); } } } // Draw a circle or a drill/hole center point void draw_circle(int x, int y, int drill) { real widthLocal; real radius; string h; real DrillingDiam = u2mm(drill); // All range drilles and holes if (!Flag_SpecifiedRange){ if (DrillingDiam <= MillerDiam || !Flag_MillHoles){ widthLocal = 0.01; sprintf(h, "change width %f\n",widthLocal); cmd_drill += h; sprintf(h, "wire (%f %f) (%f %f) ;\n", u2mm(x)-widthLocal/2, u2mm(y), u2mm(x) + widthLocal/2, u2mm(y) ); } else{ radius = DrillingDiam/2-MillerDiam/2; //widthLocal = MillerDiam; widthLocal = 0.01; sprintf(h, "circle %f (%f %f) (%f %f) ;\n", widthLocal, u2mm(x), u2mm(y), u2mm(x) + radius, u2mm(y) ); } }; // Specified range if (Flag_SpecifiedRange) { if (DrillingDiam >= minDiam && DrillingDiam <= maxDiam) { if (DrillingDiam <= MillerDiam || !Flag_MillHoles){ widthLocal = 0.01; sprintf(h, "change width %f\n",widthLocal); cmd_drill += h; sprintf(h, "wire (%f %f) (%f %f) ;\n", u2mm(x)-widthLocal/2, u2mm(y), u2mm(x) + widthLocal/2, u2mm(y) ); } else{ radius = DrillingDiam/2-MillerDiam/2; // widthLocal = MillerDiam; widthLocal = 0.01; sprintf(h, "circle %f (%f %f) (%f %f) ;\n", widthLocal, u2mm(x), u2mm(y), u2mm(x) + radius, u2mm(y) ); } } }; cmd_drill += h; return; } // void WriteDrills(void) { string Cmd; MillerDiam = Width; sprintf(cmd_drill, "GRID mm ;\n" "change layer %d ;\n" "change style continuous ;\n" "set undo_log off ;\n" , myLNumber ); if (board) board(B) { B.holes(L) { draw_circle(L.x, L.y, L.drill); } B.elements(E) { E.package.holes(H) { draw_circle(H.x, H.y, H.drill); } E.package.contacts(C) { if (C.pad) { draw_circle(C.pad.x, C.pad.y, C.pad.drill); } } } B.signals(S) { S.vias(V) { draw_circle(V.x, V.y, V.drill); } } output(FileName, "wt"){ printf("%s\n", cmd_drill); } B.signals(S) { if (S.name == OutlinesSignalName) { S.polygons(P) { int x1 = INT_MAX, y1 = INT_MAX, x2 = INT_MIN, y2 = INT_MIN; int x0, y0, first = 1; int FrameWire; int State; P.wires(W) { x1 = min(x1, W.x1); x2 = max(x2, W.x1); y1 = min(y1, W.y1); y2 = max(y2, W.y1); } sprintf(Cmd, "delete (%f %f) (%f %f); window fit;\n" "LAYER %d %s ;\n" "display NONE %d ;\n" "change layer %d ;\n" "GROUP ALL ;\n" "delete (> %f %f) ;\n" ";SCR '" + FileName + "';\n" "grid inch ;\n" "SET CONFIRM YES ;\n" "REMOVE %s ;\n" "SET CONFIRM OFF ;\n" , u2mm(x1), u2mm(y1), u2mm(x2), u2mm(y2), myLNumber,myLName, myLNumber, myLNumber, u2mm(x1), u2mm(y1), FileName); }}} exit (Cmd); } } // // // Main program: // if (Process) { int n; while (ProcessNames[n]) { if (strupr(ProcessNames[n]) == strupr(Process)) { SelectedProcess = n; break; } n++; } if (!SelectedProcess) Fatal("Illegal Selection: " + Process, "Please select one of the Drawing."); } if (!InPass2) { string Layers[]; int SelectedLayer = -1; int ForceDialog = (!Process || !Width); real drillDiam; board(B) { int n; B.layers(L) { if (L.number <= 16 && L.visible) { if (Layer == L.number) SelectedLayer = n; sprintf(Layers[n++], "%d %s", L.number, L.name); } } if (n == 0) Fatal("No signal layer active!", "Please activate the signal layer to generate outlines for."); if (!Layer) { if (n > 1) ForceDialog = 1; SelectedLayer = 0; } if (SelectedLayer < 0) { string s; sprintf(s, "%d", Layer); Fatal("Invalid layer: " + s, "The layer was not found or is not active."); } } // // Enter Parameters if (ForceDialog) { dlgDialog("Parameters Setting") { dlgGridLayout { dlgCell(0, 0) dlgLabel("&What you want: "); dlgCell(0, 1) dlgComboBox(ProcessNames, SelectedProcess); dlgCell(1, 0) dlgLabel("Object &Layer: "); dlgCell(1, 1) dlgComboBox(Layers, SelectedLayer); } dlgSpacing(20); dlgStretch(1); dlgHBoxLayout { dlgStretch(2); dlgPushButton("+OK") { if (!SelectedProcess) Error("No selection!", "Please select 'Outlines' or 'Drills/Holes'."); else dlgAccept(); } dlgPushButton("-Cancel") { dlgReject(); exit(1); } dlgPushButton("About") dlgMessageBox(usage); } }; //End: dlgDialog("Parameters Setting") { // // Outlines Section if(SelectedProcess == proOutlines){ dlgDialog("Draw Outlines"){ dlgGridLayout { dlgCell(0, 0) dlgLabel("Object Layer: "); dlgCell(0, 1) dlgLabel(Layers[SelectedLayer]); Layer = strtol(Layers[SelectedLayer]); myLNumber = Layer +100; sprintf(myLName, "Outline_%d",myLNumber); dlgCell(1, 0) dlgLabel("to Layer Number"); dlgCell(1, 1) dlgIntEdit(myLNumber, 100, 200); dlgCell(2, 0) dlgLabel("to Layer Name "); dlgCell(2, 1) dlgStringEdit(myLName); Width = 0.8; dlgCell(3, 0) dlgLabel("Outline &Width mm"); dlgCell(3, 1) dlgRealEdit(Width, 0.001, 100); } dlgSpacing(30); dlgHBoxLayout { dlgStretch(2); dlgPushButton("+OK") { if (!Width) Error("Illegal width: 0", "The width must be greater than zero."); else dlgAccept(); } dlgPushButton("-Cancel") { dlgReject(); exit(1); } dlgPushButton("About") dlgMessageBox(usage); } }; // End: dlgDialog("Draw Outlines"){ } //End: if(SelectedProcess == proOutlines){ // // Drills/Holes Section if(SelectedProcess == proDrill_Points){ dlgDialog("Draw drill/hole points"){ dlgGridLayout { dlgCell(0, 0) dlgLabel("Object Layer: "); dlgCell(0, 1) dlgLabel(Layers[SelectedLayer]); } myLNumber = 144; myLName = "myDrill"; drillDiam = 0.8; dlgGridLayout { dlgCell(0, 0) dlgLabel("to Layer Number:"); dlgCell(0, 1) dlgIntEdit(myLNumber, 100, 200); dlgCell(1, 0) dlgLabel("to Layer Name: "); dlgCell(1, 1) dlgStringEdit(myLName); dlgCell(2, 0) dlgLabel("Drill(mill) diam. (mm):"); dlgCell(2, 1) dlgRealEdit(drillDiam, 0.1, 10); } dlgHBoxLayout { dlgLabel("Mill larger than drill(mill) to their size: "); dlgStretch(0); dlgCheckBox("", Flag_MillHoles); } // For a Specified range dlgSpacing(30); dlgHBoxLayout { dlgLabel("Specify drills/holes range in diam. from Min to Max: "); dlgStretch(0); dlgCheckBox("", Flag_SpecifiedRange); } dlgGridLayout { dlgCell(0, 0) dlgLabel("Min drill/hole diam. (mm): "); dlgCell(0, 1) dlgRealEdit(minDiam, 0, 100); dlgCell(1, 0) dlgLabel("Max drill/hole diam. (mm):"); dlgCell(1, 1) dlgRealEdit(maxDiam, 0, 100); } dlgSpacing(30); dlgHBoxLayout { dlgStretch(2); dlgPushButton("+OK") { if (!Flag_SpecifiedRange && !drillDiam && Flag_MillHoles) Error("Illegal drill(mill) diameter: 0", "The drill(mill) diam. must be greater than zero."); else if (Flag_SpecifiedRange ==1 && minDiam >= maxDiam) Error("Illegal Min and/or Max diameter: ", "Min must be less than Max."); else dlgAccept(); } dlgPushButton("-Cancel") { dlgReject(); exit(1); } dlgPushButton("About") dlgMessageBox(usage); } }; // End: dlgDialog("Draw drill/hole points"){ Width = drillDiam; } //End: if(SelectedProcess == proDrill_Points){ } //End: if (ForceDialog) { Process = ProcessNames[SelectedProcess]; Layer = strtol(Layers[SelectedLayer]); GenerateOutlines(); } // End: if (!InPass2) { else // InPass2 if (Process == ProcessNames[1]){ // = Outlines WriteOutlines(); } if (Process == ProcessNames[2]){ // = Drills/Holes WriteDrills(); }