/* CEDPOLY (CED) -- Chip Editor Polygon Functions */ /* CEDPOLY (CED) -- Chipeditor-Polygonfunktionen */ /* -- INTENDED FOR KEY-CALL USE -- */ /* // Copyright (c) 2001-2012 Oliver Bartels F+E, Muenchen // Author: Manfred Baumeister // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (101019) RELEASED FOR BAE V7.6. // rl (091020) 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 (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 (010808) ORIGINAL CODING. DERIVED FROM GEDPOLY.ULC. // // DESCRIPTION // // The cedpoly User Language program provides a menu with a // series of advanced polygon processing functions such as // changing polygon layers, defining polygon types, copying // group-selected polygons with scaling, activating 2D drawing // routines, etc. */ // Includes #include "pop.ulh" // User Language popup utilities #include "icd.ulh" // User Language IC Design utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string UPRABORT = M_UPRABORT(); string REPDONE = M("Es wurden keine Fehler festgestellt.", "Operation completed without errors."); string UPRFCT = M("Polygon-Funktion selektieren!", "Select Polygon Function!"); string UPRFCT1 = M("Polygon&lage setzen","Set Polygon &Layer"); string UPRFCT2 = M("Polygon&typ setzen","Set Polygon &Type"); string UPRFCT3 = M("%Polygon S&kalierung","%Polygon &Scale"); string UPRFCT4 = M("Polygon Sp&iegelung","Polygon &Mirroring"); string UPRFCT5 = M("&Zeichenlinien auftrennen","D&ocument Lines Split"); string UPRFCT6 = M("Zeichenlinien &verbinden","Document Lines &Join"); string UPRFCT7 = M("%Polygone loesch&en","%&Delete Polygons"); string UPRFCT8 = M("%Randsperr&flaechen","%Border &Keep Outs"); string UPRMIRR = M("Polygon-Spiegelungsmodus waehlen!", "Select Polygon Mirror Mode!"); string UPRMIRR1 = M("&X-Achse","&X-Axis"); string UPRMIRR2 = M("&Y-Achse","&Y-Axis"); string UPRELEMMODE = M("Bearbeitungsmodus waehlen!", "Select Element Mode!"); string UPRELEM1 = M("&Einzelelemente","&Single Elements"); string UPRELEM2 = M("&Gruppe","&Group"); string UPRPKOUTM = M("Sperrflaeche Abstand (%.2fum) ? ", "Keepout Area Distance (%.2fum) ? "); string UPRPKOUTI = M("Sperrflaeche Abstand [%.3f mil] ? ", "Keepout Area Distance [%.3f mil] ? "); string UPRSELPOLY = M("Polygon(e) waehlen (Eckpunkt anklicken)!", "Select Polygon(s)! (at Polygon Corner)"); string UPRSELSPOLY = M("Polygon waehlen (Eckpunkt anklicken)!", "Select Polygon (at Polygon Corner)!"); string UPRSELLAY = M("Lage waehlen!","Select Layer!"); string UPRPTYP = M("Polygon-Typ selektieren!", "Select Polygon Type!"); string UPRPTYPAC = M("&Aktivflaeche","&Active Area"); string UPRPTYPDL = M("Zeichen&linie","Document &Line"); string UPRPTYPKO = M("&Sperrflaeche","&Keep Out Area"); string UPRPTYPBO = M("%&Umrandung","%&Board Outline"); string UPRSCORG = M("Ausgangspunkt fuer Polygonskalierungskopie waehlen!", "Select Polygon Scale Copy Source Point!"); string UPRSCDEST = M("Zielpunkt fuer Polygonskalierungskopie waehlen!", "Select Polygon Scale Copy Destination Point!"); string UPRSCALE = M("Polygon-Skalierungsfaktor ? ", "Polygon Scale Factor ? "); string ERRCHANGE = M("Fehler beim Aendern des Polygons!", "Error changing polygon!"); string ERRDELETE = M("Fehler beim Loeschen des Polygons!", "Error deleting polygon!"); string ERRPOLY = M("Fehler bei der Polygon-Erzeugung!", "Error creating polygon!"); string ERRNOGRP = M("Gruppe enthaelt kein Polygon!", "Group contains no polygon!"); string ERRNOCHG = M("Polygon ist bereits vom gewuenschten Typ!", "Polygon already of specified type!"); string ERRINVDAT = M("Ungueltige Polygondaten!", "Invalid polygon data!"); string ERRNOPICK = M_ERRNOPICK(); string ERRINPVAL = M_ERRINPVAL(); #define FMTENTRY "\n: %s" // Globals #define COMPTOL 0.00000001 // Compare tolerance [m] int mirrmode /* Mirror mode (0=X,1=Y) */; double mx,my /* Mirror reference coordinates */; int polyflag /* Polygon stored flag */; double scale = 1.0 /* Scale factor */; double orgx, orgy /* Origin coordinates */; double destx, desty /* Destination coordinates */; int polytyp /* Polygon type */; int polylay /* Polygon layer */; int polymir /* Polygon mirror mode */; int curpolytyp /* Current polycon count */; int curpolylay /* Current polygon layer */; int curpolymir /* Current polygon mirror mode */; int curpn /* Current polygon point count */; struct pointdes { // Polygon point descriptor double x /* Point X coordinate */; double y /* Point Y coordinate */; int t /* Point type */; } curpl[] /* Current polygon point list */; int ddbclass = bae_planddbclass() /* Layout plan DDB class */; // Main program void main() { // Abort if invalid plan class if (ddbclass==DDBCLUNDEF) error_class(); // Ask for polygon function type bae_defmenusel(-1); bae_promptdialog(UPRFCT); switch (bae_askmenu(9,UPRFCT1,UPRFCT2,UPRFCT3, UPRFCT4,UPRFCT5,UPRFCT6,UPRFCT7,UPRFCT8,UPRABORT)) { // Set polygon layer case 0 : setpolylayer(); break; // Set polygon type case 1 : setpolytype(); break; // Polygon scale case 2 : polyscale(); break; // Mirror polygons case 3 : mirrpoly(); break; // Documentary line split case 4 : doclsplit(); break; // Documentary line join case 5 : docljoin(); break; // Delete polygons case 6 : delpoly(); break; // Create outline keep out polygons case 7 : polykeepouts(); break; // Abort on default default : error_abort(); } } /*________________________________________________________________*/ // Polygon layer functions void setpolylayer() /* // Set layer of mouse-selectable polygons */ { index I_FIGURE fig /* Figure list element */; int layer /* New layer code */; int cnt = 0 /* Polygon count */; // Select any layer if (bae_promptdialog(UPRSELLAY),ced_asklayer(layer)) // Abort selected error_abort(); // Loop while pick element found bae_prtdialog(UPRSELPOLY); while (ced_pickelem(fig,I_FIGPOLY)==0) { // Save current state for undo if (cnt==0) bae_callmenu(MNU_BAESAVESTATE); // Change layer if (ced_elemlaychg(fig,layer)) error(ERRCHANGE); cnt++; } // No pick if (cnt) bae_prtdialog(ERRNOPICK); else perror(ERRNOPICK); } /*________________________________________________________________*/ // Polygon type functions void setpolytype() /* // Set type of mouse-selectable polygons */ { index I_FIGURE fig /* Figure list element */; index I_FIGURE figpar /* Figure list element param. */; int grpmode = 0 /* Group mode (default none) */; int menuitems = 5 /* Menu item count */; // Test if board outline type is allowed if (ddbclass!=DDBCLILAY || !borderallowed()) { // Skip invalid menu items menuitems=4; UPRPTYPBO=UPRABORT; } // Ask for polygon type bae_promptdialog(UPRPTYP); switch (bae_askmenu(menuitems,UPRPTYPAC,UPRPTYPDL,UPRPTYPKO, UPRPTYPBO,UPRABORT)) { // Abort on last menu item case (menuitems-1) : error_abort(); // Active Area case 0 : polytyp=I_POLYACTAREA; break; // Documentary Line case 1 : polytyp=I_POLYDOCLINE; break; // Keep Out Area case 2 : polytyp=I_POLYKEEPOUT; break; // Board Outline case 3 : // Test the plan class if (ddbclass!=DDBCLILAY) error_class(); polytyp=I_POLYBORDER; break; // Abort default : error_abort(); } // Polygon type if (polytyp==I_POLYBORDER) { // Board outline polyborder(); } else { // Ask for layer bae_promptdialog(UPRSELLAY); if (ced_asklayer(polylay)) // Abort error_abort(); // Select the element mode bae_promptdialog(UPRELEMMODE); if ((grpmode=bae_askmenu(3,UPRELEM1,UPRELEM2,UPRABORT))<0 || grpmode>1) // Abort error_abort(); // Save current state for undo bae_callmenu(MNU_BAESAVESTATE); // Check the group mode if (grpmode) { // Loop for all group polygons forall (fig where fig.GROUP && fig.TYP==C_FIGPOLY) { // Set polygon types figpar=fig; polytype(figpar); } } else { // Loop while pick polygon found while (bae_promptdialog(UPRSELPOLY), ced_pickelem(fig,I_FIGPOLY)==0) // Set polygon types polytype(fig); } } // Screen redraw screenredraw(); // Done bae_prtdialog(REPDONE); } int borderallowed() /* // Test if new board outline is allowed // Return value : // nonzero if board outline allowed, zero else */ { index I_POLY poly /* Polygon index */; // Test the plan class if (ddbclass!=DDBCLILAY) // No layout; board outline not allowed return(0); // Test if board outline exists already forall (poly where poly.TYP==I_POLYBORDER) // Board outline found return(0); // Board outline allowed return(1); } void polytype(index I_FIGURE fig) /* // Set type of given polygon // Parameters : // index I_FIGURE fig : Polygon figure list element */ { index I_FIGURE nfig /* New figure list index */; STRINGS rl /* Rule list */; // Scan polygon points if (icd_scanfelem(fig,0.0,0.0,0.0,1,0, NULL,polytypefunc,NULL,NULL,NULL,NULL)!=0) error_scan(); // Get the polygon mirror mode polymir=curpolymir; // Get the current polygon layer curpolylay=fig.LAYER; // Create the new polygon if (createpoly()) // Non-fatal error; continue without delete return; // Transfer rules if (/* fig.RULEOBJID>=0 && */ icd_lastfigelem(nfig)==0) { // Get rules if (rsi_getfigrules(fig,rl)>0) // Attach rules if (icd_rulefigatt(nfig,rl)) rsi_error(0); } // Delete the old polygon if (ced_delelem(fig)) error(ERRDELETE); } void polyborder() /* // Change type of mouse-selectable polygon to board outline */ { index I_FIGURE fig /* Figure list element */; index I_FIGURE nfig /* New figure list index */; STRINGS rl /* Rule list */; // Pick polygon if (bae_promptdialog(UPRSELSPOLY),ced_pickelem(fig,I_FIGPOLY)) error(ERRNOPICK); // Scan polygon points if (icd_scanfelem(fig,0.0,0.0,0.0,1,0, NULL,polytypefunc,NULL,NULL,NULL,NULL)!=0) error_scan(); // Save current state for undo bae_callmenu(MNU_BAESAVESTATE); // Set the polygon attributes polylay=(-2); polytyp=I_POLYBORDER; polymir=0; // Create the new polygon if (createpoly()) // Non-fatal error return; // Transfer rules if (/* fig.RULEOBJID>=0 && */ icd_lastfigelem(nfig)==0) { // Get rules if (rsi_getfigrules(fig,rl)>0) // Attach rules if (icd_rulefigatt(nfig,rl)) rsi_error(0); } // Delete the old polygon if (ced_delelem(fig)) error(ERRDELETE); } int polytypefunc(index I_POLY poly,int layer, int polyinws,int tree,index I_LEVEL level) /* // Polygon type scan function // Return value : // zero if done or (-1) on error // Parameters : // index I_POLY poly : Polygon index // int layer : Polygon layer // int polyinws : Polygon in workspace flag // int tree : Polygon tree // index I_LEVEL level : Polygon level */ { index I_POINT point /* Point index */; // Set the current polygon type and tree curpolytyp=poly.TYP; curpolylay=poly.LAYER; curpolymir=poly.MVIS; // Reset point count curpn=0; // Store all polygon points to internal point list forall (point of poly) { // Store the point data curpl[curpn].x=point.X; curpl[curpn].y=point.Y; curpl[curpn].t=point.TYP; // Increment point count curpn++; } // Return without errors return(0); } int createpoly() /* // Create polygon // Return value : // zero if done, or (-1) on (non-fatal) error */ { int i /* Loop control variable */; // Test if area to line transformation if (curpolytyp!=I_POLYDOCLINE && polytyp==I_POLYDOCLINE && curpn>0) // Add first area point to line point list curpl[curpn++]=curpl[0]; // Test if closed line to area transformation else if (curpolytyp==I_POLYDOCLINE && polytyp!=I_POLYDOCLINE && curpn>2 && curpl[0].x==curpl[curpn-1].x && curpl[0].y==curpl[curpn-1].y && curpl[0].t==curpl[curpn-1].t) // Delete last area point from point list curpn--; // Check if valid polygon if (curpn < ((polytyp==I_POLYDOCLINE) ? 2 : 3) ) { perror(ERRINVDAT); return(-1); } // Check if change is necessary if (curpolytyp==polytyp && curpolylay==polylay) { // Polygon already of desired type bae_prtdialog(ERRNOCHG); return(-1); } // Build internal point list bae_clearpoints(); // Build internal point list for (i=0;i1) error_abort(); // Loop while pick element found while (bae_promptdialog(UPRSELPOLY),bae_inpoint( bae_planwsnx(),bae_planwsny(),mx,my,0)==0) { // Repeat coordinates for polygon pick bae_clriactqueue(); bae_storemouseiact(1,mx,my,0,LMB); // Pick polygon if (ced_pickelem(fig,I_FIGPOLY)) // No pick element found; abort break; // Save current state for undo if (cnt==0) bae_callmenu(MNU_BAESAVESTATE); // Reset polygon flag polyflag=0; // Scan polygon points if (icd_scanfelem(fig,0.0,0.0,0.0,1,0, NULL,polymirrfunc,NULL,NULL,NULL,NULL)!=0) perror(ERRCHANGE); // Check if valid polygon if (polyflag) { // Transfer rules if (/* fig.RULEOBJID>=0 && */ icd_lastfigelem(nfig)==0) { // Get rules if (rsi_getfigrules(fig,rl)>0) // Attach rules if (icd_rulefigatt(nfig,rl)) rsi_error(0); } // Delete old polygon if (ced_delelem(fig)) error(ERRDELETE); // Screen redraw screenredraw(); cnt++; } } // No pick element found if (cnt) bae_prtdialog(ERRNOPICK); else perror(ERRNOPICK); } int polymirrfunc(index I_POLY poly,int layer, int polyinws,int tree,index I_LEVEL level) /* // Polygon mirror scan function. Generate mirrored polygon // Return value : // zero if done or (-1) on error // Parameters : // index I_POLY poly : Polygon data // int layer : Polygon layer // int polyinws : Polygon in workspace flag // int tree : Polygon tree number // index I_LEVEL level : Polygon level */ { index I_POINT point /* Polygon point index */; // Clear internal point list bae_clearpoints(); // Copy polygon points to internal point list forall (point of poly) { // Store transformed point if (bae_storepoint(mirrmode?2.0*mx-point.X:point.X, mirrmode?point.Y:2.0*my-point.Y,point.TYP?3-point.TYP:0)) return(-1); } // Create new polygon if (ced_storepoly(poly.LAYER,poly.TYP,poly.MVIS)) return(-1); // Return without errors polyflag=1; return(0); } /*________________________________________________________________*/ // Polygon scale functions void polyscale() /* // Create scaled copy of group-selected polygons */ { index I_FIGURE fig /* Figure list index */; int cnt = 0 /* Polygon count */; // Abort if group empty if (groupempty()) error(ERRNOGRP); // Get origin coordinates bae_promptdialog(UPRSCORG); if (bae_inpoint(bae_planwsnx(),bae_planwsny(),orgx,orgy,0)) // Aborted error_abort(); // Get destination coordinates if (bae_promptdialog(UPRSCDEST),bae_inpoint(orgx,orgy,destx,desty,2)) // Aborted error_abort(); // Get the scale factor if (askdbl(scale,UPRSCALE,10)) error(ERRINPVAL); // Loop for all group selected polygons forall (fig where fig.GROUP && fig.TYP==I_FIGPOLY) { // Save current state for undo if (cnt==0) bae_callmenu(MNU_BAESAVESTATE); // Scan polygon points if (icd_scanfelem(fig,0.0,0.0,0.0,1,1, NULL,polyscalefunc,NULL,NULL,NULL,NULL)) error(ERRPOLY); cnt++; } // Screen redraw screenredraw(); // Done bae_prtdialog(REPDONE); } int polyscalefunc(index I_POLY poly,int layer, int polyinws,int tree,index I_LEVEL level) /* // Polygon scale scan function. Generate transformed polygon // Return value : // zero if done or (-1) on error // Parameters : // index I_POLY poly : Polygon data // int layer : Polygon layer // int polyinws : Polygon in workspace flag // int tree : Polygon tree number // index I_LEVEL level : Polygon level */ { index I_POINT point /* Polygon point index */; // Check if boaurd outline if (poly.TYP==I_POLYBORDER) // Ignore board outline return(0); // Clear internal point list bae_clearpoints(); // Copy polygon points to internal point list forall (point of poly) { // Store transformed point if (bae_storepoint(destx+scale*(point.X-orgx), desty+scale*(point.Y-orgy),point.TYP)) return(-1); } // Create new polygon if (ced_storepoly(poly.LAYER,poly.TYP,poly.MVIS)) return(-1); // Return without errors return(0); } /*________________________________________________________________*/ // Polygon split functions void doclsplit() /* // Split documentary lines */ { index I_FIGURE fig /* Figure list index */; index I_FIGURE nfig /* New figure list index */; index I_POLY poly /* Polygon index */; index I_POINT point /* Point index */; double px,py /* Pick coordinates */; int minidx /* Minimum distance point index */; double mindist /* Minimum distance */; STRINGS rl /* Rule list */; int cnt = 0 /* Polygon count */; int i /* Loop control variable */; // Loop while pick element found while (bae_promptdialog(UPRSELPOLY),ced_pickelem(fig,I_FIGPOLY)==0) { // Get the pick coordinates bae_wsmouse(px,py,0); // Reset point count curpn=0; minidx=(-1); poly=fig.POLY; // Store all polygon points to internal point list forall (point of poly) { // Store the point data curpl[curpn].x=point.X; curpl[curpn].y=point.Y; curpl[curpn].t=point.TYP; // Check if new minimum point distance if (point.TYP==0 && (minidx<0 || mindist>dist(px,py,point.X,point.Y))) { // Store the new minimum mindist=dist(px,py,point.X,point.Y); minidx=curpn; } // Increment point count curpn++; } // Check if valid split point found if (curpn>2 && minidx>0 && minidx<(curpn-1)) { // Save current state for undo if (cnt==0) bae_callmenu(MNU_BAESAVESTATE); // Store the first polygon half bae_clearpoints(); for (i=0;i<=minidx;i++) if (bae_storepoint(curpl[i].x, curpl[i].y,curpl[i].t)) error(ERRINVDAT); if (ced_storepoly(fig.LAYER,I_POLYDOCLINE, fig.POLY.MVIS)) error(ERRINVDAT); // Store the second polygon half bae_clearpoints(); for (i=minidx;i=0 && */ icd_lastfigelem(nfig)==0) { // Get rules if (rsi_getfigrules(fig,rl)>0) // Attach rules if (icd_rulefigatt(nfig,rl)) rsi_error(0); } // Delete element if (ced_delelem(fig)) error(ERRDELETE); } cnt++; } // No pick if (cnt) bae_prtdialog(ERRNOPICK); else perror(ERRNOPICK); // Screen redraw screenredraw(); } /*________________________________________________________________*/ // Polygon join functions void docljoin() /* // Join documentary lines */ { index I_FIGURE fig /* Figure list element */; index I_FIGURE figpar /* Figure list element param. */; int grpmode = 0 /* Group mode (default none) */; int delloop = 1 /* Delete loop flag */; int cnt = 0 /* Polygon count */; // Select the element mode bae_defmenusel(-1); bae_promptdialog(UPRELEMMODE); if ((grpmode=bae_askmenu(3,UPRELEM1,UPRELEM2,UPRABORT))<0 || grpmode>1) // Abort error_abort(); // Check the group mode if (grpmode) { // Save current state for undo bae_callmenu(MNU_BAESAVESTATE); while (delloop) { // Loop for all group polygons delloop=0; forall (fig where fig.GROUP && fig.TYP==C_FIGPOLY) { // Set polygon types figpar=fig; if (doclpjoin(figpar,1)) { delloop=1; break; } } } } else { // Loop while pick element found while (bae_promptdialog(UPRSELPOLY), ced_pickelem(fig,I_FIGPOLY)==0) { // Save current state for undo if (cnt==0) bae_callmenu(MNU_BAESAVESTATE); doclpjoin(fig,0); cnt++; } // No pick if (cnt) bae_prtdialog(ERRNOPICK); else perror(ERRNOPICK); } // Screen redraw screenredraw(); } int doclpjoin(index I_FIGURE fig,int grpflag) /* // Join documentary lines starting at given polygon // Return value : // one if lines joind, else zero // Parameters : // index I_FIGURE fig : Polygon figure list element // int grpflag : Group flag */ { index I_POLY poly /* Polygon index */; index I_POINT point /* Point index */; struct pointdes spl[] /* Search polygon point list */; int spn /* Search polygon point count */; double blx, bly /* Polygon box lower boundary */; double bux, buy /* Polygon box upper boundary */; int found /* Polygon found flag */; int retval = 0 /* Return value */; int i /* Loop control variable */; // Store the polygon poly=fig.POLY; curpolylay=poly.LAYER; curpolymir=poly.MVIS; blx=fig.RLX-COMPTOL; bly=fig.RLY-COMPTOL; bux=fig.RUX+COMPTOL; buy=fig.RUY+COMPTOL; // Store all polygon points to internal point list curpn=0; forall (point of poly) { // Store the point data curpl[curpn].x=point.X; curpl[curpn].y=point.Y; curpl[curpn].t=point.TYP; // Increment point count curpn++; } // Scan all touching neighbour polygons do { if (fig.RLXbux) bux=fig.RUX+COMPTOL; if (fig.RUY>buy) buy=fig.RUY+COMPTOL; // Delete the last found polygon if (ced_delelem(fig)) error(ERRDELETE); // Scan for neighbour polygon found=0; forall (fig where (grpflag==0 || fig.GROUP) && fig.TYP==I_FIGPOLY && fig.LAYER==curpolylay && fig.MIRROR==curpolymir && icd_figboxtest(fig,blx,bly,bux,buy)==1) { poly=fig.POLY; spn=0; forall (point of poly) { // Store the point data spl[spn].x=point.X; spl[spn].y=point.Y; spl[spn].t=point.TYP; // Increment point count spn++; } // Check all line end combinations if (fabs(curpl[curpn-1].x-spl[0].x)<=COMPTOL && fabs(curpl[curpn-1].y-spl[0].y)<=COMPTOL) { // Attach the point list for (i=0;i=0;i--) { curpl[curpn]=spl[i]; if (curpl[curpn].t) curpl[curpn].t= 3-curpl[curpn].t; curpn++; } found=1; retval=1; break; } else if (fabs(curpl[0].x-spl[0].x)<=COMPTOL && fabs(curpl[0].y-spl[0].y)<=COMPTOL) { // Move the point list for (i=curpn-1;i>=0;i--) curpl[i+spn]=curpl[i]; curpn+=spn; // Insert the reversed point list for (i=0;i=0;i--) curpl[i+spn]=curpl[i]; curpn+=spn; // Insert the point list for (i=0;i=curpn ? i-curpn : i ; // Skip arc center if (curpl[p1idx].t!=0) continue; p2idx= (i+1)>=curpn ? i+1-curpn : i+1 ; // Check if arc segment if (curpl[p2idx].t!=0) { // Get arc end index p3idx= (i+2)>=curpn ? i+2-curpn : i+2 ; // Create the arc segment keep out area if (carc(curpl[p1idx].x,curpl[p1idx].y, curpl[p3idx].x,curpl[p3idx].y, curpl[p2idx].x,curpl[p2idx].y, curpl[p2idx].t!=1,pwidth)) error(ERRINVDAT); } else { // Create the line segment keep out area if (cline(curpl[p1idx].x,curpl[p1idx].y, curpl[p2idx].x,curpl[p2idx].y,pwidth)) error(ERRINVDAT); } // Store the keepout area if (ced_storepoly(layer,I_POLYKEEPOUT,0)) error(ERRINVDAT); } } // No pick if (cnt) bae_prtdialog(ERRNOPICK); else perror(ERRNOPICK); // Screen redraw screenredraw(); } int cline(double x1,double y1,double x2,double y2,double dist) /* // Create outline polygon for line segment of given width // Return value : // zero if done or (-1) on error // Parameters : // double x1 : Start point X coordinate // double y1 : Start point Y coordinate // double x2 : End point X coordinate // double y2 : End point Y coordinate // double dist : Line distance */ { double dfac /* Factor for circle points calc. */; double d /* Line length */; double dx,dy /* Line vector */; // Start and end points not identical ? bae_clearpoints(); if ((x1!=x2)||(y1!=y2)) { // Get line vector dx=x2-x1; dy=y2-y1; // Get line length and angle d=sqrt(dx*dx+dy*dy); // Store polygon points dfac=dist/d; if (bae_storepoint(x2-dy*dfac,y2+dx*dfac,0) || bae_storepoint(x2,y2,2) || bae_storepoint(x2+dy*dfac,y2-dx*dfac,0) || bae_storepoint(x1+dy*dfac,y1-dx*dfac,0) || bae_storepoint(x1,y1,2) || bae_storepoint(x1-dy*dfac,y1+dx*dfac,0)) return(-1); } else { // Store circle if (bae_storepoint(x1+dist,y1,0) || bae_storepoint(x1,y1,1) || bae_storepoint(x1-dist,y1,0) || bae_storepoint(x1,y1,1)) return(-1); } // Return without errors return(0); } int carc(double xs,double ys,double xe,double ye, double xc,double yc,int cwflag,double dist) /* // Create outline polygon for arc segment of given width // Return value : // zero if done or (-1) on error // Parameters : // double xs : Start point X coordinate // double ys : Start point Y coordinate // double xe : End point X coordinate // double ye : End point Y coordinate // double xc : Center point X coordinate // double yc : Center point Y coordinate // int cwflag : Arc clockwise flag // double dist : Line distance */ { double wxs, wys /* Start width vector coords. */; double wxe, wye /* End width vector coords. */; double dx, dy /* Line vector coordinates */; double r /* Arc radius */; int a1ptyp, a2ptyp /* Arc point types */; // Calc. the start radius vector dx=xs-xc; dy=ys-yc; // Calc. the arc radius if ((r=sqrt(dx*dx+dy*dy))<=0.0) return(-1); // Calc. the start point width vector wxs=(dx/r)*dist; wys=(dy/r)*dist; // Calc. the end radius vector dx=xe-xc; dy=ye-yc; // Calc. the end point width vector wxe=(dx/r)*dist; wye=(dy/r)*dist; // Test if clockwise arc if (cwflag) { // Reverse both point width vectors wxs=(-wxs); wys=(-wys); wxe=(-wxe); wye=(-wye); // Use clockwise main arc first a1ptyp=2; a2ptyp=1; } else { // Use anti-clockwise main arc first a1ptyp=1; a2ptyp=2; } // Store arc polygon bae_clearpoints(); if (bae_storepoint(xs+wxs,ys+wys,0) || bae_storepoint(xc,yc,a1ptyp) || bae_storepoint(xe+wxe,ye+wye,0) || bae_storepoint(xe,ye,1) || bae_storepoint(xe-wxe,ye-wye,0) || bae_storepoint(xc,yc,a2ptyp) || bae_storepoint(xs-wxs,ys-wys,0) || bae_storepoint(xs,ys,1)) return(-1); // Return without errors return(0); } int groupempty() /* // Test if group is empty // Return value : // zero if group not empty or nonzero if empty */ { index I_FIGURE fig /* Figure list index */; // Loop thru the figure list forall (fig where fig.GROUP && fig.TYP==I_FIGPOLY) // Return the group not empty code return(0); // Group contains no element; return the group empty code return(1); } // User Language program end