// hdrawDoc.cpp : implementation of the ChdrawDoc class // #include "stdafx.h" #include "femm.h" #include "hdrawDoc.h" #include "hdrawView.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" #include "ExteriorProps.h" extern void *phdrawDoc; extern lua_State *lua; extern BOOL bLinehook; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // ChdrawDoc IMPLEMENT_DYNCREATE(ChdrawDoc, CDocument) BEGIN_MESSAGE_MAP(ChdrawDoc, CDocument) //{{AFX_MSG_MAP(ChdrawDoc) ON_COMMAND(ID_DEFINE_PROBLEM, OnDefineProblem) ON_COMMAND(ID_EDIT_MATPROPS, OnEditMatprops) ON_COMMAND(ID_EDIT_PTPROPS, OnEditPtprops) ON_COMMAND(ID_EDIT_SEGPROPS, OnEditSegprops) ON_COMMAND(ID_EDIT_CIRCPROPS, OnEditCircprops) ON_COMMAND(ID_EDIT_EXTERIOR, OnEditExterior) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // ChdrawDoc construction/destruction ChdrawDoc::ChdrawDoc() { // set some default values for starting up rendering // things properly FirstDraw=FALSE; NoDraw=FALSE; // set up some default document behaviors d_prec=1.e-08; d_minangle=DEFAULT_MINIMUM_ANGLE; d_depth=1; d_coord=0; d_length=0; d_type=0; // Figure out what directory the executables // are in, so we can call `triangle' if we need to. BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); // read document default behaviors from disk ScanPreferences(); // fire up lua initalise_lua(); // initialize the data in the document OnNewDocument(); } ChdrawDoc::~ChdrawDoc() { if (phdrawDoc==this) phdrawDoc=NULL; } BOOL ChdrawDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; // clear out all current lines, nodes, and block labels nodelist.RemoveAll(); linelist.RemoveAll(); arclist.RemoveAll(); blocklist.RemoveAll(); undonodelist.RemoveAll(); undolinelist.RemoveAll(); undoarclist.RemoveAll(); undoblocklist.RemoveAll(); nodeproplist.RemoveAll(); lineproplist.RemoveAll(); blockproplist.RemoveAll(); circproplist.RemoveAll(); meshnode.RemoveAll(); meshline.RemoveAll(); greymeshline.RemoveAll(); // set problem attributes to generic ones; Precision=d_prec; PrevSoln=""; dT=0; MinAngle=d_minangle; SmartMesh=theApp.d_SmartMesh; Depth=d_depth; LengthUnits=d_length; ProblemType=d_type; Coords=d_coord; ProblemNote="Add comments here."; extRo=extRi=extZo=0; // reset view to default attributes ChdrawView *pView; POSITION pos; pos=GetFirstViewPosition(); if (pos!=NULL){ pView=(ChdrawView *)GetNextView(pos); if (pView!=NULL) pView->OnNewDocument(); } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // ChdrawDoc serialization void ChdrawDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // ChdrawDoc diagnostics #ifdef _DEBUG void ChdrawDoc::AssertValid() const { CDocument::AssertValid(); } void ChdrawDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // ChdrawDoc commands void ChdrawDoc::OnDefineProblem() { hdCProbDlg pDlg; // Send present parameter values to the dialog // pDlg.m_rji=TheDoc->vi[0]; pDlg.probtype = ProblemType; pDlg.m_problem_note = ProblemNote; pDlg.m_precision = Precision; pDlg.m_minangle = MinAngle; pDlg.bsmart = SmartMesh; pDlg.m_prevsoln = PrevSoln; pDlg.m_dt = dT; pDlg.m_depth = Depth; pDlg.lengthunits = LengthUnits; // Display dialog and collect data if(pDlg.DoModal()==IDOK) { Precision = pDlg.m_precision; MinAngle = pDlg.m_minangle; SmartMesh = pDlg.bsmart; PrevSoln = pDlg.m_prevsoln; ProblemNote = pDlg.m_problem_note; ProblemType = pDlg.probtype; LengthUnits = pDlg.lengthunits; Depth = pDlg.m_depth; dT = pDlg.m_dt; } } void ChdrawDoc::UnselectAll() { int i; for(i=0;i < nodelist.GetSize();i++) nodelist[i].IsSelected=FALSE; for(i=0;i < linelist.GetSize();i++) linelist[i].IsSelected=FALSE; for(i=0;i < blocklist.GetSize();i++) blocklist[i].IsSelected=FALSE; for(i=0;i < arclist.GetSize();i++) arclist[i].IsSelected=FALSE; } BOOL ChdrawDoc::AddNode(double x, double y, double d) { int i,k; CNode pt; CSegment segm; CArcSegment asegm; CComplex c,a0,a1,a2; double R; // test to see if ``too close'' to existing node... for (i=0;i newnodes; newnodes.RemoveAll(); // don't add if line is degenerate if (n0==n1) return FALSE; // don't add if the line is already in the list; for(i=0;i0) for(k=0;kp1.re) p1.re=nodelist[i].x; if(nodelist[i].yp1.im) p1.im=nodelist[i].y; } t=abs(p1-p0)*CLOSE_ENOUGH; } } else t=tol; for(i=0;iR) return 0; l=sqrt( R*R - Im(v)*Im(v)); // Im(v) is distance between line and center... if ((l/R) < 1.e-05){ // case where line is very close to a tangent; p[i]=p0 + Re(v)*t; // make it be a tangent. R=Re((p[i]-p0)/t); z=arg((p[i]-c)/(a0-c)); if ((R>0) && (R0.) && (z0) && (R0.) && (z0) && (R0.) && (zR0+R1) || (d<1.e-08)) return 0; // directly eliminate case where there can't // be any crossings.... l=sqrt((R0+R1-d)*(d+R0-R1)*(d-R0+R1)*(d+R0+R1))/(2.*d); c=1.+(R0/d)*(R0/d)-(R1/d)*(R1/d); t=(c1-c0)/d; tta0=arc0.ArcLength*PI/180; tta1=arc1.ArcLength*PI/180; p[i]=c0 + (c*d/2.+ I*l)*t; // first possible intersection; z0=arg((p[i]-c0)/(a0-c0)); z1=arg((p[i]-c1)/(a1-c1)); if ((z0>0.) && (z00.) && (z10.) && (z00.) && (z1 newnodes; double R,d,dmin,t; 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;i0) for(k=0;k0) for(k=0;kp1.re) p1.re=nodelist[i].x; if(nodelist[i].yp1.im) p1.im=nodelist[i].y; } t=abs(p1-p0)*CLOSE_ENOUGH; } } else t=tol; for(i=0;i0) && (z1.) t=1.; if (t<0.) t=0.; x[2]=x[0]+t*(x[1]-x[0]); y[2]=y[0]+t*(y[1]-y[0]); return sqrt((p-x[2])*(p-x[2]) + (q-y[2])*(q-y[2])); } int ChdrawDoc::ClosestSegment(double x, double y) { double d0,d1; int i,j; if(linelist.GetSize()==0) return -1; j=0; d0=ShortestDistance(x,y,0); for(i=0;i=1.) && (Re(q1)>=1.)) return FALSE; if ((Im(q0)<=0.) && (Im(q1)<=0.)) return FALSE; if ((Im(q0)>=0.) && (Im(q1)>=0.)) return FALSE; // compute intersection z=Im(q0)/Im(q0-q1); // check to see if the line segments intersect at a point sufficiently // far from the segment endpoints.... x=Re((1.0 - z)*q0 + z*q1); if((x < ee) || (x > (1.0 - ee))) return FALSE; // return resulting intersection point p0 = (1.0 - z)*nodelist[n0].CC() + z*nodelist[n1].CC(); *xi=Re(p0); *yi=Im(p0); return TRUE; } BOOL ChdrawDoc::DeleteSelectedBlockLabels() { int i=0; BOOL flag=FALSE; if (blocklist.GetSize() > 0) do{ if(blocklist[i].IsSelected==TRUE){ blocklist.RemoveAt(i,1); flag=TRUE; } else i++; } while (i 0) do{ if(linelist[i].IsSelected==TRUE){ linelist.RemoveAt(i,1); flag=TRUE; } else i++; } while (i 0) do{ if(arclist[i].IsSelected==TRUE){ arclist.RemoveAt(i,1); flag=TRUE; } else i++; } while (i 0) do{ if(nodelist[i].IsSelected==TRUE){ flag=TRUE; // first remove all lines that contain the point; for(j=0;ji) linelist[j].n0--; if (linelist[j].n1>i) linelist[j].n1--; } // update arcs to point to the new node numbering for(j=0;ji) arclist[j].n0--; if (arclist[j].n1>i) arclist[j].n1--; } } else i++; } while (i1) zDlg.m_isdefault=FALSE; // find average block size; for(i=0,j=0,a=0.;ia) a=blocklist[i].MaxArea; zDlg.m_sidelength=floor(2.e07*sqrt(a/PI)+0.5)/1.e07; zDlg.pblockproplist=&blockproplist; zDlg.pcircproplist=&circproplist; if (nselected==1){ if(blocklist[k].BlockType=="") zDlg.cursel=1; else for(i=0,zDlg.cursel=0;i=0) ms+=linelist[k].MaxSideLength; j++; if (linelist[i].Hidden==TRUE) zDlg.m_hide=TRUE; } ms/=(double) j; zDlg.plineproplist=&lineproplist; zDlg.pcircproplist=&circproplist; if (nselected==1){ for(i=0,zDlg.cursel=0;i0) linelist[i].MaxSideLength=zDlg.m_linemeshsize; else zDlg.m_linemeshsize=-1; } if (zDlg.cursel==0) linelist[i].BoundaryMarker=""; else linelist[i].BoundaryMarker=lineproplist[zDlg.cursel-1].BdryName; if (zDlg.condsel==0) linelist[i].InConductor=""; else linelist[i].InConductor=circproplist[zDlg.condsel-1].CircName; linelist[i].Hidden=zDlg.m_hide; linelist[i].InGroup=zDlg.m_ingroup; } } } } void ChdrawDoc::OpArcSegDlg() { int i,j,k,nselected; hdCOpArcSegDlg zDlg; // check to see how many (if any) arcs are selected. for(i=0,k=0,nselected=0;i33) MsgBox("File is from a newer version of FEMM\nThis file may contain attributes not\nsupported by this version of FEMM"); q[0]=NULL; } // Depth in the into-the-page direction if( _strnicmp(q,"[depth]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&Depth); q[0]=NULL; } // Required solver precision if( _strnicmp(q,"[precision]",11)==0){ v=StripKey(s); sscanf(v,"%lf",&Precision); q[0]=NULL; } // Minimum Angle Constraint for finite element mesh if( _strnicmp(q,"[minangle]",10)==0){ v=StripKey(s); sscanf(v,"%lf",&MinAngle); q[0]=NULL; } // Smart Mesh flag if( _strnicmp(q,"[dosmartmesh]",13)==0){ v=StripKey(s); sscanf(v,"%i",&SmartMesh); q[0]=NULL; } // Units of length used by the problem if( _strnicmp(q,"[lengthunits]",13)==0){ v=StripKey(s); sscanf(v,"%s",q); if( _strnicmp(q,"inches",6)==0) LengthUnits=0; else if( _strnicmp(q,"millimeters",11)==0) LengthUnits=1; else if( _strnicmp(q,"centimeters",1)==0) LengthUnits=2; else if( _strnicmp(q,"mils",4)==0) LengthUnits=4; else if( _strnicmp(q,"microns",6)==0) LengthUnits=5; else if( _strnicmp(q,"meters",6)==0) LengthUnits=3; q[0]=NULL; } // Problem Type (planar or axisymmetric) if( _strnicmp(q,"[problemtype]",13)==0){ v=StripKey(s); sscanf(v,"%s",q); if( _strnicmp(q,"planar",6)==0) ProblemType=0; if( _strnicmp(q,"axisymmetric",3)==0) ProblemType=1; q[0]=NULL; } // Previous Solution File if( _strnicmp(q,"[prevsoln]",10)==0){ v=StripKey(s); // have to do this carefully to accept a filename with spaces k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } PrevSoln=v; q[0]=NULL; } // Coordinates (cartesian or polar) if( _strnicmp(q,"[coordinates]",13)==0){ v=StripKey(s); sscanf(v,"%s",q); if ( _strnicmp(q,"cartesian",4)==0) Coords=0; if ( _strnicmp(q,"polar",5)==0) Coords=1; q[0]=NULL; } // Comments if (_strnicmp(q,"[comment]",9)==0){ v=StripKey(s); // put in carriage returns; k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } ProblemNote=v; q[0]=NULL; } // timestep if( _strnicmp(q,"[dt]",4)==0){ v=StripKey(s); sscanf(v,"%lf",&dT); q[0]=NULL; } // properties for axisymmetric external region if( _strnicmp(q,"[extzo]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extZo); q[0]=NULL; } if( _strnicmp(q,"[extro]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extRo); q[0]=NULL; } if( _strnicmp(q,"[extri]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extRi); q[0]=NULL; } // Point Properties if( _strnicmp(q,"",11)==0){ PProp.PointName="New Point Property"; PProp.T=0; PProp.qp=0; q[0]=NULL; } if( _strnicmp(q,"",11)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } PProp.PointName=v; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.T); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.qp); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ nodeproplist.Add(PProp); q[0]=NULL; } // Boundary Properties; if( _strnicmp(q,"",11)==0){ BProp.BdryName="New Boundary"; BProp.BdryFormat=0; BProp.Tset=0; BProp.Tinf=0; BProp.qs=0; BProp.beta=0; BProp.h=0; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } BProp.BdryName=v; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); sscanf(v,"%i",&BProp.BdryFormat); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.Tset); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.qs); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.beta); q[0]=NULL; } if( _strnicmp(q,"",3)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.h); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.Tinf); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ lineproplist.Add(BProp); q[0]=NULL; } // Block Properties; if( _strnicmp(q,"",12)==0){ MProp.BlockName="New Material"; MProp.Kx=1.; MProp.Ky=1.; MProp.Kt=3; MProp.qv=0.; MProp.npts=0; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } MProp.BlockName=v; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Kx); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Ky); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Kt); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.qv); q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); sscanf(v,"%i",&MProp.npts); if (MProp.npts>0) { for(j=0;j",9)==0){ blockproplist.Add(MProp); q[0]=NULL; } // Circuit Properties if( _strnicmp(q,"",16)==0){ CProp.CircName="New Conductor"; CProp.T=0.; CProp.q=0.; CProp.CircType=0; q[0]=NULL; } if( _strnicmp(q,"",15)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } CProp.CircName=v; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.T); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.q); q[0]=NULL; } if( _strnicmp(q,"",15)==0){ v=StripKey(s); sscanf(v,"%i",&CProp.CircType); q[0]=NULL; } if( _strnicmp(q,"",14)==0){ circproplist.Add(CProp); q[0]=NULL; } // Points list; if(_strnicmp(q,"[numpoints]",11)==0){ v=StripKey(s); sscanf(v,"%i",&k); for(i=0;i0) { blk.BlockType=""; blk.MaxArea=0; blk.InGroup=0; for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) nodeproplist[i].PointName); fprintf(fp," = %.17g\n",nodeproplist[i].T); fprintf(fp," = %.17g\n",nodeproplist[i].qp); fprintf(fp," \n"); } fprintf(fp,"[BdryProps] = %i\n",lineproplist.GetSize()); for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) lineproplist[i].BdryName); fprintf(fp," = %i\n",lineproplist[i].BdryFormat); fprintf(fp," = %.17g\n",lineproplist[i].Tset); fprintf(fp," = %.17g\n",lineproplist[i].qs); fprintf(fp," = %.17g\n",lineproplist[i].beta); fprintf(fp," = %.17g\n",lineproplist[i].h); fprintf(fp," = %.17g\n",lineproplist[i].Tinf); fprintf(fp," \n"); } fprintf(fp,"[BlockProps] = %i\n",blockproplist.GetSize()); for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) blockproplist[i].BlockName); fprintf(fp," = %.17g\n",blockproplist[i].Kx); fprintf(fp," = %.17g\n",blockproplist[i].Ky); fprintf(fp," = %.17g\n",blockproplist[i].Kt); fprintf(fp," = %.17g\n",blockproplist[i].qv); if (blockproplist[i].npts>0) { fprintf(fp," = %i\n",blockproplist[i].npts); for (j=0;j\n"); } fprintf(fp,"[ConductorProps] = %i\n",circproplist.GetSize()); for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) circproplist[i].CircName); fprintf(fp," = %.17g\n",circproplist[i].T); fprintf(fp," = %.17g\n",circproplist[i].q); fprintf(fp," = %i\n",circproplist[i].CircType); fprintf(fp," \n"); } // write out node list fprintf(fp,"[NumPoints] = %i\n",nodelist.GetSize()); for(i=0;i") j++; fprintf(fp,"[NumHoles] = %i\n",j); for(i=0,k=0;i") { fprintf(fp,"%.17g %.17g %i\n",blocklist[i].x,blocklist[i].y, blocklist[i].InGroup); k++; } // write out regional attributes fprintf(fp,"[NumBlockLabels] = %i\n",blocklist.GetSize()-j); for(i=0,k=0;i0) fprintf(fp,"%.17g ",sqrt(4.*blocklist[i].MaxArea/PI)); else fprintf(fp,"-1 "); fprintf(fp,"%i %i\n",blocklist[i].InGroup, blocklist[i].IsExternal+blocklist[i].IsDefault); k++; } fclose(fp); return TRUE; } BOOL ChdrawDoc::LoadMesh() { int i,j,k,q,nl; CString pathname,rootname,infile; FILE *fp; char s[1024]; // clear out the old mesh... meshnode.RemoveAll(); meshline.RemoveAll(); greymeshline.RemoveAll(); pathname=GetPathName(); if (pathname.GetLength()==0){ MsgBox("No mesh to display"); return FALSE; } rootname=pathname.Left(pathname.ReverseFind('.')); //read meshnodes; infile=rootname+".node"; if((fp=fopen(infile,"rt"))==NULL){ MsgBox("No mesh to display"); return FALSE; } fgets(s,1024,fp); sscanf(s,"%i",&k); meshnode.SetSize(k); CNode node; for(i=0;in[q]) { segm.x=n[p]; segm.y=n[q]; if (j!=0) meshline.SetAt(nl++,segm); else greymeshline.Add(segm); } } } meshline.SetSize(nl); fclose(fp); // clear out temporary files infile=rootname+".ele"; DeleteFile(infile); infile=rootname+".node"; DeleteFile(infile); infile=rootname+".edge"; DeleteFile(infile); infile=rootname+".pbc"; DeleteFile(infile); infile=rootname+".poly"; DeleteFile(infile); return TRUE; } void ChdrawDoc::UpdateUndo() { int i; undonodelist.RemoveAll(); undolinelist.RemoveAll(); undoarclist.RemoveAll(); undoblocklist.RemoveAll(); for(i=0;i tempnodelist; CArray< CSegment, CSegment&> templinelist; CArray< CArcSegment, CArcSegment&> temparclist; CArray< CBlockLabel, CBlockLabel&> tempblocklist; tempnodelist.RemoveAll(); templinelist.RemoveAll(); temparclist.RemoveAll(); tempblocklist.RemoveAll(); for(i=0;i",11)==0) { v=StripKey(s); sscanf(v,"%lf",&d_prec); q[0]=NULL; } if( _strnicmp(q,"",10)==0) { v=StripKey(s); sscanf(v,"%lf",&d_minangle); q[0]=NULL; } if( _strnicmp(q,"",7)==0) { v=StripKey(s); sscanf(v,"%lf",&d_depth); q[0]=NULL; } if( _strnicmp(q,"",13)==0) { v=StripKey(s); sscanf(v,"%i",&d_coord); q[0]=NULL; } if( _strnicmp(q,"",13)==0) { v=StripKey(s); sscanf(v,"%i",&d_length); q[0]=NULL; } if( _strnicmp(q,"",13)==0) { v=StripKey(s); sscanf(v,"%i",&d_type); q[0]=NULL; } } fclose(fp); return TRUE; } return FALSE; } BOOL ChdrawDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // TODO: Add your specialized code here and/or call the base class if (bLinehook!=FALSE) return TRUE; return CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } void ChdrawDoc::OnEditExterior() { // TODO: Add your command handler code here CExteriorProps dlg; dlg.m_Ro=extRo; dlg.m_Ri=extRi; dlg.m_Zo=extZo; if(dlg.DoModal()==IDOK) { extRo=dlg.m_Ro; extRi=dlg.m_Ri; extZo=dlg.m_Zo; } } BOOL ChdrawDoc::CanCreateRadius(int n) { // check to see if a selected point, specified by n, can be // converted to a radius. To be able to be converted to a radius, // the point must be an element of either 2 lines, 2 arcs, or // 1 line and 1 arc. int j,k; for(k=0,j=0;k=0){ b=sqrt(b); v[j++]=p[k]+I*b*(p[k]-c)/abs(p[k]-c); v[j++]=p[k]-I*b*(p[k]-c)/abs(p[k]-c); } } // locations of the centerpoints that could be for the radius that // we are looking for are stored in v. We now need to paw through // them to find the one solution that we are after. u=(p1-p0)/abs(p1-p0); // unit vector along the line for(m=0,k=0;k(r/10000.)) { m++; if (m==2) break; } } if (m==0) return FALSE; // But there are also special cases where there could be two answers. // We then pick the solution that has the center point closest to the point to be removed. if(m>1) { if (abs(v[0]-p0)(179.*DEG)) return FALSE; // check to see if the points are in the wrong order // and fix it if they are. if (phi<0){ p0=p1; p1=p2; p2=p0; p0=nodelist[n].CC(); k=seg[0]; seg[0]=seg[1]; seg[1]=k; phi=fabs(phi); } len = r/tan(phi/2.); // distance from p0 to the tangency point; // catch the case where the desired radius is too big to fit; if ((abs(p1-p0)(r0/10000.)) { j++; if (j==2) break; } } // There could be no valid solutions... if (j==0) return FALSE; // But there are also special cases where there could be two answers. // We then pick the solution that has the center point closest to the point to be removed. if(j>1) { if (abs(p[0]-c0)