/* LCIFOUT (LAY) -- Layout CIF Data Output Interface */ /* LCIFOUT (LAY) -- Layout CIF-Datenausgabe */ /* // Copyright (c) 1995-2012 Oliver Bartels F+E, Muenchen // Author: Roman Ludwig // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (101019) RELEASED FOR BAE V7.6. // rl (091027) RELEASED FOR BAE V7.4. // rl (081014) RELEASED FOR BAE V7.2. // rl (071029) RELEASED FOR BAE V7.0. // rl (060829) RELEASED FOR BAE V6.8. // rl (060427) ENHANCEMENT: // Corrected arc suppresion to 1um instead of 1mm radius. // rl (050906) RELEASED FOR BAE V6.6. // rl (040811) RELEASED FOR BAE V6.4. // rl (030904) RELEASED FOR BAE V6.2. // rl (021209) RELEASED FOR BAE V6.0. // rl (020618) RELEASED FOR BAE V5.4. // rl (020313) ENHANCEMENT: // Restricted group output option to layout editor environment. // rl (010625) RELEASED FOR BAE V5.0. // rl (010503) ENHANCEMENT: // Added optional parameter settings from bae.ini file. // rl (000512) RELEASED FOR BAE V4.6. // rl (000509) ENHANCEMENT: // Added dialog box support. // ob (000122) CHANGE: // Added flat output mode. // rl (000110) CHANGE: // Adapted to BAE V4.4. // bms (970402) CHANGE: // Inline documentation changed; source re-formatted. // bms (970127) CHANGE: // Applied new L_POLY* type definitions from std.ulh. // bms (970122) CHANGE: // Applied new function bae_fopen from std.ulh. // rl (960827) ORIGINAL CODING. // // DESCRIPTION // // The lcifout User Language program generates geometry data output // for the currently loaded layout in CIF format. // */ // Includes #include "pop.ulh" // User Language popup utilities #include "lay.ulh" // User Language layout utilities // Disable undo state request #pragma ULCALLERNOUNDO // INI file parameter name definitions #define PAR_CIFEXT "CIFOEXT_LAY" // CIF output file name extension #define PAR_CIFLWIDTH "CIFLWIDTH_LAY" // CIF output text standard line width #define PAR_CIFGLOBSYM "CIFGLOBSYM_LAY"// Create global symbol flag #define PAR_CIFTEXTIGN "CIFTEXTIGN_LAY"// Ignore texts #define PAR_CIFCIRCDIS "CIFCIRCDIS_LAY"// Disable circle command #define PAR_CIFDEFFLAT "CIFDEFFLAT_LAY"// Default flat output mode #define PAR_CIFOCRDFAC "CIFOCRDFAC_LAY"// CIF coordinate output scale #define PAR_CIFOANGFAC "CIFOANGFAC_LAY"// CIF angle output scale // Message definitions string UPRABORT = M_UPRABORT(); string REPCIFWRITE = M("CIF-Daten Ausgabe...","Writing CIF data ..."); string REPCIFDONE = M("CIF-Daten erfolgreich geschrieben.", "CIF data successfully written."); string UPRCIFFILE = M("!CIF-Daten Ausgabedatei", "!CIF-Data Output File"); string UPRDCIFFILE = M("CIF-Daten Ausgabedatei :", "CIF-Data Output File :"); string UPRFCT = M("Ausgabemenge selektieren!","Select Output Set!"); string UPRDFCT = M("Ausgabemenge :","Output Set :"); string UPRFCT1 = M("&Gruppenelemente","&Group Elements"); string UPRFCT2 = M("&Alles","&All"); string UPRMODE = M("Ausgabemodus selektieren!", "Select Output Mode!"); string UPRDMODE = M("Ausgabemodus :","Output Mode :"); string UPRMODE1 = M("&Hierachisch","&Hierachical"); string UPRMODE2 = M("&Flach","&Flat"); string UPRCIFPARAM = M("CIF-Ausgabeparameter","CIF Output Settings"); string UPRBRWFILENAME = M("&Browse","&Browse"); string ERROFILENAME = M("Ungueltiger Ausgabedateiname!", "Invalid Output File Name!"); // Globals int GLOBALSYM = bae_iniintval(PAR_CIFGLOBSYM,1) /* Create global symbol flag */; int TEXTIGNORE = bae_iniintval(PAR_CIFTEXTIGN,1) /* Ignore texts */; int CIRCDISCMD = bae_iniintval(PAR_CIFCIRCDIS,1) /* Disable circle command */; double STDLINEWIDTH = bae_inidblval(PAR_CIFLWIDTH,0.0002) /* Text standard line width */; string CIFEXT = bae_inistrval(PAR_CIFEXT,".cif") /* CIF output file name ext. */; int ciffh /* CIF output file handle */; int coordcnt = 0 /* Coord. output count */; int cifcurlay = 0 /* Current CIF output layer */; int toplay = lay_plantoplay() /* Layout top layer */; int ilaycnt = lay_planmidlaycnt() /* Inner layer count */; int laye /* Layer range end */; int ilaylb, ilayub /* Inner layer range boundaries */; int flatflag = bae_iniintval(PAR_CIFDEFFLAT,1) /* Flat output mode flag */; // Constant definitions double CIFCOORDSCALE = bae_inidblval(PAR_CIFOCRDFAC,1.0E8) /* CIF coordinate output scale */; double CIFANGSCALE = bae_inidblval(PAR_CIFOANGFAC,100.0) /* CIF angle output scale */; #define SMALLVAL 0.000001 // Small distance value #define SMALLANG 0.001 // Small angle value #define PI 3.141592 // PI #define ARCSTEPANG (PI/8.0) // Arc lin. step angle (per um) #define MAXARCSANG (PI/16.0) // Min. arc linear step angle // CIF symbol list definitions struct symdes { // Symbol descriptor string name /* Symbol macro name */; double scale /* Symbol scale */; index L_MACRO macp /* Symbol pool index */; index L_POOL macidx /* Symbol macro index */; } syml[] /* Symbol list */; int symn /* Symbol count */; // Polygon point data definition typedef struct { // Point descriptor double X,Y /* Point coordinate */; int TYP /* Point type */; } PTDES /* Point descriptor data type */; // Main program void main() { index L_FIGURE fig /* Figure list index */; string cifname /* CIF output file name */; double xoff,yoff /* Plan origin offset */; double pcol = 23.0 /* Parameter column */; double cy /* Dialog box current y coordinate */; int repflag /* Dialog box repeat flag */; int res /* Dialog box selection result */; int varidx /* INI variable index */; int outfidx /* Output file name param. index */; int grpidx /* Group output parameter index */; int flatidx /* Flat output parameter index */; int grpflag /* Group output flag */; int grpenable = 0 /* Group enable flag */; // Abort if invalid plan class if (bae_planddbclass()==DDBCLUNDEF) error_class(); forall (fig where fig.GROUP) { grpenable=1; break; } // Set default group output grpflag=grpenable; // Check for dialog support if (bae_dialclr()) { // Get the CIF output file name if (bae_peekiact()) cifname=askstr("",MAXPATHLEN); else if (bae_askfilename(cifname,CIFEXT,UPRCIFFILE) || cifname=="") // Abort error_abort(); if (cifname=="*") cifname=convstring(bae_planfname(),0)+CIFEXT; else if (cifname[0]=='*') cifname=convstring(bae_planfname(),0)+ strextract(cifname,1,strlen(cifname)); // Check if group output supported if (grpenable) { // Select element range bae_promptdialog(UPRFCT); switch (bae_askmenu(3,UPRFCT1,UPRFCT2,UPRABORT)) { // Group elements case 0 : grpflag=1; break; // All elements case 1 : grpflag=0; break; default : error_abort(); } } // Select output mode bae_promptdialog(UPRMODE); switch (bae_askmenu(3,UPRMODE1,UPRMODE2,UPRABORT)) { // Hierachical output case 0 : flatflag=0; break; // Flat output case 1 : flatflag=1; break; default : error_abort(); } } else { // Init. the y coordinate cy=DIAL_TOPMARG; // Store output file controls dial_label(0.0,cy,UPRDCIFFILE); cy+=DIAL_CTRVSTEP; outfidx=dial_string( convstring(bae_planfname(),0)+CIFEXT,MAXPATHLEN,0.0,cy); cy+=0.2; bae_dialaddcontrol(PA_ACT,0,1,0,0.0,0.0,0.0,"",0, DIAL_LEFTMARG,cy,8.0,UPRBRWFILENAME); // Store a seperator cy+=DIAL_BUTVSTEP; dial_hsep(cy); // Check if group output supported if (grpenable) { // Store group output controls dial_label(0.0,cy,UPRDFCT); grpidx=dial_selbox(grpflag,pcol,cy); dial_sbentry(0,1,UPRFCT1); dial_sbentry(0,0,UPRFCT2); } // Store output level controls dial_label(0.0,cy,UPRDMODE); flatidx=dial_selbox(flatflag,pcol,cy); dial_sbentry(0,0,UPRMODE1); dial_sbentry(0,1,UPRMODE2); // Store the OK and abort button with seperator dial_hsep(cy); dial_okabortini(cy,pcol+20.0+DIAL_RIGHTSMARG,2); // Perform the dialog input loop repflag=1; do { // Call the dialog function bae_setintpar(16,4013); switch (res=bae_dialaskparams(UPRCIFPARAM,0, DIAL_LEFTMARG+pcol+20.0+DIAL_RIGHTSMARG,cy)) { // Done case 0 : repflag=0; case 2 : // Get data from dialog box entries bae_dialgetdata(outfidx,0,0.0,cifname); if (bae_chkoutfname(cifname)) { bae_msgbox(2,ERROFILENAME,""); continue; } if (grpenable) bae_dialgetdata( grpidx,grpflag,0.0,""); bae_dialgetdata(flatidx,flatflag,0.0,""); if (res==0) break; varidx=0; bae_iniflagset(varidx,PAR_CIFDEFFLAT,flatflag); bae_iniwrite(varidx); break; // Browse file name case 1 : // Get the output file name bae_dialgetdata(outfidx,0,0.0,cifname); if (bae_askfilename( cifname,CIFEXT,UPRCIFFILE)==0 && cifname!="") bae_dialsetdata(outfidx, PA_STR|PA_HBRDREL,0,0.0,cifname); break; // Fail/abort case (-1) : default : error_abort(); } // Stop if no further repeat requests } while (repflag); } // Get the inner layer range boundaries if (toplay>1 || ilaycnt==0) { ilaylb=0; ilayub=laye=toplay; } else { ilaylb=1; ilayub=ilaycnt+2; laye=ilaycnt+1; } // If necessary, add the CIF extension to the file name catext(cifname,CIFEXT); // Open CIF-file for write ciffh=bae_fopen(cifname,1); // Get plan origin offset xoff=bae_planwsnx(); yoff=bae_planwsny(); // Write CIF file header fprintf(ciffh,"(CIF file of plan %s database %s);\n", bae_planename(),bae_planfname()); // Test if (nearly) flat output mode, if, keep only main symbol if (!flatflag) { // Create symbol list if (grpflag) { forall (fig where fig.GROUP) if (lay_scanfelem(fig,xoff,yoff,0.0,1,1, symmac,NULL,NULL,NULL,NULL,NULL,NULL)!=0) error_scan(); } else { if (lay_scanall(xoff,yoff,0.0,1,1, symmac,NULL,NULL,NULL,NULL,NULL,NULL)!=0) error_scan(); } } // Show the CIF file write start message bae_prtdialog(REPCIFWRITE); // Test if (nearly) flat output mode, if, keep only main symbol if (!flatflag) { // Write macro symbol definitions if (defmacs()!=0) error_scan(); } // Write main symbol definition if (GLOBALSYM) { fprintf(ciffh,"DS 1 1 1;\n"); fprintf(ciffh,"9 L_%s;\n",bae_planename()); } // Write top level data for all CIF layers for (cifcurlay=0;cifcurlay<=laye;cifcurlay++) { // Write layer data storeciflayname(cifcurlay); if (grpflag) { forall (fig where fig.GROUP) if (lay_scanfelem(fig,xoff,yoff,0.0,1,1, cifmac,cifpoly,cifpath,ciftext, NULL,ciflchk,NULL)!=0) error_scan(); } else { if (lay_scanall(xoff,yoff,0.0,1,1, cifmac,cifpoly,cifpath,ciftext,NULL,ciflchk,NULL)!=0) error_scan(); } } // Close main symbol definition if (GLOBALSYM) fprintf(ciffh,"DF;\n"); // Test if (nearly) flat output mode, if, keep only main symbol if (!flatflag) { // Write symbol references if (grpflag) { forall (fig where fig.GROUP) if (lay_scanfelem(fig,xoff,yoff,0.0,1,1, refmac,NULL,NULL,NULL,NULL,NULL,NULL)!=0) error_scan(); } else { if (lay_scanall(xoff,yoff,0.0,1,1, refmac,NULL,NULL,NULL,NULL,NULL,NULL)!=0) error_scan(); } } // Place main symbol if (GLOBALSYM) fprintf(ciffh,"C 1;\n"); // Write CIF-file end fprintf(ciffh,"E;\n"); // Close CIF file fclose(ciffh); // Done bae_prtdialog(REPCIFDONE); } static double fmax(double val1,double val2) /* // Get max. of two values // Return value : // Max. value // Parameters : // double val1,val2 : Values */ { return(val1>val2?val1:val2); } // CIF output functions static double cifscale(double value) /* // Scale CIF coordinate output // Return value : // Scaled coordinate value // Parameters : // double value : Value to scale */ { int result /* Result value */; if (value>0.0) result=value*CIFCOORDSCALE+0.5; else result=value*CIFCOORDSCALE-0.5; return(result); } static void cifcoordout(double x,double y) /* // CIF coordinate output // Parameters : // double x,y : Coordinates */ { fprintf(ciffh," %.0f %.0f",cifscale(x),cifscale(y)); // Do automatic line feed after 4 coordinate pairs if ((coordcnt%4)==3) fprintf(ciffh,"\n "); // Increment coordinate count coordcnt++; } void storeciflayname(int lay) /* // CIF layer output // Parameters : // int lay : Layer number */ { fprintf(ciffh,"L Sig_%d;\n",lay+1); } static void storecifang(double rotangle) /* // Write CIF rotation angle info // Parameters : // double rotangle : Rotation angle */ { double rotx,roty /* Trigonometric values */; int rx,ry /* Rotation vector */; // Check if angle rectangle in 90 degree grid switch (angclass(rotangle)) { // No output for zero angle case 0 : break; // 90 degree back case 1 : fprintf(ciffh," R 0 1"); break; // 180 degree back case 2 : fprintf(ciffh," R -1 0"); break; // 270 degree back case 3 : fprintf(ciffh," R 0 -1"); break; // "Odd" angle value default : // Get rotation vector components rotx=cos(rotangle); roty=sin(rotangle); rx= rotx>=0 ? CIFANGSCALE*rotx+0.5 : CIFANGSCALE*rotx-0.5; ry= roty>=0 ? CIFANGSCALE*roty+0.5 : CIFANGSCALE*roty-0.5; // Write rotation vector fprintf(ciffh," R %d %d",rx,ry); } } static int checkbox(PTDES points[],int pn) /* // Check a polygon for box shape // Return value : // 1 if box shape zero if none // Parameters : // PTDES points[] : Point list // int pn : Point count */ { // Four edge points ? if (pn!=4) return(0); // Check point types if (points[0].TYP!=0 || points[1].TYP!=0 || points[2].TYP!=0 || points[3].TYP!=0) return(0); // Check sides if (fabs(points[0].Y-points[1].Y)<=SMALLVAL) { if (fabs(points[2].Y-points[3].Y)>SMALLVAL || fabs(points[0].X-points[3].X)>SMALLVAL || fabs(points[1].X-points[2].X)>SMALLVAL) return(0); } else if (fabs(points[0].X-points[1].X)<=SMALLVAL) { if (fabs(points[2].X-points[3].X)>SMALLVAL || fabs(points[0].Y-points[3].Y)>SMALLVAL || fabs(points[1].Y-points[2].Y)>SMALLVAL) return(0); } else return(0); // Box check positive return(1); } static int checkwritecircle(PTDES points[],int pn) /* // Check a polygon for circle shape. Output if circle // Return value : // 1 if circle shape, zero if none, (-1) on file error // Parameters : // PTDES points[]: Point list // int pn : Point count */ { double xmin,ymin /* Shape minimum coords. */; double xmax,ymax /* Shape maximum ccords. */; double xcent,ycent /* Shape center point */; double r /* Circle radius */; double r1,r2 /* Arc radius buffer vars. */; int centcnt /* Center point count */; int nextidx /* Next point index */; double x,y /* Current point coords. */; int i /* Loop control variable */; // Test if circle check enabled if (CIRCDISCMD) return(0); // Four edge points ? if (pn!=4) return(0); // Check point types if (points[0].TYP!=0 && points[1].TYP!=0 && points[2].TYP!=0 && points[3].TYP!=0) return(0); // Evaluate the point list // Clear the eval. variables xcent=ycent=0.0; centcnt=0; // Loop for all points bae_clearpoints(); for (i=0;iSMALLVAL || fabs(points[nextidx].Y-y)>SMALLVAL) // Not a circle shape return(0); // Store the center coordinates xcent+=x; ycent+=y; centcnt++; } } // Test if the center count is valid if (centcnt!=2) // Not a circle shape return(0); // Get the polygon range bae_getpolyrange(xmin,ymin,xmax,ymax); // Calc. the arc center point xcent/=2.0; ycent/=2.0; // Calc. both possible radius values r1=fabs(xmin-xcent); r2=fabs(xmax-xcent); // Test if both are equal if (fabs(r1-r2)>SMALLVAL) // Not a circle shape return(0); // Get the min. radius r= r1fabs(epsin) ; // Adjust the stepping angle adjsang= ARCSTEPANG*r*CIFCOORDSCALE ; if (adjsang>MAXARCSANG) adjsang=MAXARCSANG; // Get the stepping sin, cos stepsin=sin(cwflag ? -adjsang : adjsang); stepcos=cos(cwflag ? -adjsang : adjsang); // Use the start point as first current point cpsin=spsin; cpcos=spcos; // Loop until end point reached while (1) { // Calculate the next point sin, cos npsin=cpsin*stepcos+cpcos*stepsin; npcos=cpcos*stepcos-cpsin*stepsin; // Test if at or behind the end point // Check if end between old and new point sin, cos if (eptestsin) { // sin area is more accurate if ((epcos>0.0)==(cpcos>0.0) && (cpsin=cpsin-SMALLANG && epsin<=npsin+SMALLANG : epsin>=npsin-SMALLANG && epsin<=cpsin+SMALLANG)) break; } else { // cos area is more accurate if ((epsin>0.0)==(cpsin>0.0) && (cpcos=cpcos-SMALLANG && epcos<=npcos+SMALLANG : epcos>=npcos-SMALLANG && epcos<=cpcos+SMALLANG)) break; } // Treat the next as current point cpsin=npsin; cpcos=npcos; // Draw a line to the next point cifcoordout(xc+r*cpcos,yc+r*cpsin); } } static int cifmac() /* // CIF layer data output macro function // Return value : // 0 if out. ws., 1 if inside, 2 if unknown or (-1) on error */ { // Abort scan if not flat output return(flatflag ? 1 : 0); } static int cifpoly(index L_POLY poly,int layer,int polyinws,int tree, index L_LEVEL level) /* // Output an already transformed polygon data block to CIF file // Return value : // zero if done or (-1) on file error // Parameters : // index L_POLY poly : Polygon // int layer : Polygon layer // int polyinws : Poly in workspace flag // int tree : Polygon tree number // index L_LEVEL level : Level */ { index L_POINT point /* Polygon point */; PTDES lpoint /* Last output point */; PTDES cpoint /* Current output point */; PTDES npoint /* Next output point */; PTDES tpoints[] /* Test points */; double xsum,ysum /* Center point calc. variables */; int shiftflag /* Coordinate shift flag */; int i /* Loop variable */; // The layer check was already done by the layer check function // Test if the polygon type is valid if (poly.TYP!=L_POLYCOPPASS && poly.TYP!=L_POLYCOPACT && poly.TYP!=L_POLYHTCHCOP) // Drawing or forbidden area only return(0); // Copy points to array i=0; forall (point of poly) { tpoints[i].X=point.X; tpoints[i].Y=point.Y; tpoints[i++].TYP=point.TYP; } // Check polygon for box shape if (checkbox(tpoints,poly.PN)) { // Calc. center point xsum=0.0; ysum=0.0; for (i=0;iilaylb && cifcurlayi;j--) syml[j]=syml[j-1]; // Insert new symbol data syml[i].name=macp.NAME; syml[i].macp=macp; syml[i].macidx=macidx; symn++; // Abort scan return(0); } static int defmacs() /* // Write symbol definitions to CIF output file // Return value : // zero if done or (-1) on file error */ { int i,j /* Loop control variables */; // Loop for all symbol definitions for (i=0;i=symn) // Symbol not found return(-1); // Write symbol reference call // Reserve zero and main symbol index one, add two fprintf(ciffh,"C %d",GLOBALSYM ? sidx+2 : sidx+1); // Write mirror flag if necessary if (mirrfl) fprintf(ciffh," MX"); // Write angle storecifang(rotang); // Write symbol placement coordinates fprintf(ciffh," T"); // Reset coordinate output count coordcnt=0; cifcoordout(x,y); fprintf(ciffh,";\n"); // Abort macro scan return(0); } // User Language program end