BOOL CcdrawDoc::AddNode(CNode &node, double d) { int i,k; CSegment segm; CArcSegment asegm; CComplex c,a0,a1,a2; double x,y; double R; x=node.x; y=node.y; // test to see if ``too close'' to existing node... for (i=0;i<nodelist.GetSize();i++) if(nodelist[i].GetDistance(x,y)<d) return FALSE; // can't put a node on top of a block label; do same sort of test. for (i=0;i<blocklist.GetSize();i++) if(blocklist[i].GetDistance(x,y)<d) return FALSE; // if all is OK, add point in to the node list... nodelist.Add(node); // test to see if node is on an existing line; if so, // break into two lines; k=(int) linelist.GetSize(); for(i=0;i<k;i++) { if (fabs(ShortestDistance(x,y,i))<d) { segm=linelist[i]; linelist[i].n1=(int) nodelist.GetSize()-1; segm.n0=(int) nodelist.GetSize()-1; linelist.Add(segm); } } // test to see if node is on an existing arc; if so, // break into two arcs; k=(int) arclist.GetSize(); for(i=0;i<k;i++) { if (ShortestDistanceFromArc(CComplex(x,y),arclist[i])<d) { a0.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y); a1.Set(nodelist[arclist[i].n1].x,nodelist[arclist[i].n1].y); a2.Set(x,y); GetCircle(arclist[i],c,R); asegm=arclist[i]; arclist[i].n1=(int) nodelist.GetSize()-1; arclist[i].ArcLength=arg((a2-c)/(a0-c))*180./PI; asegm.n0=(int) nodelist.GetSize()-1; asegm.ArcLength=arg((a1-c)/(a2-c))*180./PI; arclist.Add(asegm); } } return TRUE; }
bool GameEntity::HitTest(GameEntity & ge) { if(shapeType==S_Circle) { if(ge.GetShape()==S_Circle) { return HitTestCircles(GetCircle(),ge.GetCircle()); } else if(ge.GetShape()==S_Box) { //这个暂时没做 return false; } else if(ge.GetShape()==S_Beam) { return HitTestBeamCircle(ge.GetBeam(),circle); } } else if(shapeType==S_Box) { if(ge.GetShape()==S_Circle) { //这个暂时没做 circle box return false; } else if(ge.GetShape()==S_Box) { //这个暂时没做 box box return false; } else if(ge.GetShape()==S_Beam) { return HitTestBeamBox(ge.GetBeam(),box); } } else if(shapeType==S_Beam) { if(ge.GetShape()==S_Circle) { //beam circle return HitTestBeamCircle(beam,ge.GetCircle()); } else if(ge.GetShape()==S_Box) { return HitTestBeamBox(beam,ge.GetBox()); } else if(ge.GetShape()==S_Beam) { //这个暂时没做 beam beam return false; } } return false; }
void Entity::GetFOV(GameMap &CurrentMap) { vector<Tile>::iterator it; //reset all to invis for(it = CurrentMap.TileMap.begin(); it != CurrentMap.TileMap.end(); it++) { (*it).Visible = false; } Circle.clear(); GetCircle(CurrentMap); vector<int>::iterator nit; for(nit = Circle.begin(); nit != Circle.end(); nit++) { CurrentMap.Bresenham(y, x, CurrentMap.TileMap[(*nit)].y, CurrentMap.TileMap[(*nit)].x); } }
// TSnap::IsTree TEST(alg, IsTree) { PNGraph Graph; int RootNId; Graph = GetSingleNode(); EXPECT_EQ(1,TSnap::IsTree(Graph,RootNId)); Graph = GetTree(); EXPECT_EQ(1,TSnap::IsTree(Graph,RootNId)); Graph = GetForest(); EXPECT_EQ(0,TSnap::IsTree(Graph,RootNId)); Graph = GetCircle(); EXPECT_EQ(0,TSnap::IsTree(Graph,RootNId)); }
void Monster::GetFOVNPC(GameMap &CurrentMap) { vector<int> ReturnedTiles; vector<Tile>::iterator it; Circle.clear(); VisTiles.clear(); GetCircle(CurrentMap); vector<int>::iterator nit; for(nit = Circle.begin(); nit != Circle.end(); nit++) { ReturnedTiles.clear(); ReturnedTiles = CurrentMap.BresenhamNPC(y, x, CurrentMap.TileMap[(*nit)].y, CurrentMap.TileMap[(*nit)].x); for(int i = 0; i < ReturnedTiles.size(); i++) VisTiles.push_back(ReturnedTiles[i]); } }
double CbelaviewDoc::ShortestDistanceFromArc(CComplex p, CArcSegment &arc) { double R,d,l,z; CComplex a0,a1,c,t; a0.Set(nodelist[arc.n0].x,nodelist[arc.n0].y); a1.Set(nodelist[arc.n1].x,nodelist[arc.n1].y); GetCircle(arc,c,R); d=abs(p-c); if(d==0) return R; t=(p-c)/d; l=abs(p-c-R*t); z=arg(t/(a0-c))*180/PI; if ((z>0) && (z<arc.ArcLength)) return l; z=abs(p-a0); l=abs(p-a1); if(z<l) return z; return l; }
BOOL CcdrawDoc::WriteDXF(CString fname) { int i,j,k; double x0,y0,x1,y1,R,dt; double extmaxx,extminx,extmaxy,extminy; BOOL laze[256]; int nlaze; char lay[256]; CComplex c,p,s; FILE *fp; if ((fp=fopen(fname,"wt"))==NULL) return FALSE; if (nodelist.GetSize()<2){ extmaxx=1; extmaxy=1; extminx=0; extminy=0; } else{ extminx=nodelist[0].x; extminy=nodelist[1].y; extmaxx=extminx; extmaxy=extminy; for(i=1;i<nodelist.GetSize();i++) { if(nodelist[i].x<extminx) extminx=nodelist[i].x; if(nodelist[i].x>extmaxx) extmaxx=nodelist[i].x; if(nodelist[i].y<extminy) extminy=nodelist[i].y; if(nodelist[i].y>extmaxy) extmaxy=nodelist[i].y; } } for(i=0;i<arclist.GetSize();i++) { k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength); dt=arclist[i].ArcLength*PI/(((double) k)*180.); GetCircle(arclist[i],c,R); p.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y); s=exp(I*dt); for(j=0;j<k;j++){ p=(p-c)*s+c; if(p.re<extminx) extminx=p.re; if(p.re>extmaxx) extmaxx=p.re; if(p.im<extminy) extminy=p.im; if(p.im>extmaxy) extmaxy=p.im; } } p.Set(extminx,extminy); s.Set(extmaxx,extmaxy); R=0.025*abs(s-p); // check out which layers are actually called out; for(i=0,nlaze=0;i<256;i++) laze[i]=FALSE; for(i=0;i<linelist.GetSize();i++) if(linelist[i].InGroup!=0) { for(j=0,k=FALSE;j<nlaze;j++) { if(laze[j]==linelist[i].InGroup) { k=TRUE; j=nlaze; } } if((k==FALSE) && (nlaze<256)){ laze[nlaze]=linelist[i].InGroup; nlaze++; } } for(i=0;i<arclist.GetSize();i++) if(arclist[i].InGroup!=0) { for(j=0,k=FALSE;j<nlaze;j++) { if(laze[j]==arclist[i].InGroup) { k=TRUE; j=nlaze; } } if((k==FALSE) && (nlaze<256)){ laze[nlaze]=arclist[i].InGroup; nlaze++; } } fprintf(fp," 0\nSECTION\n 2\nHEADER\n 9\n"); fprintf(fp,"$INSBASE\n 10\n0.0000\n 20\n0.0000\n 9\n"); fprintf(fp,"$EXTMIN\n 10\n%f\n 20\n%f\n 9\n",extminx-R,extminy-R); fprintf(fp,"$EXTMAX\n 10\n%f\n 20\n%f\n 9\n",extmaxx+R,extmaxy+R); fprintf(fp,"$LIMMIN\n 10\n%f\n 20\n%f\n 9\n",extminx-R,extminy-R); fprintf(fp,"$LIMMAX\n 10\n%f\n 20\n%f\n 9\n",extmaxx+R,extmaxy+R); fprintf(fp,"$TEXTSTYLE\n 7\nSTANDARD\n 9\n$CLAYER\n"); fprintf(fp," 8\ndefault\n 0\nENDSEC\n 0\n"); fprintf(fp,"SECTION\n 2\nTABLES\n 0\n"); fprintf(fp,"TABLE\n 2\nLTYPE\n 70\n4948253\n 0\n"); fprintf(fp,"LTYPE\n 2\nCONTINUOUS\n 70\n 64\n 3\n"); fprintf(fp,"Solid line\n 72\n 65\n 73\n 0\n 40\n0.0\n 0\nENDTAB\n 0\n"); fprintf(fp,"TABLE\n 2\nLAYER\n 70\n 5\n 0\n"); fprintf(fp,"LAYER\n 2\ndefault\n 70\n 64\n 62\n 7\n 6\n"); fprintf(fp,"CONTINUOUS\n 0\n"); for(i=0;i<nlaze;i++) { fprintf(fp,"LAYER\n 2\nlayer%i\n 70\n 64\n 62\n 7\n 6\n",laze[i]); fprintf(fp,"CONTINUOUS\n 0\n"); } fprintf(fp,"ENDTAB\n 0\nTABLE\n 2\n"); fprintf(fp,"STYLE\n 70\n 1\n 0\nSTYLE\n 2\nSTANDARD\n 70\n"); fprintf(fp," 0\n 40\n0.0\n 41\n1.0\n 50\n0.0\n 71\n 0\n"); fprintf(fp," 42\n0.2\n 3\ntxt\n 4\n\n 0\nENDTAB\n 0\n"); fprintf(fp,"TABLE\n 2\nVIEW\n 70\n 0\n 0\nENDTAB\n 0\n"); fprintf(fp,"ENDSEC\n 0\nSECTION\n 2\nBLOCKS\n 0\nENDSEC\n"); fprintf(fp," 0\nSECTION\n 2\nENTITIES\n 0\n"); for(i=0;i<linelist.GetSize();i++) { x0=nodelist[linelist[i].n0].x; y0=nodelist[linelist[i].n0].y; x1=nodelist[linelist[i].n1].x; y1=nodelist[linelist[i].n1].y; if (linelist[i].InGroup==0) sprintf(lay,"default"); else sprintf(lay,"layer%i",linelist[i].InGroup); fprintf(fp,"LINE\n 8\n%s\n 10\n%f\n 20\n%f\n 30\n0.0\n 11\n%f\n 21\n%f\n 31\n0.0\n 0\n", lay,x0,y0,x1,y1); } for(i=0;i<arclist.GetSize();i++) { GetCircle(arclist[i],c,R); x0=arg(nodelist[arclist[i].n0].CC()-c)*180./PI; x1=arg(nodelist[arclist[i].n1].CC()-c)*180./PI; if (x0<0) x0+=360.; if (x1<0) x1+=360.; if (arclist[i].InGroup==0) sprintf(lay,"default"); else sprintf(lay,"layer%i",arclist[i].InGroup); fprintf(fp,"ARC\n 8\n%s\n",lay); fprintf(fp," 10\n%f\n 20\n%f\n 30\n%f\n 40\n%f\n 50\n%f\n 51\n%f\n 0\n", c.re,c.im,0.,R,x0,x1); } fprintf(fp,"ENDSEC\n 0\nEOF\n"); fclose(fp); return TRUE; }
BOOL CcdrawDoc::AddArcSegment(CComplex p0, CComplex p1, CArcSegment &asegm, double tol) { int i,j,k; CSegment segm; CArcSegment newarc; CComplex c,p[2]; CArray< CComplex, CComplex&> newnodes; double R,d,dmin,t; asegm.n0=ClosestNode(p0.re,p0.im); asegm.n1=ClosestNode(p1.re,p1.im); newnodes.RemoveAll(); // don't add if line is degenerate if (asegm.n0==asegm.n1) return FALSE; // don't add if the arc is already in the list; for(i=0;i<arclist.GetSize();i++){ if ((arclist[i].n0==asegm.n0) && (arclist[i].n1==asegm.n1) && (fabs(arclist[i].ArcLength-asegm.ArcLength)<1.e-02)) return FALSE; // arcs are ``the same'' if start and end points are the same, and if // the arc lengths are relatively close (but a lot farther than // machine precision... } // add proposed arc to the linelist asegm.IsSelected=FALSE; // check to see if there are intersections for(i=0;i<linelist.GetSize();i++) { j=GetLineArcIntersection(linelist[i],asegm,p); if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]); } for(i=0;i<arclist.GetSize();i++) { j=GetArcArcIntersection(asegm,arclist[i],p); if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]); } // add nodes at intersections if (tol==0) { if (nodelist.GetSize()<2) t=1.e-08; else{ CComplex p0,p1; p0=nodelist[0].CC(); p1=p0; for(i=1;i<nodelist.GetSize();i++) { if(nodelist[i].x<p0.re) p0.re=nodelist[i].x; if(nodelist[i].x>p1.re) p1.re=nodelist[i].x; if(nodelist[i].y<p0.im) p0.im=nodelist[i].y; if(nodelist[i].y>p1.im) p1.im=nodelist[i].y; } t=abs(p1-p0)*CLOSE_ENOUGH; } } else t=tol; for(i=0;i<newnodes.GetSize();i++) AddNode(newnodes[i].re,newnodes[i].im,t); // add proposed arc segment; arclist.Add(asegm); // check to see if proposed arc passes through other points; // if so, delete arc and create arcs that link intermediate points; // does this by recursive use of AddArcSegment; UnselectAll(); GetCircle(asegm,c,R); if (tol==0) dmin=fabs(R*PI*asegm.ArcLength/180.)*1.e-05; else dmin=tol; k=(int) arclist.GetSize()-1; for(i=0;i<nodelist.GetSize();i++) { if( (i!=asegm.n0) && (i!=asegm.n1) ) { d=ShortestDistanceFromArc(CComplex(nodelist[i].x,nodelist[i].y), arclist[k]); if (d<dmin){ CComplex a0,a1,a2; a0.Set(nodelist[asegm.n0].x,nodelist[asegm.n0].y); a1.Set(nodelist[asegm.n1].x,nodelist[asegm.n1].y); a2.Set(nodelist[i].x,nodelist[i].y); arclist[k].ToggleSelect(); DeleteSelectedArcSegments(); newarc=asegm; newarc.n1=i; newarc.ArcLength=arg((a2-c)/(a0-c))*180./PI; AddArcSegment(newarc,dmin); newarc=asegm; newarc.n0=i; newarc.ArcLength=arg((a1-c)/(a2-c))*180./PI; AddArcSegment(newarc,dmin); i=(int) nodelist.GetSize(); } } } return TRUE; }
// Call triangle to order segments on the boundary properly BOOL ChdrawDoc::FunnyOnWritePoly() { FILE *fp; int i,j,k,l,t,n,n0,n1,n2; double z,R,dL; CComplex a0,a1,a2,c; CComplex b0,b1,b2; char instring[1024]; CString s; CArray< CNode, CNode&> nodelst; CArray< CSegment, CSegment&> linelst; CArray< CArcSegment, CArcSegment&> arclst; CArray< CBlockLabel, CBlockLabel&> blocklst; CArray< CPeriodicBoundary, CPeriodicBoundary&> pbclst; CArray< CCommonPoint, CCommonPoint& >ptlst; CNode node; CSegment segm; CPeriodicBoundary pbc; CCommonPoint pt; nodelst.RemoveAll(); linelst.RemoveAll(); pbclst.RemoveAll(); ptlst.RemoveAll(); UpdateUndo(); // calculate length used to kludge fine meshing near input node points for (i=0,z=0;i<linelist.GetSize();i++) { a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y); a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y); z += (abs(a1-a0)/((double) linelist.GetSize())); } dL=z/LineFraction; // copy node list as it is; for(i=0;i<nodelist.GetSize();i++) nodelst.Add(nodelist[i]); // discretize input segments for(i=0;i<linelist.GetSize();i++) { // abuse the IsSelected flag to carry a notation // of which line or arc in the input geometry a // particular segment is associated with segm=linelist[i]; segm.IsSelected=i; a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y); a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y); if (linelist[i].MaxSideLength==-1) k=1; else{ z=abs(a1-a0); k=(int) ceil(z/linelist[i].MaxSideLength); } if (k==1) // default condition where discretization on line is not specified { if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(segm); // line is too short to add extra points else{ // add extra points at a distance of dL from the ends of the line. // this forces Triangle to finely mesh near corners for(j=0;j<3;j++) { if(j==0) { a2=a0+dL*(a1-a0)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } if(j==1) { a2=a1+dL*(a0-a1)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } if(j==2) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } } } } else{ for(j=0;j<k;j++) { a2=a0+(a1-a0)*((double) (j+1))/((double) k); node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } } // discretize input arc segments for(i=0;i<arclist.GetSize();i++) { segm.IsSelected=i+(int) linelist.GetSize(); a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y); k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength); segm.BoundaryMarker=arclist[i].BoundaryMarker; segm.InConductor=arclist[i].InConductor; GetCircle(arclist[i],c,R); a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.)); if(k==1){ segm.n0=arclist[i].n0; segm.n1=arclist[i].n1; linelst.Add(segm); } else for(j=0;j<k;j++) { a2=(a2-c)*a1+c; node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=arclist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=arclist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } // create correct output filename; CString pn = GetPathName(); CString plyname=pn.Left(pn.ReverseFind('.')) + ".poly"; // check to see if we are ready to write a datafile; if ((fp=fopen(plyname,"wt"))==NULL){ MsgBox("Couldn't write to specified .poly file"); Undo(); UnselectAll(); return FALSE; } // write out node list fprintf(fp,"%i 2 0 1\n",nodelst.GetSize()); for(i=0;i<nodelst.GetSize();i++) { fprintf(fp,"%i %.17g %.17g %i\n", i,nodelst[i].x,nodelst[i].y,0); } // write out segment list fprintf(fp,"%i 1\n",linelst.GetSize()); for(i=0;i<linelst.GetSize();i++) { t=-(linelst[i].IsSelected+2); fprintf(fp,"%i %i %i %i\n",i,linelst[i].n0,linelst[i].n1,t); } // write out list of holes; for(i=0,j=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") { fprintf(fp,"%i %.17g %.17g\n",k,blocklist[i].x,blocklist[i].y); k++; } // figure out a good default mesh size for block labels where // mesh size isn't explicitly specified CComplex xx,yy; double DefaultMeshSize; if (nodelst.GetSize()>1) { xx=nodelst[0].CC(); yy=xx; for(k=0;k<nodelst.GetSize();k++) { if (nodelst[k].x<Re(xx)) xx.re=nodelst[k].x; if (nodelst[k].y<Im(xx)) xx.im=nodelst[k].y; if (nodelst[k].x>Re(yy)) yy.re=nodelst[k].x; if (nodelst[k].y>Im(yy)) yy.im=nodelst[k].y; } DefaultMeshSize=pow((double)(abs(yy - xx) / BoundingBoxFraction), (double)2); if (!theApp.d_SmartMesh) DefaultMeshSize=abs(yy-xx); } else DefaultMeshSize=-1; // write out regional attributes fprintf(fp,"%i\n",blocklist.GetSize()-j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType!="<No Mesh>") { fprintf(fp,"%i %.17g %.17g ",k,blocklist[i].x,blocklist[i].y); fprintf(fp,"%i ",k+1); if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize)) fprintf(fp,"%.17g\n",blocklist[i].MaxArea); else fprintf(fp,"%.17g\n",DefaultMeshSize); k++; } fclose(fp); //call triangle CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; char CommandLine[512]; sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I %s", BinDir,MinAngle,rootname); STARTUPINFO StartupInfo = {0}; PROCESS_INFORMATION ProcessInfo; StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.dwFlags = STARTF_USESHOWWINDOW; StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE; if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)){ if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE); else{ DWORD ExitCode; hProc=ProcessInfo.hProcess; do{ GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode); ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); Sleep(1); } while(ExitCode==STILL_ACTIVE); hProc=NULL; } } else { MsgBox("Couldn't spawn triangle.exe"); Undo(); UnselectAll(); return FALSE; } DWORD ExitCode; GetExitCodeProcess( ProcessInfo.hProcess, // handle to the process &ExitCode // address to receive termination status ); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); if (ExitCode!=0) { MsgBox("Call to triangle was unsuccessful"); Undo(); UnselectAll(); return FALSE; } //#endif // So far, so good. Now, read back in the .edge file // to make sure the points in the segments and arc // segments are ordered in a consistent way so that // the (anti)periodic boundary conditions can be applied. //read meshlines; plyname=pn.Left(pn.ReverseFind('.')) + ".edge"; if((fp=fopen(plyname,"rt"))==NULL){ MsgBox("Call to triangle was unsuccessful"); Undo(); UnselectAll(); return FALSE; } fgets(instring,1024,fp); sscanf(instring,"%i",&k); UnselectAll(); // abuse IsSelected again to keep a // tally of how many subsegments each // entity is sliced into. ptlst.SetSize(linelist.GetSize()+arclist.GetSize()); for(i=0;i<ptlst.GetSize();i++) ptlst[i].t=0; for(i=0;i<k;i++) { fgets(instring,1024,fp); sscanf(instring,"%i %i %i %i",&l,&n0,&n1,&j); if(j!=0) { j=-(j+2); // convert back to the `right' numbering // store a reference line that we can use to // determine whether or not this is a // boundary segment w/out re-running triangle. if (ptlst[j].t==0) { ptlst[j].t=1; if(n0<n1){ ptlst[j].x=n0; ptlst[j].y=n1; } else{ ptlst[j].x=n1; ptlst[j].y=n0; } } if(j<linelist.GetSize()) { // deal with segments linelist[j].IsSelected++; if((linelist[j].n0==n1) || (linelist[j].n1==n0)) { t=linelist[j].n0; linelist[j].n0=linelist[j].n1; linelist[j].n1=t; } } else{ // deal with arc segments; // Can't just flip the point order with // impunity in the arc segments, so we flip // a marker which denotes which side the // normal is on. j=j-(int) linelist.GetSize(); arclist[j].IsSelected++; if((arclist[j].n0==n1) || (arclist[j].n1==n0)) arclist[j].NormalDirection=FALSE; if((arclist[j].n0==n0) || (arclist[j].n1==n1)) arclist[j].NormalDirection=TRUE; } } } fclose(fp); // figure out which segments / arcsegments are on the // boundary and force an appropriate mesh density on // these based on how many divisions are in the first // trial meshing of the domain. // paw through the element list to find out how many // elements each reference segment appears in. If a // segment is on the boundary, it ought to appear in just // one element. Otherwise, it appears in two. plyname=pn.Left(pn.ReverseFind('.')) + ".ele"; if((fp=fopen(plyname,"rt"))==NULL){ MsgBox("Call to triangle was unsuccessful"); Undo(); UnselectAll(); return FALSE; } fgets(instring,1024,fp); sscanf(instring,"%i",&k); for(i=0;i<k;i++) { fgets(instring,1024,fp); sscanf(instring,"%i %i %i %i",&j,&n0,&n1,&n2); // Sort out the three nodes... if (n0>n1) { n=n0; n0=n1; n1=n; } if (n1>n2) { n=n1; n1=n2; n2=n; } if (n0>n1) { n=n0; n0=n1; n1=n; } // now, check to see if any of the test segments // are sides of this node... for(j=0;j<ptlst.GetSize();j++) { if ((n0==ptlst[j].x) && (n1==ptlst[j].y)) ptlst[j].t--; if ((n0==ptlst[j].x) && (n2==ptlst[j].y)) ptlst[j].t--; if ((n1==ptlst[j].x) && (n2==ptlst[j].y)) ptlst[j].t--; } } fclose(fp); // impose "new" mesh constraints on bdry arcs and segments.... for(i=0;i<linelist.GetSize();i++) { if (ptlst[i].t==0) linelist[i].MaxSideLength= LineLength(i)/((double) linelist[i].IsSelected); } for(i=0;i<arclist.GetSize();i++) { if (ptlst[i+linelist.GetSize()].t==0){ // alter maxsidelength, but do it in such // a way that it carries only 4 significant // digits. There's no use in carrying double // precision here, because it looks crappy // when you open up the arc segment to see // its properties. char kludge[32]; arclist[i].MaxSideLength= arclist[i].ArcLength/((double) arclist[i].IsSelected); sprintf(kludge,"%.1e",arclist[i].MaxSideLength); sscanf(kludge,"%lf",&arclist[i].MaxSideLength); } } ptlst.RemoveAll(); // want to impose explicit discretization only on // the boundary arcs and segments. After the meshing // is done, spacing on boundary segments should be // restored to the value that was there before meshing // was called, but the arc segments should keep the // "new" MaxSideLength--this is used in other places // and must always be consistent with the the mesh. // Now, do a shitload of checking to make sure that // the PBCs haven't been defined by the user // in a messed up way. // First, search through defined bc's for periodic ones; for(i=0;i<lineproplist.GetSize();i++) { if ((lineproplist[i].BdryFormat==4) || (lineproplist[i].BdryFormat==5)){ pbc.BdryName=lineproplist[i].BdryName; pbc.BdryFormat=lineproplist[i].BdryFormat-4; // 0 for pbc, 1 for apbc pbclst.Add(pbc); } } for(i=0;i<linelist.GetSize();i++) { for(j=0;j<pbclst.GetSize();j++) { if (pbclst[j].BdryName==linelist[i].BoundaryMarker) { // A pbc or apbc can only be applied to 2 segs // at a time. If it is applied to multiple segs // at the same time, flag it and kick it out. if (pbclst[j].nseg==2) { MsgBox("An (anti)periodic BC is assigned to more than two segments"); Undo(); UnselectAll(); return FALSE; } pbclst[j].seg[pbclst[j].nseg]=i; pbclst[j].nseg++; } } } for(i=0;i<arclist.GetSize();i++) { for(j=0;j<pbclst.GetSize();j++) { if (pbclst[j].BdryName==arclist[i].BoundaryMarker) { // A pbc or apbc can only be applied to 2 arcs // at a time. If it is applied to multiple arcs // at the same time, flag it and kick it out. if (pbclst[j].narc==2) { MsgBox("An (anti)periodic BC is assigned to more than two arcs"); Undo(); UnselectAll(); return FALSE; } pbclst[j].seg[pbclst[j].narc]=i; pbclst[j].narc++; } } } j=0; while(j<pbclst.GetSize()) { // check for a bc that is a mix of arcs and segments. // this is an error, and it should get flagged. if ((pbclst[j].nseg>0) && (pbclst[j].narc>0)) { MsgBox("Can't mix arcs and segments for (anti)periodic BCs"); Undo(); UnselectAll(); return FALSE; } // remove any periodic BC's that aren't actually in play if((pbclst[j].nseg<2) && (pbclst[j].narc<2)) pbclst.RemoveAt(j); else j++; } for(j=0;j<pbclst.GetSize();j++) { // check to see if adjoining entries are applied // to objects of compatible size/shape, and // reconcile meshing on the objects. // for segments: if(pbclst[j].nseg>0){ // make sure that lines are pretty much the same length if(fabs(LineLength(pbclst[j].seg[0]) -LineLength(pbclst[j].seg[1]))>1.e-06) { MsgBox("(anti)periodic BCs applied to dissimilar segments"); Undo(); UnselectAll(); return FALSE; } // make sure that both lines have the same spacing double len1,len2,len; len1=linelist[pbclst[j].seg[0]].MaxSideLength; len2=linelist[pbclst[j].seg[1]].MaxSideLength; if(len1<=0) len1=len2; if(len2<=0) len2=len1; len=min(len1,len2); linelist[pbclst[j].seg[0]].MaxSideLength=len; linelist[pbclst[j].seg[1]].MaxSideLength=len; } // for arc segments: if(pbclst[j].narc>0){ // make sure that arcs are pretty much the // same arc length if(fabs(arclist[pbclst[j].seg[0]].ArcLength -arclist[pbclst[j].seg[1]].ArcLength)>1.e-06) { MsgBox("(anti)periodic BCs applied to dissimilar arc segments"); Undo(); UnselectAll(); return FALSE; } // make sure that both lines have the same spacing double len1,len2,len; len1=arclist[pbclst[j].seg[0]].MaxSideLength; len2=arclist[pbclst[j].seg[1]].MaxSideLength; len=min(len1,len2); arclist[pbclst[j].seg[0]].MaxSideLength=len; arclist[pbclst[j].seg[1]].MaxSideLength=len; } } // write out new poly and write out adjacent // boundary nodes in a separate .pbc file. // kludge things a bit and use IsSelected to denote // whether or not a line or arc has already been processed. UnselectAll(); nodelst.RemoveAll(); linelst.RemoveAll(); // first, add in existing nodes for(n=0;n<nodelist.GetSize();n++) nodelst.Add(nodelist[n]); for(n=0;n<pbclst.GetSize();n++) { if (pbclst[n].nseg!=0) // if this pbc is a line segment... { int s0,s1; CNode node0,node1; s0=pbclst[n].seg[0]; s1=pbclst[n].seg[1]; linelist[s0].IsSelected=TRUE; linelist[s1].IsSelected=TRUE; // make is so that first point on first line // maps to first point on second line... t=linelist[s1].n1; linelist[s1].n1=linelist[s1].n0; linelist[s1].n0=t; // store number of sub-segments in k if (linelist[s0].MaxSideLength==-1) k=1; else{ a0=nodelist[linelist[s0].n0].CC(); a1=nodelist[linelist[s0].n1].CC(); b0=nodelist[linelist[s1].n0].CC(); b1=nodelist[linelist[s1].n1].CC(); z=abs(a1-a0); k=(int) ceil(z/linelist[s0].MaxSideLength); } // add segment end points to the list; pt.x=linelist[s0].n0; pt.y=linelist[s1].n0; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); pt.x=linelist[s0].n1; pt.y=linelist[s1].n1; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); if (k==1){ // catch the case in which the line // doesn't get subdivided. linelst.Add(linelist[s0]); linelst.Add(linelist[s1]); } else{ segm=linelist[s0]; for(j=0;j<k;j++) { a2=a0+(a1-a0)*((double) (j+1))/((double) k); b2=b0+(b1-b0)*((double) (j+1))/((double) k); node0.x=a2.re; node0.y=a2.im; node1.x=b2.re; node1.y=b2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node0); segm.n0=linelist[s0].n0; segm.n1=l; linelst.Add(segm); pt.x=l; l=(int) nodelst.GetSize(); nodelst.Add(node1); segm.n0=linelist[s1].n0; segm.n1=l; linelst.Add(segm); pt.y=l; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); } else if(j==(k-1)) { // last subdivision--no ptlst // entry associated with this one. l=(int) nodelst.GetSize()-2; segm.n0=l; segm.n1=linelist[s0].n1; linelst.Add(segm); l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[s1].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node0); nodelst.Add(node1); segm.n0=l-2; segm.n1=l; linelst.Add(segm); segm.n0=l-1; segm.n1=l+1; linelst.Add(segm); pt.x=l; pt.y=l+1; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); } } } } else{ // if this pbc is an arc segment... int s0,s1; int p0[2],p1[2]; CNode node0,node1; CComplex bgn0,bgn1,c0,c1,d0,d1; double r0,r1; s0=pbclst[n].seg[0]; s1=pbclst[n].seg[1]; arclist[s0].IsSelected=TRUE; arclist[s1].IsSelected=TRUE; k=(int) ceil(arclist[s0].ArcLength/arclist[s0].MaxSideLength); segm.BoundaryMarker=arclist[s0].BoundaryMarker; segm.InConductor=arclist[s0].InConductor; GetCircle(arclist[s0],c0,r0); GetCircle(arclist[s1],c1,r1); if (arclist[s0].NormalDirection==0){ bgn0=nodelist[arclist[s0].n0].CC(); d0=exp(I*arclist[s0].ArcLength*PI/(((double) k)*180.)); p0[0]=arclist[s0].n0; p0[1]=arclist[s0].n1; } else{ bgn0=nodelist[arclist[s0].n1].CC(); d0=exp(-I*arclist[s0].ArcLength*PI/(((double) k)*180.)); p0[0]=arclist[s0].n1; p0[1]=arclist[s0].n0; } if (arclist[s1].NormalDirection!=0){ bgn1=nodelist[arclist[s1].n0].CC(); d1=exp(I*arclist[s1].ArcLength*PI/(((double) k)*180.)); p1[0]=arclist[s1].n0; p1[1]=arclist[s1].n1; } else{ bgn1=nodelist[arclist[s1].n1].CC(); d1=exp(-I*arclist[s1].ArcLength*PI/(((double) k)*180.)); p1[0]=arclist[s1].n1; p1[1]=arclist[s1].n0; } // add arc segment end points to the list; pt.x=p0[0]; pt.y=p1[0]; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); pt.x=p0[1]; pt.y=p1[1]; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); if (k==1){ // catch the case in which the line // doesn't get subdivided. segm.n0=p0[0]; segm.n1=p0[1]; linelst.Add(segm); segm.n0=p1[0]; segm.n1=p1[1]; linelst.Add(segm); } else{ for(j=0;j<k;j++) { bgn0=(bgn0-c0)*d0+c0; node0.x=bgn0.re; node0.y=bgn0.im; bgn1=(bgn1-c1)*d1+c1; node1.x=bgn1.re; node1.y=bgn1.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node0); segm.n0=p0[0]; segm.n1=l; linelst.Add(segm); pt.x=l; l=(int) nodelst.GetSize(); nodelst.Add(node1); segm.n0=p1[0]; segm.n1=l; linelst.Add(segm); pt.y=l; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); } else if(j==(k-1)) { // last subdivision--no ptlst // entry associated with this one. l=(int) nodelst.GetSize()-2; segm.n0=l; segm.n1=p0[1]; linelst.Add(segm); l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=p1[1]; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node0); nodelst.Add(node1); segm.n0=l-2; segm.n1=l; linelst.Add(segm); segm.n0=l-1; segm.n1=l+1; linelst.Add(segm); pt.x=l; pt.y=l+1; pt.t=pbclst[n].BdryFormat; ptlst.Add(pt); } } } } } // Then, do the rest of the lines and arcs in the // "normal" way and write .poly file. // discretize input segments for(i=0;i<linelist.GetSize();i++) if(linelist[i].IsSelected==FALSE){ a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y); a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y); if (linelist[i].MaxSideLength==-1) k=1; else{ z=abs(a1-a0); k=(int) ceil(z/linelist[i].MaxSideLength); } segm=linelist[i]; if (k==1) // default condition where discretization on line is not specified { if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(segm); // line is too short to add extra points else{ // add extra points at a distance of dL from the ends of the line. // this forces Triangle to finely mesh near corners for(j=0;j<3;j++) { if(j==0) { a2=a0+dL*(a1-a0)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } if(j==1) { a2=a1+dL*(a0-a1)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } if(j==2) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } } } } else{ for(j=0;j<k;j++) { a2=a0+(a1-a0)*((double) (j+1))/((double) k); node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } } // discretize input arc segments for(i=0;i<arclist.GetSize();i++) if(arclist[i].IsSelected==FALSE){ a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y); k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength); segm.BoundaryMarker=arclist[i].BoundaryMarker; segm.InConductor =arclist[i].InConductor; GetCircle(arclist[i],c,R); a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.)); if(k==1){ segm.n0=arclist[i].n0; segm.n1=arclist[i].n1; linelst.Add(segm); } else for(j=0;j<k;j++) { a2=(a2-c)*a1+c; node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=arclist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=arclist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } // create correct output filename; pn = GetPathName(); plyname=pn.Left(pn.ReverseFind('.')) + ".poly"; // check to see if we are ready to write a datafile; if ((fp=fopen(plyname,"wt"))==NULL){ MsgBox("Couldn't write to specified .poly file"); Undo(); UnselectAll(); return FALSE; } // write out node list fprintf(fp,"%i 2 0 1\n",nodelst.GetSize()); for(i=0;i<nodelst.GetSize();i++) { // include boundary marker; for(j=0,t=0;j<nodeproplist.GetSize();j++) if(nodeproplist[j].PointName==nodelst[i].BoundaryMarker) t=j+2; // include conductor number; for(j=0;j<circproplist.GetSize();j++) if(circproplist[j].CircName==nodelst[i].InConductor) t+=((j+1)*0x10000); fprintf(fp,"%i %.17g %.17g %i\n",i,nodelst[i].x,nodelst[i].y,t); } // write out segment list fprintf(fp,"%i 1\n",linelst.GetSize()); for(i=0;i<linelst.GetSize();i++) { // include boundary marker; for(j=0,t=0;j<lineproplist.GetSize();j++) if(lineproplist[j].BdryName==linelst[i].BoundaryMarker) t=-(j+2); // include conductor number; for(j=0;j<circproplist.GetSize();j++) if(circproplist[j].CircName==linelst[i].InConductor) t-=((j+1)*0x10000); fprintf(fp,"%i %i %i %i\n",i,linelst[i].n0,linelst[i].n1,t); } // write out list of holes; for(i=0,j=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") { fprintf(fp,"%i %.17g %.17g\n",k,blocklist[i].x,blocklist[i].y); k++; } // write out regional attributes fprintf(fp,"%i\n",blocklist.GetSize()-j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType!="<No Mesh>") { fprintf(fp,"%i %.17g %.17g ",k,blocklist[i].x,blocklist[i].y); fprintf(fp,"%i ",k+1); if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize)) fprintf(fp,"%.17g\n",blocklist[i].MaxArea); else fprintf(fp,"%.17g\n",DefaultMeshSize); k++; } fclose(fp); // Make sure to prune out any duplications in the ptlst for(k=0;k<ptlst.GetSize();k++) ptlst[k].Order(); k=0; while((k+1) < ptlst.GetSize()) { j=k+1; while(j < ptlst.GetSize()) { if((ptlst[k].x==ptlst[j].x) && (ptlst[k].y==ptlst[j].y)) ptlst.RemoveAt(j); else j++; } k++; } // used to have a check to eliminate the case where a point // and its companion are the same point--actually, this shouldn't // be a problem just to let the algorithm deal with this // as usual. // One last error check--each point must have only one companion point. // however, it would be possible to screw up in the definition of the BCs // so that this isn't the case. Look through the points to try and catch // this one. /* // let's let this check go away for a minute... for(k=0,n=FALSE;(k+1)<ptlst.GetSize();k++) { for(j=k+1;j<ptlst.GetSize();j++) { if(ptlst[k].x==ptlst[j].x) n=TRUE; if(ptlst[k].y==ptlst[j].y) n=TRUE; if(ptlst[k].x==ptlst[j].y) n=TRUE; if(ptlst[k].y==ptlst[j].x) n=TRUE; } } if (n==TRUE){ MsgBox("Nonphysical (anti)periodic boundary assignments"); Undo(); UnselectAll(); return FALSE; } */ // write out a pbc file containing a list of linked nodes plyname=pn.Left(pn.ReverseFind('.')) + ".pbc"; if ((fp=fopen(plyname,"wt"))==NULL){ MsgBox("Couldn't write to specified .pbc file"); Undo(); UnselectAll(); return FALSE; } fprintf(fp,"%i\n",ptlst.GetSize()); for(k=0;k<ptlst.GetSize();k++) fprintf(fp,"%i %i %i %i\n",k,ptlst[k].x,ptlst[k].y,ptlst[k].t); fclose(fp); // call triangle with -Y flag. rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I -Y %s", BinDir,MinAngle,rootname); StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.dwFlags = STARTF_USESHOWWINDOW; StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE; if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)){ if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE); else{ DWORD ExitCode; hProc=ProcessInfo.hProcess; do{ GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode); ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); Sleep(1); } while(ExitCode==STILL_ACTIVE); hProc=NULL; } } else { MsgBox("Couldn't spawn triangle.exe"); Undo(); UnselectAll(); return FALSE; } GetExitCodeProcess( ProcessInfo.hProcess, // handle to the process &ExitCode // address to receive termination status ); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); if (ExitCode!=0) { MsgBox("Call to triangle was unsuccessful"); Undo(); UnselectAll(); return FALSE; } UnselectAll(); // Now restore boundary segment discretizations that have // been mucked up in the process... for(i=0;i<linelist.GetSize();i++) linelist[i]=undolinelist[i]; // and save the latest version of the document to make sure // any changes to arc discretization get propagated into // the solution description.... OnSaveDocument(pn); return TRUE; }
// What we do in the normal case is OnWritePoly BOOL ChdrawDoc::OnWritePoly() { FILE *fp; int i,j,k,l,t; double z,R,dL; CComplex a0,a1,a2,c; CString s; CArray< CNode, CNode&> nodelst; CArray< CSegment, CSegment&> linelst; CArray< CArcSegment, CArcSegment&> arclst; CArray< CBlockLabel, CBlockLabel&> blocklst; CNode node; CSegment segm; nodelst.RemoveAll(); linelst.RemoveAll(); // calculate length used to kludge fine meshing near input node points for (i=0,z=0;i<linelist.GetSize();i++) { a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y); a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y); z += (abs(a1-a0)/((double) linelist.GetSize())); } dL=z/LineFraction; // copy node list as it is; for(i=0;i<nodelist.GetSize();i++) nodelst.Add(nodelist[i]); // discretize input segments for(i=0;i<linelist.GetSize();i++) { a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y); a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y); if (linelist[i].MaxSideLength==-1) k=1; else{ z=abs(a1-a0); k=(int) ceil(z/linelist[i].MaxSideLength); } if (k==1) // default condition where discretization on line is not specified { if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(linelist[i]); // line is too short to add extra points else{ // add extra points at a distance of dL from the ends of the line. // this forces Triangle to finely mesh near corners segm=linelist[i]; for(j=0;j<3;j++) { if(j==0) { a2=a0+dL*(a1-a0)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } if(j==1) { a2=a1+dL*(a0-a1)/abs(a1-a0); node.x=a2.re; node.y=a2.im; l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } if(j==2) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } } } } else{ segm=linelist[i]; for(j=0;j<k;j++) { a2=a0+(a1-a0)*((double) (j+1))/((double) k); node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=linelist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=linelist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } } // discretize input arc segments for(i=0;i<arclist.GetSize();i++) { a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y); k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength); segm.BoundaryMarker=arclist[i].BoundaryMarker; segm.InConductor=arclist[i].InConductor; GetCircle(arclist[i],c,R); a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.)); if(k==1){ segm.n0=arclist[i].n0; segm.n1=arclist[i].n1; linelst.Add(segm); } else for(j=0;j<k;j++) { a2=(a2-c)*a1+c; node.x=a2.re; node.y=a2.im; if(j==0){ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=arclist[i].n0; segm.n1=l; linelst.Add(segm); } else if(j==(k-1)) { l=(int) nodelst.GetSize()-1; segm.n0=l; segm.n1=arclist[i].n1; linelst.Add(segm); } else{ l=(int) nodelst.GetSize(); nodelst.Add(node); segm.n0=l-1; segm.n1=l; linelst.Add(segm); } } } // create correct output filename; CString pn = GetPathName(); CString plyname=pn.Left(pn.ReverseFind('.')) + ".poly"; // check to see if we are ready to write a datafile; if ((fp=fopen(plyname,"wt"))==NULL){ MsgBox("Couldn't write to specified .poly file"); return FALSE; } // write out node list fprintf(fp,"%i 2 0 1\n",nodelst.GetSize()); for(i=0;i<nodelst.GetSize();i++) { // include boundary marker for(j=0,t=0;j<nodeproplist.GetSize();j++) if(nodeproplist[j].PointName==nodelst[i].BoundaryMarker) t=j+2; // include conductor number; for(j=0;j<circproplist.GetSize();j++) if(circproplist[j].CircName==nodelst[i].InConductor) t+=((j+1)*0x10000); fprintf(fp,"%i %.17g %.17g %i\n",i,nodelst[i].x,nodelst[i].y,t); } // write out segment list fprintf(fp,"%i 1\n",linelst.GetSize()); for(i=0;i<linelst.GetSize();i++) { // include boundary marker for(j=0,t=0;j<lineproplist.GetSize();j++) if(lineproplist[j].BdryName==linelst[i].BoundaryMarker) t=-(j+2); // include conductor number; for(j=0;j<circproplist.GetSize();j++) if(circproplist[j].CircName==linelst[i].InConductor) t-=((j+1)*0x10000); fprintf(fp,"%i %i %i %i\n",i,linelst[i].n0,linelst[i].n1,t); } // write out list of holes; for(i=0,j=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType=="<No Mesh>") { fprintf(fp,"%i %.17g %.17g\n",k,blocklist[i].x,blocklist[i].y); k++; } // figure out a good default mesh size for block labels where // mesh size isn't explicitly specified CComplex xx,yy; double DefaultMeshSize; if (nodelst.GetSize() > 1) { xx = nodelst[0].CC(); yy = xx; for (k = 0; k < nodelst.GetSize(); k++) { if (nodelst[k].x < Re(xx)) xx.re = nodelst[k].x; if (nodelst[k].y < Im(xx)) xx.im = nodelst[k].y; if (nodelst[k].x > Re(yy)) yy.re = nodelst[k].x; if (nodelst[k].y > Im(yy)) yy.im = nodelst[k].y; } DefaultMeshSize = pow((double)(abs(yy - xx) / BoundingBoxFraction), (double)2); if (!theApp.d_SmartMesh) DefaultMeshSize = abs(yy - xx); } else DefaultMeshSize=-1; // write out regional attributes fprintf(fp,"%i\n",blocklist.GetSize()-j); for(i=0,k=0;i<blocklist.GetSize();i++) if(blocklist[i].BlockType!="<No Mesh>") { fprintf(fp,"%i %.17g %.17g ",k,blocklist[i].x,blocklist[i].y); fprintf(fp,"%i ",k+1); if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize)) fprintf(fp,"%.17g\n",blocklist[i].MaxArea); else fprintf(fp,"%.17g\n",DefaultMeshSize); k++; } fclose(fp); // write out a trivial pbc file plyname=pn.Left(pn.ReverseFind('.')) + ".pbc"; if ((fp=fopen(plyname,"wt"))==NULL){ MsgBox("Couldn't write to specified .pbc file"); return FALSE; } fprintf(fp,"0\n"); fclose(fp); //call triangle CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; char CommandLine[512]; sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I %s", BinDir,MinAngle,rootname); STARTUPINFO StartupInfo = {0}; PROCESS_INFORMATION ProcessInfo; StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.dwFlags = STARTF_USESHOWWINDOW; StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE; if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)){ if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE); else { DWORD ExitCode; hProc=ProcessInfo.hProcess; do{ GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode); ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); Sleep(1); } while(ExitCode==STILL_ACTIVE); hProc=NULL; } } else { MsgBox("Couldn't spawn triangle.exe"); return FALSE; } DWORD ExitCode; GetExitCodeProcess( ProcessInfo.hProcess, // handle to the process &ExitCode // address to receive termination status ); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); if (ExitCode!=0) { MsgBox("Call to triangle was unsuccessful"); return FALSE; } return TRUE; }