// implementation of various incarnations of calls // to triangle from the ChdrawDoc class #include "stdafx.h" #include "femm.h" #include "hdrawDoc.h" #include "hd_probdlg.h" #include "hd_PtProp.h" #include "hd_OpBlkDlg.h" #include "hd_OpNodeDlg.h" #include "hd_OpSegDlg.h" #include "hd_OpArcSegDlg.h" #include "OpGrp.h" #include "ArcDlg.h" extern BOOL bLinehook; extern lua_State *lua; extern HANDLE hProc; double ChdrawDoc::LineLength(int i) { return abs(nodelist[linelist[i].n0].CC()- nodelist[linelist[i].n1].CC()); } BOOL ChdrawDoc::HasPeriodicBC() { BOOL flag=FALSE; int i,j,k; for(i=0;i=0){ if ((lineproplist[k].BdryFormat==4) || (lineproplist[k].BdryFormat==5)) { flag=TRUE; break; } } } if (flag==TRUE) return TRUE; // If we've gotten this far, we still need to check the // arc segments. for(i=0;i=0){ if ((lineproplist[k].BdryFormat==4) || (lineproplist[k].BdryFormat==5)) { flag=TRUE; break; } } } // Finally, we're done. The value of flag now reflects // the judgement on whether or not we have periodic // and/or antiperiodic boundaries. return flag; } // 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; int bSmartMesh=theApp.session_SmartMesh; if (bSmartMesh<0) bSmartMesh=SmartMesh; nodelst.RemoveAll(); linelst.RemoveAll(); // calculate length used to kludge fine meshing near input node points for (i=0,z=0;i") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i") { 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;kRe(yy)) yy.re=nodelst[k].x; if (nodelst[k].y>Im(yy)) yy.im=nodelst[k].y; } DefaultMeshSize=pow(abs(yy-xx)/BoundingBoxFraction,2.); if (!bSmartMesh) DefaultMeshSize=abs(yy-xx); } else DefaultMeshSize=-1; // write out regional attributes fprintf(fp,"%i\n",blocklist.GetSize()-j); for(i=0,k=0;i0) && (blocklist[i].MaxArealine_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. Check for small angles."); return FALSE; } 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; int bSmartMesh=theApp.session_SmartMesh; if (bSmartMesh<0) bSmartMesh=SmartMesh; 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") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i") { 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;kRe(yy)) yy.re=nodelst[k].x; if (nodelst[k].y>Im(yy)) yy.im=nodelst[k].y; } DefaultMeshSize=pow(abs(yy-xx)/BoundingBoxFraction,2.); if (!bSmartMesh) DefaultMeshSize=abs(yy-xx); } else DefaultMeshSize=-1; // write out regional attributes fprintf(fp,"%i\n",blocklist.GetSize()-j); for(i=0,k=0;i0) && (blocklist[i].MaxArealine_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. Check for small angles."); 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;in1) { 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;j0) && (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;j0){ // 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") j++; fprintf(fp,"%i\n",j); for(i=0,k=0;i") { 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;i0) && (blocklist[i].MaxArealine_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. Check for small angles."); Undo(); UnselectAll(); return FALSE; } UnselectAll(); // Now restore boundary segment discretizations that have // been mucked up in the process... for(i=0;i