#usage "DXFimport V1.8

" "This ULP can import DXF files that include polylines.
" "Browse to the DXF file, setup your origins, input units, scale factor and linewidth then click convert. " "The ULP will then show you the script in case you want to change the layer the input will be written to.
" "Tested in version 5, 6, 7, and Autodesk EAGLE.
" "author Written by Jorge Garcia of Cadsoft Computer, heavily based off of Hank Wallace's DXF2SCR program.
" "With special thanks to Robert Starr, Alfred Zaffran, Billy Coleman and Holger Moessinger." string Version = "1.9"; string Help = "DXFimport "+Version+ "\n

This ULP will import a DXF \ file into EAGLE (Board, Schematic, Package or Symbol-Editor). \ Use the browse button to find the DXF file, make sure to set \ the units to whatever units are used by the DXF file. Set the width, Xorg, and \ Yorg in whatever units you selected. Then set an appropriate scale factor and \ click the OK button, the generated script will be shown for editing. Once \ it's adjusted to your liking click Run.

"; /* ******************************************************************* REVISION HISTORY 2012-03-03 Initial Release. 2012-06-19 Finally incorporated Holger Moessinger's improvements to the polygon import, added him to special thanks section. 2012-07-10 Added support for LWPOLYLINE. 2013-02-13 Check maximum coodinate of eagle, Alfred Zaffran. This feature keeps track of the size of the DXF file, if it's outside the drawing limits of EAGLE the ULP will recognize this and suggest a corrective offset which the user can approve. 2013-06-12 Discovered that some files don't implement the proper spacing so I modified the ULP to cope with that. 2014-03-12 Implemented the ability to skip the section search state. Some DXF files don't have an ENTITIES section which the old ULP expected. This allows the ULP to try going through the file again without expecting an ENTITIES section. The downside is that some extraneous stuff may come in on the import but usually the user will be able to tell and remove those features. The generated script file has a comment added to it when EAGLE uses that feature. 2014-03-12 Assimilated Billy Coleman's scaling functionality. Added him to the thank you list in the description. 2014-03-13 Implemented a flag in the LWPOLYLINE state of dxf() to make sure the state isn't exited, before processing the object. Similar improvements where made in the VERTEX state of DXF. 2015-02-10 make target layer selectable alf@cadsoft.de 2017-04-06 fixed critical LWPOLYLINE bug JG 2017-06-05 fixed subtle LWPOLYLINE bug where a value of 0 causes the LWPOLYLINE object to be exited early. JG ********************************************************************* */ /* *********************************************************************** Below I have retained Mr. Wallace's original "licensing" statement for two reasons: 1. As a sign of respect for the original author of the code from which this ULP was developed and without which it would have not been possible to develop this ULP. 2. This is quite possibly the funniest licensing statement any one will ever read. Officially though, I will license this under the MIT open software license copied below: Copyright (c) 2012 Newark, Premier Farnell DBA Cadsoft Computer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Jorge Garcia 03-Mar-2012 ---------------------------------------------------------------------- DXF2SCR.C Program that crunches a DXF file with circles, arcs and lines into an Eagle script file, useful for translating board outlines. Hank Wallace 20-Mar-03 Revision 20-Mar-03 There are two licensing options for this program: 1. If you are a fan of the GNU license, and you think you understand it, and you think it is reasonable, and you believe that 'free to download' means 'high quality' or 'low maintenance cost', and you are a computer geek who cannot get a date who measures the value of his/her existence by the number of marginally useful command line options you can stuff into one program on a lonely Friday night, and you write C source code in such a manner that there are more #define'd constants and conditional compilation directives than there are actual C source statements, and you attempt to make your programs so 'portable' that they runs on no machine whatsoever without modification, then you have no license to use this software. Get a life. 2. If you one of the other 6 billion people on planet Earth, this program source code and executable is free for your use without restriction, but NO WARRANTY OR SUPPORT IS GIVEN. This program compiles under Microsoft's command line compiler, version 12.00. ----------------------------------------------------------------------------- ************************************************************************** */ /* ************************************************************************ * GLOBAL VARIABLES ************************************************************************** */ //include "debug.ulp" string ConfigFileName = filesetext(argv[0], ".cfg"); real XMax; /* Maximum dimensions of DXF file */ real YMax; real XMin; real YMin; real Exmax = REAL_MAX; /* Maximum dimensions EAGLE can draw in um */ real Eymax = REAL_MAX; real Exmin = -REAL_MAX; real Eymin = -REAL_MAX; real S_factor; real GUI_scale = 1.0; /* Additional scale factor that can be used to resize dxf */ int GUI_in_unit = 0; int GUI_scaled_Xorg = 0; /* Checkbox variables */ int GUI_scaled_Yorg = 0; int GUI_scaled_lwidth = 0; string GUI_script; string GUI_fileName; real GUI_Xorg = 0.0; real GUI_Yorg = 0.0; real GUI_lwidth = 0.001; string GUI_layers[]; GUI_layers[0] = "select a layer"; int GUI_layerselect = -1; int Lcnt = 1; int GUI_TargetLayer = 0; int SavedTargetLayer = 0; /* ******************************************************************************* * NON-GUI FUNCTIONS ******************************************************************************* */ /* ******************************************************************************* * strcomp2() * * Description: The purpose of this function is to take the input scompare and * compare it to strings s1 and s2 for an exact match. If there is * no match to either string it will return -1, if there is a match * to one of the strings it will return the index of the * corresponding strstr function that succeeded. * * The strstr function checks to see if a substring shows up within * a given string, if it does it gives the index where the * substring shows up within the string. This is not enough to * ensure an exact match. To ensure an exact match we would need * the length of the strings to be the the same. * * Arguments: scompare String to be compared * s1 First item to match * s2 Second item to match * * Return: -1 If there is no match * int If there is a match corresponding to index of strstr * function that succeeded * * Caller: dxf * ******************************************************************************* */ int strcomp2(string scompare, string s1, string s2) { int result = strstr(scompare, s1); if(result != -1 && strlen(scompare) == strlen(s1)) { return result; } else { result = strstr(scompare, s2); if (result != -1 && strlen(scompare) == strlen(s2)) { return result; } else { return -1; } } } /* ******************************************************************************* * mx() and my() * * Description: These functions below are used to find the extreme XY points of * the DXF file we're importing. This info will later be used to * make sure the file fits inside the drawing area of EAGLE. They * modify the drawing Max and Min variables in order to find the * size of the imported drawing * * Arguments: real Real x or y value * * Return: real The original x or y value that was passed * * Caller: dxf * ******************************************************************************* */ real mx(real x) { if (XMax < x) XMax = x; if (XMin > x) XMin = x; return x; } real my(real y) { if (YMax < y) YMax = y; if (YMin > y) YMin = y; return y; } /* ******************************************************************************* * dxf() * * Description: This function takes a DXF file path and processes it to produce * a script full of commands to draw the contents of the DXF file * in EAGLE. * * Arguments: dxffile Path to the DXF file to be processed * units Units of the DXF file * xorigin User defined offset in the X direction * yorigin User defined offset in the Y direction * liwidth User defined line width * ent Skips the search for sections and entities, * useful for files that don't strictly follow * the DXF format. * scale Optional scaling factor to increase or decrease * the size of the DXF file * * Return: string A long string full of EAGLE commands * * Caller: checkscript * ******************************************************************************* */ string dxf(string dxffile, int units, real xorigin, real yorigin, real liwidth, int ent, real scale) { string s[]; // This string array will store the DXF file string out; // Out is the script generated by this function string temp; // Place holder enum { state_SECTION, state_ENTITIES, state_SEARCH, state_LINE, state_ARC, state_CIRCLE, state_POLYLINE, state_VERTEX, state_LWPOLYLINE}; // Defines states for the main state machine enum { order_FIRST, order_SECOND, order_THIRD, order_FOURTH, order_FIFTH}; // Defines states for the secondary state machines int i; // index variable for xa and ya int p; // dummy variable for for loop int m; // dummy variable for main while loop int nlines; // number of lines in the text file int state; int order; // Used for internal state machines int lines; int arcs; int circles; int polylines; int linewidth=1; int LWPOLY_FLAG=1; // See comment in LWPOLYLINE state real x; real y; real x1; real y1; real x2; real y2; real x3; real y3; real r; real theta1; real theta3; real xorg; real yorg; real xa[]; // xa and ya arrays hold the possible vertexes of a polyline real ya[]; real plclosed; real bulgevalue[]; // plclosed and bulgevalue array helps in dealing with... // ... closed polylines if (units == 1) { // Setup unit scale factor S_factor = 1000; // Convert mm to um XMax = u2mm(INT_MIN)*S_factor; YMax = u2mm(INT_MIN)*S_factor; XMin = u2mm(INT_MAX)*S_factor; YMin = u2mm(INT_MAX)*S_factor; } else { S_factor = 25400; // Convert in to um XMax = u2inch(INT_MIN)*S_factor; YMax = u2inch(INT_MIN)*S_factor; XMin = u2inch(INT_MAX)*S_factor; YMin = u2inch(INT_MAX)*S_factor; } linewidth = liwidth * S_factor; xorg = xorigin * S_factor; yorg = yorigin * S_factor; S_factor *= scale; // Added scale factor affects everything except xorg, ... // ... yorg and linewidth those are handled by the GUI out += "# dxfimport generated script file.\n"; out += "Grid mic 1 off;\n"; out += "Set Wire_Bend 2;\n"; sprintf(temp, "CHANGE LAYER %d;\n", GUI_TargetLayer); // 2015-02-10 out += temp; out += "Change Font Vector;\n"; if (ent >= 1) { // Allows the section search to be disabled state = state_SEARCH; out += "# Skipped Section Search\n"; } else { state = state_SECTION; } order = order_FIRST; lines = arcs = circles = polylines = 0; nlines = fileread(s, dxffile); for (m = 0;m < nlines;m++) { switch (state) { case state_SECTION: // scan for SECTIONS in the DXF file if (strstr(s[m],"SECTION") != -1) { if (ent >= 1) { state = state_SEARCH; } else { state = state_ENTITIES; } } break; case state_ENTITIES: // scan for ENTITIES in the DXF file if (strstr(s[m],"ENDSEC") != -1) { state = state_SECTION; } if (strstr(s[m],"ENTITIES") != -1) { state = state_SEARCH; } break; case state_SEARCH: // scanning for LINE, ARC, CIRCLE, POLYLINE, SPLINE if (strstr(s[m],"ENDSEC") != -1) { if (ent >= 1) { state = state_SEARCH; } else { state = state_SECTION; } } if (strstr(s[m],"LINE") != -1 && strlen(s[m]) == 4) { state = state_LINE; lines++; } if (strstr(s[m],"ARC") != -1 && strlen(s[m]) == 3) { state = state_ARC; arcs++; } if (strstr(s[m],"CIRCLE") != -1 && strlen(s[m]) == 6) { state = state_CIRCLE; circles++; } if (strstr(s[m],"POLYLINE") != -1 && strlen(s[m]) == 8) { i=0; state = state_POLYLINE; polylines++; } if (strstr(s[m],"LWPOLYLINE") != -1 && strlen(s[m]) == 10) { i=0; // JG Support for LWPOLYLINE added 07/09/2012 state = state_LWPOLYLINE; polylines++; } break; case state_LINE: // absorbing LINE switch(order) { // LINE 10, 20, 30 (start point), 11, 21, 31 (end point). case order_FIRST: if (strcomp2(s[m], " 10", "10") != -1) { x = S_factor*strtod(s[m+1]); order = order_SECOND; } break; case order_SECOND: if (strcomp2(s[m], " 20", "20") != -1) { y = S_factor*strtod(s[m+1]); order = order_THIRD; } break; case order_THIRD: if (strcomp2(s[m], " 11", "11") != -1) { x1 = S_factor*strtod(s[m+1]); order = order_FOURTH; } break; case order_FOURTH: if (strcomp2(s[m], " 21", "21") != -1) { y1 = S_factor*strtod(s[m+1]); sprintf(temp, "Wire %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(x+xorg), my(y+yorg), mx(x1+xorg), my(y1+yorg) ); out += temp; // Write to script state = state_SEARCH; order = order_FIRST; } break; } break; case state_ARC: // absorbing ARC switch(order) { // ARC 10, 20, 30 (center), 40 (radius), 50 (start angle), 51 (end) case order_FIRST: if (strcomp2(s[m], " 10", "10") != -1) { x = S_factor*strtod(s[m+1]); order = order_SECOND; } break; case order_SECOND: if (strcomp2(s[m], " 20", "20") != -1) { y = S_factor*strtod(s[m+1]); order = order_THIRD; } break; case order_THIRD: if (strcomp2(s[m], " 40", "40") != -1) { r = S_factor*strtod(s[m+1]); order = order_FOURTH; } break; case order_FOURTH: if (strcomp2(s[m], " 50", "50") != -1) { theta1 = strtod(s[m+1]); theta1 *= (PI/180); order = order_FIFTH; } break; case order_FIFTH: if (strcomp2(s[m], " 51", "51") != -1) { theta3 = strtod(s[m+1]); theta3 *= (PI/180); x1 = r*cos(theta1)+x; // compute Eagle arc parameters from DXF arc params y1 = r*sin(theta1)+y; x2 = x1-2*r*cos(theta1); y2 = y1-2*r*sin(theta1); x3 = r*cos(theta3)+x; y3 = r*sin(theta3)+y; sprintf(temp, "Arc CCW %d (%0.2f %0.2f) (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(x1+xorg), my(y1+yorg), mx(x2+xorg), my(y2+yorg), mx(x3+xorg), my(y3+yorg) ); out += temp; state = state_SEARCH; order = order_FIRST; } break; } break; case state_CIRCLE: // absorbing CIRCLE switch(order) { // CIRCLE 10, 20, 30 (center), 40 (radius). case order_FIRST: if (strcomp2(s[m], " 10", "10") != -1) { x = S_factor*strtod(s[m+1]); order = order_SECOND; } break; case order_SECOND: if (strcomp2(s[m], " 20", "20") != -1) { y = S_factor*strtod(s[m+1]); order = order_THIRD; } break; case order_THIRD: if (strcomp2(s[m], " 40", "40") != -1) { y1 = S_factor*strtod(s[m+1]); sprintf(temp, "Circle %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(x+xorg), my(y+yorg), mx(x+xorg), my(y+y1+yorg) ); out += temp; state = state_SEARCH; order = order_FIRST; } break; } break; case state_POLYLINE: // absorbing POLYLINE if (strstr(s[m], "VERTEX") != -1) { // VERTEX state = state_VERTEX; } if (strcomp2(s[m], " 70", "70") != -1) { // EDIT HM 20120425: Determine if Polyline is closed and... plclosed = strtod(s[m+1]); // ...take care of bulge values for line segments. } if (strstr(s[m], "SEQEND") != -1) { for (p=0; p < i-1;p++) { // n points give n-1 lines that's why there's an i-1 in... if (bulgevalue[p] != 0) { // ...the conditional sprintf(temp, "Wire %d (%0.2f %0.2f) %+0.2f (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), (atan(bulgevalue[p])*180/PI*4), mx(xa[p+1]+xorg), my(ya[p+1]+yorg) ); out += temp; } else { sprintf(temp, "Wire %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), mx(xa[p+1]+xorg), my(ya[p+1]+yorg) ); out += temp; } } if(plclosed) { if(bulgevalue[p] != 0) { sprintf(temp, "Wire %d (%0.2f %0.2f) %+0.2f (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), (atan(bulgevalue[p])*180/PI*4), mx(xa[0]+xorg), my(ya[0]+yorg) ); out += temp; } else { sprintf(temp, "Wire %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), mx(xa[0]+xorg), my(ya[0]+yorg) ); out += temp; } } state = state_SEARCH; } break; case state_VERTEX: // absorbing VERTEX switch(order) { case order_FIRST: if (strcomp2(s[m], " 10", "10") != -1) { // 10 (x-value) 20 (y-value) xa[i] = S_factor*strtod(s[m+1]); order = order_SECOND; } break; case order_SECOND: if (strcomp2(s[m], " 20", "20") != -1) { ya[i] = S_factor*strtod(s[m+1]); // This avoids a misalignment of the bulge array should... bulgevalue[i] = 0; // ...one or more polylines not have bulges order = order_THIRD; } break; case order_THIRD: if (strcomp2(s[m], " 42", "42") != -1) { bulgevalue[i] = strtod(s[m+1]); //* Store bulge value for node } if (strcomp2(s[m], " 0", "0") != -1) { i++; state = state_POLYLINE; // Look for next vertex in polyline order = order_FIRST; } break; } break; case state_LWPOLYLINE: // absorbing LWPOLYLINE 07/09/2012 if (strcomp2(s[m], " 70", "70") != -1) { // Checks for closed polylines and imports them. plclosed = strtod(s[m+1]); } if (strcomp2(s[m], " 10", "10") != -1) { xa[i] = S_factor*strtod(s[m+1]); m = m+1; //By doing this I'm having the for loop move to the next untouched //line. This avoids a bug where a value of 0 for any of the //LWPOLY attributes will cause it to exit prematurely JG 06/05/2017 //the next few states have similar lines. I set the value to the //line of the currently processed data that way when the for loop //comes around it will increment to the next line automatically. } if (strcomp2(s[m], " 20", "20") != -1) { LWPOLY_FLAG = 0; // On poorly formated files, this state may run into an // improperly formatted zero and exit without // processing any points. This flag guarantees that // the state will not be exited before points are // processed. See the if statement below. ya[i] = S_factor*strtod(s[m+1]); if (strcomp2(s[m+2], " 42", "42") == -1) { // No bulge value bulgevalue[i] = 0; m = m+1; // See comments on line 624 i++; // This avoids a misalignment of the bulge array should } // one or more polylines not have bulges. if (strcomp2(s[m+2], " 42", "42") != -1) { bulgevalue[i] = strtod(s[m+3]); // Store bulge value for node i++; m = m+3; // See comments on line 624 } } if (strcomp2(s[m], " 0", "0") != -1 & LWPOLY_FLAG == 0) { for (p=0; p < i-1;p++) { // n points give n-1 lines that's why there's an i-1 in if (bulgevalue[p] != 0) { // the conditional. sprintf(temp, "Wire %d (%0.2f %0.2f) %+0.2f (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), (atan(bulgevalue[p])*(180/PI)*4), mx(xa[p+1]+xorg), my(ya[p+1]+yorg) ); out += temp; } else { sprintf(temp, "Wire %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), mx(xa[p+1]+xorg), my(ya[p+1]+yorg) ); out += temp; } } if(plclosed) { if(bulgevalue[p] != 0) { sprintf(temp, "Wire %d (%0.2f %0.2f) %+0.2f (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), (atan(bulgevalue[p])*180/PI*4), mx(xa[0]+xorg), my(ya[0]+yorg) ); out += temp; } else { sprintf(temp, "Wire %d (%0.2f %0.2f) (%0.2f %0.2f);\n", linewidth, mx(xa[p]+xorg), my(ya[p]+yorg), mx(xa[0]+xorg), my(ya[0]+yorg) ); out += temp; } } state = state_SEARCH; LWPOLY_FLAG = 1; } break; } } sprintf(temp, "Window Fit;\n"); out += temp; sprintf(temp, "# lines=%d, arcs=%d, circles=%d, polylines=%d\n", lines, arcs, circles, polylines ); out += temp; out += "Grid last;"; return out; } /* ******************************************************************************** * GUI FUNCTIONS ******************************************************************************** */ /* ******************************************************************************* * get_project_path() * * Description: Returns project path, if in board or schematic, otherwise * it will return the library path * * Arguments: none * * Return: p String containing full path of project * * Caller: runscript * ******************************************************************************* */ 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; } /* ******************************************************************************* * LoadConfigSettings() * * Description: Loads the most recent configuration settings. * * Arguments: none * * Return: none * * Caller: Main GUI code * ******************************************************************************* */ void LoadConfigSettings() { string lines[]; string rf[]; int nrf = fileglob(rf, ConfigFileName); if (nrf) { nrf = fileread(lines, rf[0]); } if (nrf == 7) { int i = 0; GUI_fileName = lines[i++]; GUI_Xorg = strtod(lines[i++]); GUI_Yorg = strtod(lines[i++]); GUI_scale = strtod(lines[i++]); GUI_lwidth = strtod(lines[i++]); GUI_in_unit = strtol(lines[i++]); SavedTargetLayer = strtol(lines[i++]); } } /* ******************************************************************************* * SaveConfigSettings() * * Description: Saves the most recent configuration settings. * * Arguments: none * * Return: none * * Caller: runscript * ******************************************************************************* */ void SaveConfigSettings() { output(ConfigFileName, "wt") { printf("%s\n", GUI_fileName); printf("%f\n", GUI_Xorg); printf("%f\n", GUI_Yorg); printf("%f\n", GUI_scale); printf("%f\n", GUI_lwidth); printf("%d\n", GUI_in_unit); printf("%d\n", GUI_TargetLayer); } } /* ******************************************************************************* * runscript() * * Description: This function writes the commands to a script file, and then * exits the ULP. Upon exit the command to run the script is * issued to EAGLE. * * Arguments: scr List of script commands * * Return: none * * Caller: checkscript * ******************************************************************************* */ void runscript(string scr) { string filepath = get_project_path() + "dxfimp.scr"; SaveConfigSettings(); output(filepath,"wt") { printf(scr); } exit("SCRIPT '" + filepath + "'"); } /* ******************************************************************************* * checkscript() * * Description: This function checks if the DXF file will fit inside EAGLE's * drawing area and if not return helpful messages. Addtionally it * will display the generated script to the user for modifications * before the script is run. * * Arguments: none * * Return: none * * Caller: Main GUI code * ******************************************************************************* */ void checkscript(void) { // This allows the user to inspect the script and make changes real sc_xo = GUI_Xorg; // These allow the scale factor to be applied independently real sc_yo = GUI_Yorg; real sc_lw = GUI_lwidth; string error; if (!GUI_TargetLayer) { dlgMessageBox("First select a layer!", "OK"); return; } if (GUI_scaled_Xorg == 1) { sc_xo *= GUI_scale; } if (GUI_scaled_Yorg == 1) { sc_yo *= GUI_scale; } if (GUI_scaled_lwidth ==1) { sc_lw *= GUI_scale; } GUI_script = GUI_script = dxf(GUI_fileName, GUI_in_unit, sc_xo, sc_yo, sc_lw, 0, GUI_scale); string dummy[]; // Dummy array to check of dxf function returned valid data if (strsplit(dummy, GUI_script, '\n') == 8) { GUI_script = dxf(GUI_fileName, GUI_in_unit, sc_xo, sc_yo, sc_lw, 1, GUI_scale); // Run again without searching for sections } real Xdim = XMax - XMin; // Max dimensions of DXF file,must be defined after dxf runs real Ydim = YMax - YMin; real EXdim = Exmax - Exmin; // Max dimensions of EAGLE real EYdim = Eymax - Eymin; if ((Xdim > EXdim) || (Ydim > EYdim)) { // Checks if DXF file is larger than EAGLE's drawing area dlgMessageBox(":DXF file is larger than EAGLE's drawing area please scale the file in your MCAD software and try again"); exit(-1); } if ((Xdim < Exmax) && (Ydim < Eymax)) { // Checks if DXF file is small enough to fit in the // first quadrant (+X +Y) if ((XMax > Exmax) || (YMax > Eymax) || (XMin < Exmin) || (YMin < Eymin)) { // Check if any of the points are outside of EAGLE's drawing area GUI_Xorg = -1.0*(XMin/S_factor); // Lower left corner of DXF file will now be at 0 0 GUI_Yorg = -1.0*(YMin/S_factor); // Make sure we return the offset in original units sprintf(error,":DXF file is outside of EAGLE's drawing area would you like to apply an offset in X of %.1f and %.1f in y?", GUI_Xorg, GUI_Yorg); if (dlgMessageBox(error, "Set offset", "CANCEL") != 0) exit(-1); return; } } else { // DXF file is too large to fit in first quadrant if ((XMax > Exmax) || (YMax > Eymax) || (XMin < Exmin) || (YMin < Eymin)) { // Check if any of the points are outside of EAGLE's drawing area GUI_Xorg = -1.0*(((XMin+XMax)/2)/S_factor); // Center of DXF file will now be at 0 0 GUI_Yorg = -1.0*(((YMin+YMax)/2)/S_factor); sprintf(error,":DXF file is outside of EAGLE's drawing area would you like to apply an offset in X of %.1f and %.1f in y?", GUI_Xorg, GUI_Yorg); if (dlgMessageBox(error, "Set offset", "CANCEL") != 0) exit(-1); return; } } int Result = dlgDialog("Run Script") { dlgTextEdit(GUI_script); dlgHBoxLayout { dlgPushButton("Run") runscript(GUI_script); dlgPushButton("Cancel") dlgReject(); } }; } int gettargetlayer(int select) { return strtol(GUI_layers[select]); } /* ******************************************************************************** * MAIN() * ******************************************************************************** */ LoadConfigSettings(); // load the last filename and config settings GUI_TargetLayer = 0; if (board) { board(B) { B.layers(L) { if (L.name) { sprintf(GUI_layers[Lcnt], "%d %s",L.number, L.name); if (L.number == SavedTargetLayer) { GUI_TargetLayer = L.number; GUI_layerselect = Lcnt; } Lcnt++; } } } } else if (schematic) { schematic(SCH) { SCH.layers(L) { if (L.name) { sprintf(GUI_layers[Lcnt], "%d %s",L.number, L.name); if (L.number == SavedTargetLayer) { GUI_TargetLayer = L.number; GUI_layerselect = Lcnt; } Lcnt++; } } } } else if (package || symbol) { library(LIB) { LIB.layers(L) { if (L.name) { sprintf(GUI_layers[Lcnt], "%d %s",L.number, L.name); if (L.number == SavedTargetLayer) { GUI_TargetLayer = L.number; GUI_layerselect = Lcnt; } Lcnt++; } } } } else { dlgMessageBox("Start this ULP in a Schematic- or Board- or Package- or Symbol- Editor!", "OK"); exit(-1); } int main() { string stateline = " "; int Result = dlgDialog("DXFIMPORT - "+Version) { dlgHBoxLayout { dlgLabel(Help); } dlgHBoxLayout { dlgLabel("File &name:"); dlgStringEdit(GUI_fileName); dlgPushButton("Bro&wse") { GUI_fileName = dlgFileOpen("Select a file", GUI_fileName, "*.dxf"); } } dlgHBoxLayout { dlgLabel("Target layer "); dlgComboBox(GUI_layers, GUI_layerselect) GUI_TargetLayer = gettargetlayer(GUI_layerselect); dlgStretch(1); } dlgHBoxLayout { dlgGroup("Input Units") { dlgRadioButton("Imperial(in)", GUI_in_unit); // GUI_in_unit = 0 dlgRadioButton("Metric(mm)", GUI_in_unit); // GUI_in_unit = 1 } dlgGridLayout { dlgCell(0, 0) dlgLabel("Xorg"); dlgCell(1, 0) dlgLabel("Yorg"); dlgCell(0, 1) dlgRealEdit(GUI_Xorg); dlgCell(1, 1) dlgRealEdit(GUI_Yorg); dlgCell(2, 0) dlgLabel("Width"); dlgCell(2, 1) dlgRealEdit(GUI_lwidth); dlgCell(3, 0) dlgLabel("Scale"); dlgCell(3, 1) dlgRealEdit(GUI_scale); dlgCell(0, 2, 3, 2) { dlgGroup("Scaled") { dlgCheckBox("Xorg", GUI_scaled_Xorg); // If checked int contains 1, if unchecked 0 dlgCheckBox("Yorg", GUI_scaled_Yorg); dlgCheckBox("Width", GUI_scaled_lwidth); } } dlgCell(1, 3) dlgPushButton("OK") { stateline = "converting file... please wait."; dlgRedisplay(); checkscript(); stateline = " "; dlgRedisplay(); } dlgCell(2, 3) dlgPushButton("-Cancel") dlgReject(); } } dlgLabel(stateline, 1); }; return Result; }