// FemmeDoc.cpp : implementation file // #include "stdafx.h" #include "femm.h" #include "FemmeDoc.h" #include "FemmeView.h" #include "probdlg.h" #include "PtProp.h" #include "OpBlkDlg.h" #include "OpNodeDlg.h" #include "OpSegDlg.h" #include "OpArcSegDlg.h" #include "OpGrp.h" #include "ArcDlg.h" #include "ExteriorProps.h" extern void *pFemmeDoc; extern lua_State *lua; extern CLuaConsoleDlg *LuaConsole; extern BOOL bLinehook; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CFemmeDoc IMPLEMENT_DYNCREATE(CFemmeDoc, CDocument) BEGIN_MESSAGE_MAP(CFemmeDoc, CDocument) //{{AFX_MSG_MAP(CFemmeDoc) 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() CFemmeDoc::CFemmeDoc() { // 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_freq=0; d_depth=1; d_coord=0; d_length=0; d_type=0; d_solver=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(); } BOOL CFemmeDoc::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; Frequency=d_freq; Precision=d_prec; MinAngle=d_minangle; SmartMesh=theApp.d_SmartMesh; Depth=d_depth; LengthUnits=d_length; ProblemType=d_type; ACSolver=d_solver; Coords=d_coord; ProblemNote="Add comments here."; PrevSoln=""; PrevType = 0; extRo=extRi=extZo=0; // reset view to default attributes CFemmeView *pView; POSITION pos; pos=GetFirstViewPosition(); if (pos!=NULL){ pView=(CFemmeView *)GetNextView(pos); // if (pView!=NULL) pView->OnNewDocument(); } return TRUE; } CFemmeDoc::~CFemmeDoc() { pFemmeDoc=NULL; } ///////////////////////////////////////////////////////////////////////////// // CFemmeDoc diagnostics #ifdef _DEBUG void CFemmeDoc::AssertValid() const { CDocument::AssertValid(); } void CFemmeDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CFemmeDoc serialization void CFemmeDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // CFemmeDoc commands void CFemmeDoc::OnDefineProblem() { probdlg pDlg; // Send present parameter values to the dialog // pDlg.m_rji=TheDoc->vi[0]; pDlg.probtype = ProblemType; pDlg.m_problem_note = ProblemNote; pDlg.m_frequency = Frequency; pDlg.m_precision = Precision; pDlg.m_minangle = MinAngle; pDlg.bsmart = SmartMesh; pDlg.m_depth = Depth; pDlg.lengthunits = LengthUnits; pDlg.solver = ACSolver; pDlg.m_prevsoln = PrevSoln; pDlg.prevtype = PrevType; // Display dialog and collect data if(pDlg.DoModal()==IDOK) { Frequency = pDlg.m_frequency; Precision = pDlg.m_precision; MinAngle = pDlg.m_minangle; SmartMesh = pDlg.bsmart; ProblemNote = pDlg.m_problem_note; ProblemType = pDlg.probtype; LengthUnits = pDlg.lengthunits; Depth = pDlg.m_depth; ACSolver = pDlg.solver; PrevSoln = pDlg.m_prevsoln; if (PrevSoln.GetLength()==0) PrevType=0; else PrevType = pDlg.prevtype; } } void CFemmeDoc::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 CFemmeDoc::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 CFemmeDoc::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 CFemmeDoc::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; 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; linelist[i].Hidden=zDlg.m_hide; linelist[i].InGroup=zDlg.m_ingroup; } } } } void CFemmeDoc::OpArcSegDlg() { int i,j,k,nselected; COpArcSegDlg zDlg; // check to see how many (if any) arcs are selected. for(i=0,k=0,nselected=0;i0) MProp.BHdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); for(j=0;jMid(n1+1,n2-n1-1); return (t+n2+1); } BOOL CFemmeDoc::OnOpenDocument(LPCTSTR lpszPathName) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; // make sure old document is cleared out... OnNewDocument(); FILE *fp; int i,j,k,t; int vers=0; char s[1024],q[1024]; char *v; CPointProp PProp; CBoundaryProp BProp; CMaterialProp MProp; CCircuit CProp; CNode node; CSegment segm; CArcSegment asegm; CBlockLabel blk; if ((fp=fopen(lpszPathName,"rt"))==NULL){ MsgBox("Couldn't read from specified .fem file"); return FALSE; } // Check to see if this is an old-version femm datafile fgets(s,1024,fp); if (strncmp(s,"Frequency",8)==0){ fclose(fp); return OldOnOpenDocument(lpszPathName); } else rewind(fp); // Go back to beginning of the file; // hook to catch old files where depth wasn't defined: Depth=-1; // parse the file while (fgets(s,1024,fp)!=NULL) { if (sscanf(s,"%s",q)==EOF) q[0]=NULL; // int _strnicmp( const char *string1, const char *string2, size_t count ); // Deal with flag for file format version if( _strnicmp(q,"[format]",8)==0 ){ v=StripKey(s); double dblvers; sscanf(v,"%lf",&dblvers); vers = (int) (10.*dblvers + 0.5); if(vers>40) MsgBox("This file is from a newer version of FEMM\nThis file may contain attributes not\nsupported by this version of FEMM"); q[0]=NULL; } // Frequency of the problem if( _strnicmp(q,"[frequency]",11)==0){ v=StripKey(s); sscanf(v,"%lf",&Frequency); 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; } // Solver to use for AC problems if( _strnicmp(q,"[acsolver]",8)==0){ v=StripKey(s); sscanf(v,"%i",&ACSolver); q[0]=NULL; // 0 == successive approx // 1 == newton } // 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; } // 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; } // name of previous solution file for AC incremental permeability solution // Previous Solution File if( _strnicmp(q,"[prevsoln]",10)==0){ int i; 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; if (PrevSoln.GetLength()==0) PrevType=0; q[0]=NULL; } // Type of previous solution file if (_strnicmp(q, "[prevtype]", 10) == 0) { v = StripKey(s); sscanf(v, "%i", &PrevType); q[0] = NULL; // 0 == None // 1 == Incremental // 2 == Frozen } // 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.Jp=0; PProp.Ap=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,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.Ap.re); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.Ap.im); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.Jp.re); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.Jp.im); 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.A0=0.; BProp.A1=0.; BProp.A2=0.; BProp.phi=0.; BProp.Mu=0.; BProp.Sig=0.; BProp.c0=0.; BProp.c1=0.; BProp.InnerAngle=0; BProp.OuterAngle=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,"",8)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.Mu); q[0]=NULL; } if( _strnicmp(q,"",11)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.Sig); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.A0); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.A1); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.A2); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.phi); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c0.re); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c1.re); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c0.im); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c1.im); q[0]=NULL; } if( _strnicmp(q,"",12)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.InnerAngle); q[0]=NULL; } if( _strnicmp(q,"",12)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.OuterAngle); 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.mu_x=1.; MProp.mu_y=1.; // permeabilities, relative MProp.H_c=0.; // magnetization, A/m MProp.Jsrc=0; // applied current density, MA/m^2 MProp.Cduct=0.; // conductivity of the material, MS/m MProp.Lam_d=0.; // lamination thickness, mm MProp.Theta_hn=0.; // hysteresis angle, degrees MProp.Theta_hx=0.; MProp.Theta_hy=0.; MProp.LamFill=1.; // lamination fill factor; MProp.LamType=0; // type of lamination; MProp.NStrands=0; MProp.WireD=0; MProp.BHpoints=0; MProp.BHdata=NULL; 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,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.mu_x); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.mu_y); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.H_c); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Jsrc.re); q[0]=NULL; } if( _strnicmp(q,"",6)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Jsrc.im); q[0]=NULL; } if( _strnicmp(q,"",7)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Cduct); q[0]=NULL; } if( _strnicmp(q,"",7)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Theta_hn); if(vers==30){ MProp.Theta_hx=MProp.Theta_hn; MProp.Theta_hy=MProp.Theta_hn; } q[0]=NULL; } if( _strnicmp(q,"",8)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Theta_hx); q[0]=NULL; } if( _strnicmp(q,"",8)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Theta_hy); q[0]=NULL; } if( _strnicmp(q,"",7)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.Lam_d); q[0]=NULL; } if( _strnicmp(q,"",8)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.LamFill); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ v=StripKey(s); sscanf(v,"%i",&MProp.LamType); q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); sscanf(v,"%i",&MProp.NStrands); q[0]=NULL; } if( _strnicmp(q,"",7)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.WireD); q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); sscanf(v,"%i",&MProp.BHpoints); if (MProp.BHpoints>0) { MProp.BHdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); for(j=0;j",9)==0){ blockproplist.Add(MProp); MProp.BHpoints=0; q[0]=NULL; } // Circuit Properties if( _strnicmp(q,"",14)==0){ CProp.CircName="New Circuit"; CProp.Amps=0.; CProp.CircType=0; q[0]=NULL; } if( _strnicmp(q,"",13)==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,"",14)==0){ double inval; v=StripKey(s); sscanf(v,"%lf",&inval); CProp.Amps+=inval; q[0]=NULL; } if( _strnicmp(q,"",14)==0){ double inval; v=StripKey(s); sscanf(v,"%lf",&inval); CProp.Amps+=(I*inval); q[0]=NULL; } if( _strnicmp(q,"",13)==0){ v=StripKey(s); sscanf(v,"%i",&CProp.CircType); q[0]=NULL; } if( _strnicmp(q,"",12)==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].Jp.re); fprintf(fp, " = %.17g\n", nodeproplist[i].Jp.im); fprintf(fp, " = %.17g\n", nodeproplist[i].Ap.re); fprintf(fp, " = %.17g\n", nodeproplist[i].Ap.im); fprintf(fp, " \n"); } fprintf(fp,"[BdryProps] = %i\n",(int) 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].A0); fprintf(fp," = %.17g\n",lineproplist[i].A1); fprintf(fp," = %.17g\n",lineproplist[i].A2); fprintf(fp," = %.17g\n",lineproplist[i].phi); fprintf(fp," = %.17g\n",lineproplist[i].c0.re); fprintf(fp," = %.17g\n",lineproplist[i].c0.im); fprintf(fp," = %.17g\n",lineproplist[i].c1.re); fprintf(fp," = %.17g\n",lineproplist[i].c1.im); fprintf(fp," = %.17g\n",lineproplist[i].Mu); fprintf(fp," = %.17g\n",lineproplist[i].Sig); fprintf(fp," = %.17g\n",lineproplist[i].InnerAngle); fprintf(fp," = %.17g\n",lineproplist[i].OuterAngle); fprintf(fp," \n"); } fprintf(fp,"[BlockProps] = %i\n",(int) blockproplist.GetSize()); for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) blockproplist[i].BlockName); fprintf(fp," = %.17g\n",blockproplist[i].mu_x); fprintf(fp," = %.17g\n",blockproplist[i].mu_y); fprintf(fp," = %.17g\n",blockproplist[i].H_c); fprintf(fp," = %.17g\n",blockproplist[i].Theta_m); fprintf(fp," = %.17g\n",blockproplist[i].Jsrc.re); fprintf(fp," = %.17g\n",blockproplist[i].Jsrc.im); fprintf(fp," = %.17g\n",blockproplist[i].Cduct); fprintf(fp," = %.17g\n",blockproplist[i].Lam_d); fprintf(fp," = %.17g\n",blockproplist[i].Theta_hn); fprintf(fp," = %.17g\n",blockproplist[i].Theta_hx); fprintf(fp," = %.17g\n",blockproplist[i].Theta_hy); fprintf(fp," = %i\n",blockproplist[i].LamType); fprintf(fp," = %.17g\n",blockproplist[i].LamFill); fprintf(fp," = %i\n",blockproplist[i].NStrands); fprintf(fp," = %.17g\n",blockproplist[i].WireD); fprintf(fp," = %i\n",blockproplist[i].BHpoints); for(j=0;j\n"); } fprintf(fp,"[CircuitProps] = %i\n",(int) circproplist.GetSize()); for(i=0;i\n"); fprintf(fp," = \"%s\"\n", (const char *) circproplist[i].CircName); fprintf(fp," = %.17g\n",circproplist[i].Amps.Re()); fprintf(fp," = %.17g\n",circproplist[i].Amps.Im()); fprintf(fp," = %i\n",circproplist[i].CircType); fprintf(fp," \n"); } // write out node list fprintf(fp,"[NumPoints] = %i\n",(int) 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",(int) blocklist.GetSize()-j); for(i=0,k=0;i0) fprintf(fp,"%.17g ",sqrt(4.*blocklist[i].MaxArea/PI)); else fprintf(fp,"-1 "); for(j=0,t=0;j0) fprintf(fp," \"%s\"", (const char *) blocklist[i].MagDirFctn); fprintf(fp,"\n"); k++; } fclose(fp); return TRUE; } BOOL CFemmeDoc::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 CFemmeDoc::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,"",11)==0) { v=StripKey(s); sscanf(v,"%lf",&d_freq); 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; } if( _strnicmp(q,"",8)==0) { v=StripKey(s); sscanf(v,"%i",&d_solver); q[0]=NULL; } } fclose(fp); return TRUE; } return FALSE; } //-------------------------------------------------------------- void CFemmeView::lnuMakeMesh() { OnMakeMesh(); } void CFemmeView::lnu_purge_mesh() { OnPurgemesh(); } void CFemmeView::lnu_show_mesh() { OnShowMesh(); } void CFemmeView::lnu_analyze(int bShow) { if (bShow) bLinehook=HiddenLua; else bLinehook=NormalLua; OnMenuAnalyze(); } void CFemmeView::lua_zoomnatural() { OnZoomNatural(); } void CFemmeView::lua_zoomout() { OnZoomOut(); } void CFemmeView::lua_zoomin() { OnZoomIn(); } BOOL CFemmeDoc::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 CFemmeDoc::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 CFemmeDoc::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)