commit 7cbb4974785c5d32fb8e57a7b562765fd409ef26 Author: jess Date: Tue May 12 04:16:16 2026 -0700 Init. I deleted the entire GUI, then did what was required just to compile the lua, backend and math engines with clang. It all compiles now. They designed well in the first place, so it was much easier than many projects would have been. I can now begin with the GUI, I will write it in Rust and ICED. Should be fun, I think. diff --git a/belasolv/StdAfx.h b/belasolv/StdAfx.h new file mode 100644 index 0000000..3fb652a --- /dev/null +++ b/belasolv/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h: portable shim pulling in compat/afx.h for BOOL, CString, and stdlib basics. +#pragma once + +#define _CRT_SECURE_NO_WARNINGS +#include + +int MsgBox(const char* sz, ...); +int MsgBox(const std::string& s); diff --git a/belasolv/belasolv.cpp b/belasolv/belasolv.cpp new file mode 100644 index 0000000..f5d5da0 --- /dev/null +++ b/belasolv/belasolv.cpp @@ -0,0 +1,82 @@ +// belasolv.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "belasolv.h" +#include "belasolvDlg.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CbelasolvApp + +BEGIN_MESSAGE_MAP(CbelasolvApp, CWinApp) + //{{AFX_MSG_MAP(CbelasolvApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CbelasolvApp construction + +CbelasolvApp::CbelasolvApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +CbelasolvApp::~CbelasolvApp() +{ + +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CbelasolvApp object + +CbelasolvApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CbelasolvApp initialization + +BOOL CbelasolvApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CbelasolvDlg dlg; + m_pMainWnd = &dlg; + + dlg.ComLine=m_lpCmdLine; + // SetDialogBkColor(); + _beginthread( old_main, 0, (void *) &dlg ); + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/belasolv/belasolv.h b/belasolv/belasolv.h new file mode 100644 index 0000000..44d9ea2 --- /dev/null +++ b/belasolv/belasolv.h @@ -0,0 +1,4 @@ +// solver entry point. +#pragma once + +void old_main(void *inptr); diff --git a/belasolv/belasolvDlg.cpp b/belasolv/belasolvDlg.cpp new file mode 100644 index 0000000..d251127 --- /dev/null +++ b/belasolv/belasolvDlg.cpp @@ -0,0 +1,96 @@ +// belasolvDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "belasolv.h" +#include "belasolvDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CbelasolvDlg dialog + +CbelasolvDlg::CbelasolvDlg(CWnd* pParent /*=NULL*/) + : CDialog(CbelasolvDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CbelasolvDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CbelasolvDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CbelasolvDlg) + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CbelasolvDlg, CDialog) + //{{AFX_MSG_MAP(CbelasolvDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CbelasolvDlg message handlers + +BOOL CbelasolvDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + return FALSE; // return TRUE unless you set the focus to a control +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CbelasolvDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CbelasolvDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CbelasolvDlg::OnOK() +{ +} diff --git a/belasolv/belasolvDlg.h b/belasolv/belasolvDlg.h new file mode 100644 index 0000000..690f0e4 --- /dev/null +++ b/belasolv/belasolvDlg.h @@ -0,0 +1,20 @@ +// MFC-free CbelasolvDlg with empty progress, label, and window-update calls. +#pragma once + +#include + +struct CProgressStub { void SetPos(int) {} }; + +class CbelasolvDlg { +public: + CProgressStub m_prog1; + CProgressStub m_prog2; + void* m_hWnd = nullptr; + std::string ComLine; + void SetDlgItemText(int, const char*) {} + void SetWindowText(const char*) {} + void UpdateWindow() {} + int InvalidateRect(void* = nullptr, int = 1) { return 1; } +}; + +extern CbelasolvDlg* TheView; diff --git a/belasolv/cuthill.cpp b/belasolv/cuthill.cpp new file mode 100644 index 0000000..c1d1b97 --- /dev/null +++ b/belasolv/cuthill.cpp @@ -0,0 +1,266 @@ +// does Cuthill-McKee algorithm as described in Hoole; + +#include +#include +#include +#include +#include "belasolv.h" +#include "belasolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +#define muo 1.2566370614359173e-6 + +BOOL CFemmeDocCore::SortElements() +{ + // Comb Sort -- see http://en.wikipedia.org/wiki/Comb_sort + int *Score; + int i,j,k,gap; + CElement e; + + Score=(int*)calloc(NumEls,sizeof(int)); + + for(k=0;k 1) + { + gap=(gap*10)/13; + if ((gap==10) || (gap==9)) gap=11; + + } + + //a single "comb" over the input list + for(j=0,i=0;(j+gap)Score[j+gap]) + { + k=j+gap; + i=Score[k];Score[k]=Score[j];Score[j]=i; + e=meshele[k];meshele[k]=meshele[j];meshele[j]=e; + i=1; + } + } + }while((gap>1)&&(i>0)); + + + free(Score); + return TRUE; +} + +BOOL CFemmeDocCore::Cuthill() +{ + + FILE *fp; + int i,j,k,n0,n1,n; + int newwide,*newnum,**ocon; + int *numcon,*nxtnum; + CNode swap; + char infile[256]; + + // allocate storage + nxtnum=(int *)calloc(NumNodes,sizeof(int)); + newnum=(int *)calloc(NumNodes,sizeof(int)); + numcon=(int *)calloc(NumNodes,sizeof(int)); + ocon=(int **)calloc(NumNodes,sizeof(int *)); + // initialize node array; + for(i=0;inewwide) + { + newwide=abs(newnum[n0]-ocon[n0][i]); + } + } + + BandWidth=newwide+1; + // } + + // free up the variables that we needed during the routine.... + free(numcon); + free(nxtnum); + free(ocon[0]); + free(ocon); + + // new mapping remains in newnum; + // apply this mapping to elements first. + for(i=0;i +#include +#include +#include +#include +#include "belasolv.h" +#include "belasolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDocCore construction/destruction + +CFemmeDocCore::CFemmeDocCore() +{ + TheView=NULL; + Precision=NULL; + LengthUnits=NULL; + ProblemType=NULL; + Coords=NULL; + BandWidth=NULL; + NumNodes=NULL; + NumEls=NULL; + NumBlockProps=NULL; + NumPBCs=NULL; + NumLineProps=NULL; + NumPointProps=NULL; + NumCircProps=NULL; + NumBlockLabels=NULL; + + meshnode=NULL; + meshele=NULL; + blockproplist=NULL; + lineproplist=NULL; + nodeproplist=NULL; + circproplist=NULL; + labellist=NULL; + pbclist=NULL; + PathName=NULL; + + extRo=extRi=extZo=NULL; +} + +CFemmeDocCore::~CFemmeDocCore() +{ + // This space for rent. +} + +void CFemmeDocCore::CleanUp() +{ + if (meshnode!=NULL) free(meshnode); + if (meshele!=NULL) free(meshele); + if (blockproplist!=NULL) free(blockproplist); + if (lineproplist!=NULL) free(lineproplist); + if (nodeproplist!=NULL) free(nodeproplist); + if (circproplist!=NULL) free(circproplist); + if (labellist!=NULL) free(labellist); + if (pbclist!=NULL) free(pbclist); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDocCore commands + +char* StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) nodeproplist=(CPointProp *)calloc(k,sizeof(CPointProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + PProp.V=0; + PProp.qp=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.V); + 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[NumPointProps]=PProp; + NumPointProps++; + q[0]=NULL; + } + + // Boundary Properties; + if( _strnicmp(q,"[bdryprops]",11)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) lineproplist=(CBoundaryProp *)calloc(k,sizeof(CBoundaryProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + BProp.BdryFormat=0; + BProp.V=0; + BProp.qs=0; + BProp.c0=0; + BProp.c1=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0){ + v=StripKey(s); + sscanf(v,"%i",&BProp.BdryFormat); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c1); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + lineproplist[NumLineProps]=BProp; + NumLineProps++; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"[blockprops]",12)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) blockproplist=(CMaterialProp *)calloc(k,sizeof(CMaterialProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0){ + MProp.ex=1; + MProp.ey=1; // permittivity, relative + MProp.qv=1; // charge density, C/m^3 + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.qv); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + blockproplist[NumBlockProps]=MProp; + NumBlockProps++; + q[0]=NULL; + } + + // Conductor Properties + if( _strnicmp(q,"[conductorprops]",16)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) circproplist=(CCircuit *)calloc(k,sizeof(CCircuit)); + q[0]=NULL; + } + + if( _strnicmp(q,"",16)==0){ + CProp.V=0; + CProp.q=0; + CProp.CircType=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V); + 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[NumCircProps]=CProp; + NumCircProps++; + q[0]=NULL; + } + + // read in regional attributes + if(_strnicmp(q,"[numblocklabels]",13)==0){ + int i; + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) labellist=(CBlockLabel *)calloc(k, sizeof(CBlockLabel)); + NumBlockLabels=k; + for(i=0;i1){ + // strip off point BC number; + j=n & 0xffff; + j=j-2; + if (j<0) j=-1; + + // strip off Conductor number + n= (n - (n & 0xffff))/0x10000 - 1; + } + else{ + j=-1; + n=-1; + } + node.bc=j; + node.InConductor=n; + + // convert all lengths to internal working units of mm + node.x*=c[LengthUnits]; + node.y*=c[LengthUnits]; + + meshnode[i]=node; + } + fclose(fp); + + //read in periodic boundary conditions; + sprintf(infile,"%s.pbc",PathName); + if((fp=fopen(infile,"rt"))==NULL){ + return FALSE; + } + fgets(s,1024,fp); + sscanf(s,"%i",&k); NumPBCs=k; + + if (k!=0) pbclist=(CCommonPoint *)calloc(k,sizeof(CCommonPoint)); + CCommonPoint pbc; + for(i=0;i=0) + { + meshnode[n0].InConductor=n; + meshnode[n1].InConductor=n; + } + } + else j=-1; + + if (j>=0) + { + // search through elements to find one containing the line; + // set corresponding edge equal to the bc number + for(q=0,n=FALSE;q +#include +#include +#include +#include +#include "belasolv.h" +#include "belasolvDlg.h" +#include "spars.h" +#include "mesh.h" +#include "FemmeDocCore.h" + +void old_main(void *inptr) +{ + CbelasolvDlg *TheView; + CFemmeDocCore Doc; + char PathName[256]; + CFileDialog *fname_dia; + char outstr[1024]; + int i; + + TheView=(CbelasolvDlg *) inptr; + + // get the name of the file to be processed, + // either from argv or from the user + if (__argc<2){ + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "belaview datafile (*.fee) | *.fee; *.FEE | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + MsgBox("No file name!"); + exit(0); + } + + CString fname=fname_dia->GetPathName(); + fname=fname.Left(fname.GetLength()-4); + strcpy(PathName,fname); + delete[] fname_dia; + } + else strcpy(PathName,__argv[1]); + + Doc.PathName=PathName; + Doc.TheView=TheView; + + // load problem geometry + if (Doc.OnOpenDocument()!=TRUE){ + MsgBox("problem loading .fee file"); + exit(7); + } + + // load mesh + if (Doc.LoadMesh()!=TRUE){ + MsgBox("problem loading mesh"); + exit(2); + } + + // label the dialog to report which problem is being solved + char PaneText[256]; + char *ProbName; + ProbName=PathName; + for(i=0;i< (int) strlen(PathName);i++) + if(PathName[i]=='\\') ProbName=PathName+i; + if (strlen(PathName)>0){ + ProbName++; + sprintf(PaneText,"%s - belasolve",ProbName); + } + + while(!IsWindow(TheView->m_hWnd)) Sleep(1); + TheView->SetWindowText(PaneText); + + // renumber using Cuthill-McKee + TheView->SetDlgItemText(IDC_STATUSWINDOW,"renumbering nodes"); + if (Doc.Cuthill()!=TRUE){ + MsgBox("problem renumbering nodes"); + exit(3); + } + + // display details about the problem to be solved + TheView->SetDlgItemText(IDC_STATUSWINDOW,"solving..."); + sprintf(outstr,"Problem Statistics:\n%i nodes\n%i elements\nPrecision: %3.2e\n", + Doc.NumNodes,Doc.NumEls,Doc.Precision); + TheView->SetDlgItemText(IDC_PROBSTATS,outstr); + + // initialize the problem, allocating the space required to solve it. + + CBigLinProb L; + L.TheView=TheView; + L.Precision=Doc.Precision; + + if (L.Create(Doc.NumNodes+Doc.NumCircProps,Doc.BandWidth)==FALSE){ + MsgBox("couldn't allocate enough space for matrices"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(4); + } + + // Create element matrices and solve the problem; + if (Doc.AnalyzeProblem(L)==FALSE) + { + MsgBox("Couldn't solve the problem"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(5); + } + + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Problem solved"); + + // now that we have results, write 'em to dist + if (Doc.WriteResults(L)==FALSE) + { + MsgBox("couldn't write results to disk"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(6); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"results written to disk"); + + // make sure that everything is freed up to avoid memory leaks + Doc.CleanUp(); + L.~CBigLinProb(); + exit(0); +} diff --git a/belasolv/mesh.h b/belasolv/mesh.h new file mode 100644 index 0000000..7c6449a --- /dev/null +++ b/belasolv/mesh.h @@ -0,0 +1,100 @@ +#define PI 3.141592653589793238462643383 +#define eo 8.85418781762e-12 +#define AXISYMMETRIC 1 +#define PLANAR 0 + +class CNode +{ + public: + + double x,y; + int bc; + int InConductor; + + private: + +}; + +class CElement +{ + public: + + int p[3]; // nodes at the corners of the element + int e[3]; // boundary condition applied to each edge of the element + int blk; // block property applied to the element + int lbl; // block label associated with the element + + private: +}; + +class CBlockLabel +{ + public: + + double x,y; + double MaxArea; + int BlockType,InGroup; + BOOL IsExternal; + BOOL IsDefault; + private: + +}; + +class CCommonPoint +{ + public: + int x,y,t; + + private: +}; + +///////////////////////////////////////////////////////////////////////////// +// Classes that hold property data: CMaterialProp, CBoundaryProp, CPointProp + +class CMaterialProp +{ + public: + + double ex,ey; // permittivity, relative + double qv; // charge density, C/m^3 + + private: +}; + +class CBoundaryProp +{ + public: + + int BdryFormat; // type of boundary condition we are applying + // 0 = fixed voltage + // 1 = mixed BC + // 2 = surface charge + // 3 = periodic + // 4 = antiperiodic + + double V; // set value of V for BdryFormat=0; + double qs; // surface charge density + double c0,c1; // coefficients for mixed BC + + private: +}; + +class CPointProp +{ + public: + + double V; // fixed nodal voltage + double qp; // point current density; + + private: +}; + +class CCircuit +{ + public: + + double V,q; + int CircType; + + private: +}; diff --git a/belasolv/prob1big.cpp b/belasolv/prob1big.cpp new file mode 100644 index 0000000..3446f49 --- /dev/null +++ b/belasolv/prob1big.cpp @@ -0,0 +1,381 @@ +#include +#include +#include +#include "belasolv.h" +#include "belasolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +//conversion to internal working units of mm +double units[]={25.4,1.,10.,1000.,0.0254,0.001}; +double sq(double x){ return x*x; } + +BOOL CFemmeDocCore::AnalyzeProblem(CBigLinProb &L) +{ + int i,j,k,pctr=0; + double Me[3][3],be[3]; // element matrices; + double l[3],p[3],q[3]; // element shape parameters; + int n[3],ne[3]; // numbers of nodes for a particular element; + double a,K,r,z,kludge; + CElement *El; + + double c = (1.e-6)/eo; + Depth*=units[LengthUnits]; + extRo*=units[LengthUnits]; + extRi*=units[LengthUnits]; + extZo*=units[LengthUnits]; + kludge=1; + + TheView->SetDlgItemText(IDC_FRAME1,"Matrix Construction"); + + // do some book-keeping related to fixed boundary conditions; + // The P vector denotes which nodes have an assigned value + // The V vector denotes the assigned value + for(i=0;i=0) + if(nodeproplist[meshnode[i].bc].qp==0) + { + L.V[i]=nodeproplist[meshnode[i].bc].V; + L.Q[i]=-1; + } + + if(meshnode[i].InConductor>=0) + if(circproplist[meshnode[i].InConductor].CircType==1) + { + L.V[i]=circproplist[meshnode[i].InConductor].V; + L.Q[i]=meshnode[i].InConductor; + } + } + + // account for fixed boundary conditions along segments; + for(i=0;i=0) + { + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + L.V[meshele[i].p[j]]=lineproplist[meshele[i].e[j]].V; + L.V[meshele[i].p[k]]=lineproplist[meshele[i].e[j]].V; + L.Q[meshele[i].p[j]]=-1; + L.Q[meshele[i].p[k]]=-1; + } + } + } + } + + + // build element matrices using the matrices derived in Allaire's book. + for(i=0;im_prog1.SetPos(pctr); } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++) Me[j][k]=0; + be[j]=0; + } + + // Determine shape parameters. + // l's are element side lengths; + // p's corresponds to the `b' parameter in Allaire + // q's corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( sq(meshnode[n[k]].x-meshnode[n[j]].x) + + sq(meshnode[n[k]].y-meshnode[n[j]].y) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + if (ProblemType==AXISYMMETRIC){ + Depth=2.*PI*r; + + // "Warp" the permeability of this element is part of + // the conformally mapped external region + if(labellist[meshele[i].lbl].IsExternal) + { + z=(meshnode[n[0]].y+meshnode[n[1]].y+meshnode[n[2]].y)/3. - extZo; + kludge=(r*r+z*z)/(extRi*extRo); + } + else kludge=1; + } + + + // x-contribution; + K = -Depth*blockproplist[El->blk].ex/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] += K*p[j]*p[k]; + if (j!=k) Me[k][j]+=K*p[j]*p[k]; + } + + // y-contribution; + K = -Depth*blockproplist[El->blk].ey/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] +=K*q[j]*q[k]; + if (j!=k) Me[k][j]+=K*q[j]*q[k]; + } + + // contribution to be[] from volume charge density + for(j = 0;j<3;j++){ + K = -Depth*c*(blockproplist[El->blk].qv)*a/3.; + be[j]+=K; + } + + + for(j=0;j<3;j++) + { + if (El->e[j] >= 0) + { + k=j+1; if(k==3) k=0; + + if (ProblemType==AXISYMMETRIC) + Depth=PI*(meshnode[n[j]].x + meshnode[n[k]].x); + + // contributions to Me, be from derivative boundary conditions; + if (lineproplist[El->e[j]].BdryFormat==1) + { + K =-1000.*Depth*c*lineproplist[El->e[j]].c0*l[j]/6.; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K = 1000.*Depth*c*lineproplist[El->e[j]].c1*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + + // contribution to be[] from surface charge density; + if (lineproplist[El->e[j]].BdryFormat==2) + { + K =-1000.*Depth*c*lineproplist[El->e[j]].qs*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + } + } + + // process any prescribed nodal values; + for(j=0;j<3;j++) + { + if(L.Q[n[j]]!=-2) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + ne[j]=n[j]; + if(meshnode[n[j]].InConductor>=0) + if(circproplist[meshnode[n[j]].InConductor].CircType==0) + ne[j]=meshnode[n[j]].InConductor+NumNodes; + } + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.Put(L.Get(ne[j],ne[k])-Me[j][k],ne[j],ne[k]); + L.b[ne[j]]-=be[j]; + + if(ne[j]!=n[j]) + { + L.Put(L.Get(n[j],n[j])-Me[j][j],n[j],n[j]); + L.Put(L.Get(n[j],ne[j])+Me[j][j],n[j],ne[j]); + } + } + + } // end of loop that builds element matrices + + // add in contribution from point charge density; + for(i=0;i=0) && (L.Q[i]==-2)) + { + if (ProblemType==AXISYMMETRIC) Depth=2.*PI*meshnode[i].x; + L.b[i]+=((1.e6)*Depth*c*nodeproplist[meshnode[i].bc].qp); + L.Q[i]=-1; + } + + // some bookkeeping to denote which nodes we can smooth over + if(meshnode[i].InConductor>=0) L.Q[i]=meshnode[i].InConductor; + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0,pctr=0;k +#include +#include +#include +#include "belasolv.h" +#include "belasolvDlg.h" +#include "spars.h" + +#define KLUDGE + +CEntry::CEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigLinProb::CBigLinProb() +{ + n=0; +} + +CBigLinProb::~CBigLinProb() +{ + if (n==0) return; + + int i; + CEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + free(Q); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + + free(M); + n=0; +} + +int CBigLinProb::Create(int d, int bw) +{ + int i; + + bdw=bw; + b=(double *)calloc(d,sizeof(double)); + V=(double *)calloc(d,sizeof(double)); + P=(double *)calloc(d,sizeof(double)); + R=(double *)calloc(d,sizeof(double)); + U=(double *)calloc(d,sizeof(double)); + Z=(double *)calloc(d,sizeof(double)); + Q=(BOOL *) calloc(d,sizeof(BOOL)); + M=(CEntry **)calloc(d,sizeof(CEntry *)); + n=d; + + for(i=0;ic = i; + } + + return 1; +} + +void CBigLinProb::Put(double v, int p, int q) +{ + CEntry *e,*l; + int i; + + if(qc < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CEntry *m = new CEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + return; +} + +double CBigLinProb::Get(int p, int q) +{ + CEntry *e; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) return e->x; + + return 0; +} + +void CBigLinProb::MultA(double *X, double *Y) +{ + int i; + CEntry *e; + + for(i=0;ix*X[i]; + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=e->x*X[e->c]; + Y[e->c]+=e->x*X[i]; + e=e->next; + } + } +} + +double CBigLinProb::Dot(double *X, double *Y) +{ + int i; + double z; + + for(i=0,z=0;ix; + + // SSOR preconditioner: + int i; + double c; + CEntry *e; + + c= Lambda*(2-Lambda); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * Lambda; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * Lambda; + e=e->next; + } + Y[i]/= M[i]->x; + } +} + +int CBigLinProb::PCGSolve(int flag) +{ + int i; + double res,res_o,res_new; + double er,del,rho,pAp; + + // quick check for most obvious sign of singularity; + for(i=0;ix==0){ + MsgBox("singular flag tripped at %i of %i",i,n); + return FALSE; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"Conjugate Gradient Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // Best guess for relaxation parameter + Lambda=1.5; + + // residual with V=0 + MultPC(b,Z); + res_o=Dot(Z,b); + if(res_o==0) return 1; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>Precision); + + return 1; +} + +void CBigLinProb::SetValue(int i, double x) +{ + int k,fst,lst; + double z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>n) lst=n; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigLinProb::AntiPeriodicity(int i, int j) +{ + int k,fst,lst; + double v1,v2,c; + +#ifdef KLUDGE + int tmpbdw=bdw; + bdw=0; +#endif + + if (jn) lst=n; + } + + for(k=fst;kn) lst=n; + } + + for(k=fst;k +#include +#include +#include +#include +#include +#include + +#define __AFXWIN_H__ + +#ifndef BOOL +typedef int BOOL; +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// MFC-flavored thin wrapper around std::string. +class CString { + std::string s; +public: + CString() = default; + CString(const char* p) : s(p ? p : "") {} + CString(const std::string& x) : s(x) {} + + operator const char*() const { return s.c_str(); } + const char* c_str() const { return s.c_str(); } + const char* GetString() const { return s.c_str(); } + const std::string& Std() const { return s; } + std::string& Std() { return s; } + + int GetLength() const { return (int)s.size(); } + bool IsEmpty() const { return s.empty(); } + void Empty() { s.clear(); } + char operator[](int i) const { return s[(size_t)i]; } + + CString& operator=(const char* p) { s = p ? p : ""; return *this; } + CString& operator=(const std::string& x) { s = x; return *this; } + CString& operator+=(const CString& o) { s += o.s; return *this; } + CString& operator+=(const char* p) { s += p ? p : ""; return *this; } + CString& operator+=(char c) { s += c; return *this; } + CString operator+(const CString& o) const { CString r(*this); r += o; return r; } + CString operator+(const char* p) const { CString r(*this); r += p; return r; } + bool operator==(const CString& o) const { return s == o.s; } + bool operator==(const char* p) const { return s == (p ? p : ""); } + bool operator!=(const CString& o) const { return !(*this == o); } + bool operator!=(const char* p) const { return !(*this == p); } + bool operator<(const CString& o) const { return s < o.s; } + + CString Mid(int start) const { return CString(s.substr((size_t)start)); } + CString Mid(int start, int n) const { return CString(s.substr((size_t)start, (size_t)n)); } + CString Left(int n) const { return CString(s.substr(0, (size_t)n)); } + CString Right(int n) const { int sz = (int)s.size(); return CString(s.substr((size_t)(sz > n ? sz - n : 0))); } + int Find(char c) const { auto p = s.find(c); return p == std::string::npos ? -1 : (int)p; } + int Find(const char* p) const { auto i = s.find(p ? p : ""); return i == std::string::npos ? -1 : (int)i; } + int ReverseFind(char c) const { auto p = s.rfind(c); return p == std::string::npos ? -1 : (int)p; } + void MakeLower() { for (auto& c : s) c = (char)std::tolower((unsigned char)c); } + void MakeUpper() { for (auto& c : s) c = (char)std::toupper((unsigned char)c); } + void TrimLeft() { while (!s.empty() && std::isspace((unsigned char)s.front())) s.erase(s.begin()); } + void TrimRight() { while (!s.empty() && std::isspace((unsigned char)s.back())) s.pop_back(); } + + int Format(const char* fmt, ...) { + va_list ap; va_start(ap, fmt); + int n = vsnprintf(nullptr, 0, fmt, ap); va_end(ap); + if (n <= 0) { s.clear(); return 0; } + s.resize((size_t)n); + va_start(ap, fmt); + vsnprintf(&s[0], (size_t)n + 1, fmt, ap); + va_end(ap); + return n; + } +}; + +// concatenation of CString and a C string literal on either side. +inline CString operator+(const char* p, const CString& r) { return CString(p) + r; } + +// Win32 stand-ins used by FEMM math files. +inline int DeleteFile(const char* path) { return std::remove(path) == 0; } +inline int _strnicmp(const char* a, const char* b, size_t n) { return strncasecmp(a, b, n); } +inline int _stricmp (const char* a, const char* b) { return strcasecmp(a, b); } +inline void Sleep(unsigned int /*ms*/) {} + +// MSVC math-intrinsic macros. +#ifndef __min +#define __min(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef __max +#define __max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +// forward decls for MFC dialog/binding types femm/ headers reference. +class CDataExchange; +class CWnd; +class CDialog; +class CFile; +class CFileException; +class CArchive; +class CObject; +class CRuntimeClass; + +#include "resource.h" diff --git a/compat/afxcmn.h b/compat/afxcmn.h new file mode 100644 index 0000000..fe46351 --- /dev/null +++ b/compat/afxcmn.h @@ -0,0 +1,2 @@ +// empty stand-in for the MFC common-controls header. +#pragma once diff --git a/compat/afxdisp.h b/compat/afxdisp.h new file mode 100644 index 0000000..c6f5377 --- /dev/null +++ b/compat/afxdisp.h @@ -0,0 +1,2 @@ +// empty stand-in for the MFC automation header. +#pragma once diff --git a/compat/afxdtctl.h b/compat/afxdtctl.h new file mode 100644 index 0000000..060a92c --- /dev/null +++ b/compat/afxdtctl.h @@ -0,0 +1,2 @@ +// empty stand-in for the MFC date/time control header. +#pragma once diff --git a/compat/afxext.h b/compat/afxext.h new file mode 100644 index 0000000..7f38452 --- /dev/null +++ b/compat/afxext.h @@ -0,0 +1,2 @@ +// empty stand-in for the MFC extensions header. +#pragma once diff --git a/compat/afxtempl.h b/compat/afxtempl.h new file mode 100644 index 0000000..1a8ec4b --- /dev/null +++ b/compat/afxtempl.h @@ -0,0 +1,38 @@ +// CArray wrapping std::vector with MFC's method names. +#pragma once +#include "afx.h" +#include +#include + +template +class CArray { + std::vector v; +public: + CArray() = default; + + int GetSize() const { return (int)v.size(); } + int GetCount() const { return (int)v.size(); } + bool IsEmpty() const { return v.empty(); } + int GetUpperBound() const { return (int)v.size() - 1; } + + void SetSize(int n, int /*growBy*/ = -1) { v.resize((size_t)n); } + void RemoveAll() { v.clear(); } + void RemoveAt(int i, int n = 1) { v.erase(v.begin() + i, v.begin() + i + n); } + + int Add(ARG_T x) { v.push_back(x); return (int)v.size() - 1; } + void InsertAt(int i, ARG_T x, int n = 1) { v.insert(v.begin() + i, (size_t)n, x); } + + T GetAt(int i) const { return v[(size_t)i]; } + void SetAt(int i, ARG_T x) { v[(size_t)i] = x; } + T& ElementAt(int i) { return v[(size_t)i]; } + void SetAtGrow(int i, ARG_T x) { if ((size_t)i >= v.size()) v.resize((size_t)i + 1); v[(size_t)i] = x; } + + T* GetData() { return v.data(); } + const T* GetData() const { return v.data(); } + + T& operator[](int i) { return v[(size_t)i]; } + const T& operator[](int i) const { return v[(size_t)i]; } + + void Copy(const CArray& src) { v = src.v; } + int Append(const CArray& src) { int s = (int)v.size(); v.insert(v.end(), src.v.begin(), src.v.end()); return s; } +}; diff --git a/compat/afxwin.h b/compat/afxwin.h new file mode 100644 index 0000000..a95a2ee --- /dev/null +++ b/compat/afxwin.h @@ -0,0 +1,106 @@ +// MFC widget skeletons so GUI headers parse without dragging in real MFC. +#pragma once + +#include "afx.h" + +typedef unsigned int UINT; +typedef unsigned long DWORD; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef long LONG; +typedef void* HCURSOR; +typedef void* HICON; +typedef void* HWND; +typedef void* HINSTANCE; +typedef void* HANDLE; +typedef int LPCRECT; +typedef const char* LPCSTR; +typedef const char* LPCTSTR; +typedef char* LPSTR; +typedef char* PSTR; +typedef const char* PCSTR; +typedef DWORD COLORREF; +typedef unsigned long WPARAM; +typedef long LPARAM; +typedef long LRESULT; + +struct CPoint { int x = 0, y = 0; CPoint() = default; CPoint(int a, int b) : x(a), y(b) {} }; +struct CRect { int left = 0, top = 0, right = 0, bottom = 0; }; +struct CSize { int cx = 0, cy = 0; }; + +struct MSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; CPoint pt; }; + +#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)) | ((WORD)((BYTE)(g))<<8) | ((DWORD)((BYTE)(b))<<16))) + +#define PM_REMOVE 1 +#define PM_NOREMOVE 0 +#define MB_ICONEXCLAMATION 0x30 +#define MB_OK 0 +#define VK_ESCAPE 0x1B +#define WM_PAINT 0x000F +#define WM_CHAR 0x0102 +#define WM_CLOSE 0x0010 +#define WM_RBUTTONUP 0x0205 +#define WM_KEYDOWN 0x0100 +#define WM_KEYUP 0x0101 +#define WM_LBUTTONDOWN 0x0201 +#define WM_LBUTTONUP 0x0202 +#define WM_QUIT 0x0012 + +inline int PeekMessage(MSG*, HWND, UINT, UINT, UINT) { return 0; } +inline int TranslateMessage(const MSG*) { return 0; } +inline long DispatchMessage(const MSG*) { return 0; } +inline int MessageBox(HWND, const char*, const char*, UINT) { return 0; } +inline int GetAsyncKeyState(int) { return 0; } +inline int MessageBeep(UINT) { return 0; } + +#define afx_msg +#define DECLARE_MESSAGE_MAP() +#define BEGIN_MESSAGE_MAP(...) +#define END_MESSAGE_MAP() +#define ON_COMMAND(...) +#define ON_WM_PAINT() +#define ON_WM_CHAR() +#define ON_WM_RBUTTONUP() +#define ON_WM_CLOSE() +#define ON_BN_CLICKED(...) +#define DECLARE_DYNCREATE(x) +#define IMPLEMENT_DYNCREATE(...) +#define DECLARE_DYNAMIC(x) +#define IMPLEMENT_DYNAMIC(...) + +class CObject {}; +class CCmdTarget : public CObject {}; + +class CWnd : public CCmdTarget { +public: + void* m_hWnd = nullptr; + int SetDlgItemText(int, const char*) { return 0; } + int SetWindowText(const char*) { return 0; } + int UpdateWindow() { return 0; } + int InvalidateRect(void* = nullptr, int = 1) { return 1; } +}; + +class CDialog : public CWnd { +public: + CDialog(int = 0, CWnd* = nullptr) {} + virtual int DoModal() { return 0; } + virtual void OnOK() {} + virtual void OnCancel() {} + virtual int OnInitDialog() { return 1; } +}; + +class CEdit : public CWnd { +public: + int Create(unsigned long, const CRect&, CWnd*, unsigned int) { return 0; } + void SetSel(int, int, int = 0) {} +}; + +class CProgressCtrl : public CWnd { public: void SetPos(int) {} }; +class CButton : public CWnd {}; +class CStatic : public CWnd {}; +class CComboBox : public CWnd {}; +class CListBox : public CWnd {}; +class CTreeCtrl : public CWnd {}; +class CTabCtrl : public CWnd {}; +class CDataExchange {}; diff --git a/compat/femm_resource_ids.h b/compat/femm_resource_ids.h new file mode 100644 index 0000000..9bdd792 --- /dev/null +++ b/compat/femm_resource_ids.h @@ -0,0 +1,640 @@ +// every IDD/IDC/IDR/IDS/IDM identifier femm/ names, mapped to 0 for parse-only builds. +#pragma once + +#define IDC_A_RE 0 +#define IDC_A0 0 +#define IDC_A1 0 +#define IDC_A2 0 +#define IDC_ABCN 0 +#define IDC_ABCR 0 +#define IDC_ABCX 0 +#define IDC_ABCY 0 +#define IDC_ABOUTX 0 +#define IDC_ABOUTY 0 +#define IDC_ACKBLK 0 +#define IDC_ACKNODE 0 +#define IDC_ACKSEG 0 +#define IDC_ADD_PROP 0 +#define IDC_AGENAME 0 +#define IDC_AHIGH 0 +#define IDC_ALOW 0 +#define IDC_AMPM 0 +#define IDC_ARCANGLE 0 +#define IDC_ARCGRP 0 +#define IDC_ARCHIDE 0 +#define IDC_ARCSEGBDRY 0 +#define IDC_ARCSEGBDRY2 0 +#define IDC_AUTOMESH 0 +#define IDC_AUTOMESHCHECK 0 +#define IDC_B 0 +#define IDC_BASEX 0 +#define IDC_BASEY 0 +#define IDC_BD_ACKBLK 0 +#define IDC_BD_ACKNODE 0 +#define IDC_BD_ACKSEG 0 +#define IDC_BD_ARCGRP 0 +#define IDC_BD_ARCHIDE 0 +#define IDC_BD_ARCSEG_COND 0 +#define IDC_BD_ARCSEGBDRY2 0 +#define IDC_BD_AUTOMESH 0 +#define IDC_BD_AUTOMESHCHECK 0 +#define IDC_BD_BDRYFORMAT 0 +#define IDC_BD_BDRYNAME 0 +#define IDC_BD_BLKGROUP 0 +#define IDC_BD_BLOCKNAME 0 +#define IDC_BD_C0 0 +#define IDC_BD_C1 0 +#define IDC_BD_CIRCNAME 0 +#define IDC_BD_DACTION 0 +#define IDC_BD_DCOLOR 0 +#define IDC_BD_DCOORD 0 +#define IDC_BD_DDEPTH 0 +#define IDC_BD_DGRIDSIZE 0 +#define IDC_BD_DLENGTH 0 +#define IDC_BD_DMINANGLE 0 +#define IDC_BD_DPIXELS 0 +#define IDC_BD_DPREC 0 +#define IDC_BD_DSHOWGRID 0 +#define IDC_BD_DSNAPGRID 0 +#define IDC_BD_DTYPE 0 +#define IDC_BD_EDIT_DEPTH 0 +#define IDC_BD_EX 0 +#define IDC_BD_EXTERNAL 0 +#define IDC_BD_EY 0 +#define IDC_BD_ISDEFAULT 0 +#define IDC_BD_LENGTH_UNITS 0 +#define IDC_BD_LINEMESHSIZE 0 +#define IDC_BD_MAXSEG2 0 +#define IDC_BD_MINANG 0 +#define IDC_BD_MODBTN 0 +#define IDC_BD_MU1LABEL 0 +#define IDC_BD_MU2LABEL 0 +#define IDC_BD_NODE_COND 0 +#define IDC_BD_NODENAME 0 +#define IDC_BD_PRC 0 +#define IDC_BD_PROBNOTE 0 +#define IDC_BD_PROBTYPE 0 +#define IDC_BD_PTGRP 0 +#define IDC_BD_Q 0 +#define IDC_BD_QP 0 +#define IDC_BD_QS 0 +#define IDC_BD_QV 0 +#define IDC_BD_RADIOAMP 0 +#define IDC_BD_RADIOVOLT 0 +#define IDC_BD_RESTORE 0 +#define IDC_BD_SEG_COND 0 +#define IDC_BD_SEGGRP 0 +#define IDC_BD_SEGHIDE 0 +#define IDC_BD_SETA 0 +#define IDC_BD_SETI 0 +#define IDC_BD_SHOW_NAMES 0 +#define IDC_BD_SHOW_ORIGIN 0 +#define IDC_BD_SIDELENGTH 0 +#define IDC_BD_V 0 +#define IDC_BD_VBDRY 0 +#define IDC_BD_VP 0 +#define IDC_BDATA 0 +#define IDC_BDRYFORMAT 0 +#define IDC_BDRYNAME 0 +#define IDC_BENDANGLE 0 +#define IDC_BENDSEGMENT 0 +#define IDC_BFIRST 0 +#define IDC_BHEDIT 0 +#define IDC_BHNAME 0 +#define IDC_BINTTYPE 0 +#define IDC_BLKGROUP 0 +#define IDC_BLOCKNAME 0 +#define IDC_BSMART 0 +#define IDC_BTU 0 +#define IDC_BV_AHIGH 0 +#define IDC_BV_ALOW 0 +#define IDC_BV_BINTTYPE 0 +#define IDC_BV_CIRCNAME 0 +#define IDC_BV_CIRCRESULT 0 +#define IDC_BV_COLORS 0 +#define IDC_BV_DENSITYPLOT 0 +#define IDC_BV_DFLT1 0 +#define IDC_BV_DPLOTTYPE 0 +#define IDC_BV_EDITACTION 0 +#define IDC_BV_FILEFORMAT 0 +#define IDC_BV_GREY 0 +#define IDC_BV_GSCALE2 0 +#define IDC_BV_LB2 0 +#define IDC_BV_LEGEND 0 +#define IDC_BV_LINTTYPE 0 +#define IDC_BV_LIPOINTS 0 +#define IDC_BV_MODBTN 0 +#define IDC_BV_NCONT 0 +#define IDC_BV_NPOINTS 0 +#define IDC_BV_NUMCONTOURS 0 +#define IDC_BV_ONRELOAD 0 +#define IDC_BV_PLOTPOINTS 0 +#define IDC_BV_RESBTN2 0 +#define IDC_BV_RESET 0 +#define IDC_BV_SCALEFACTOR 0 +#define IDC_BV_SHOW_A 0 +#define IDC_BV_SHOW_LEG2 0 +#define IDC_BV_SHOW_MASK2 0 +#define IDC_BV_SHOWGRID 0 +#define IDC_BV_SHOWIT 0 +#define IDC_BV_SHOWMASK 0 +#define IDC_BV_SHOWMESH 0 +#define IDC_BV_SHOWNAMES 0 +#define IDC_BV_SHOWPTS 0 +#define IDC_BV_SHOWREAL 0 +#define IDC_BV_SMOOTHING 0 +#define IDC_BV_SNAPGRID 0 +#define IDC_BV_TOFILE 0 +#define IDC_BV_UB2 0 +#define IDC_BV_VECTORPLOT 0 +#define IDC_BV_VPLOTTYPE 0 +#define IDC_BV_XYPLOTTYPE 0 +#define IDC_C 0 +#define IDC_C0 0 +#define IDC_C1 0 +#define IDC_CD_ACKBLK 0 +#define IDC_CD_ACKNODE 0 +#define IDC_CD_ACKSEG 0 +#define IDC_CD_ARCGRP 0 +#define IDC_CD_ARCHIDE 0 +#define IDC_CD_ARCSEG_COND 0 +#define IDC_CD_ARCSEGBDRY2 0 +#define IDC_CD_AUTOMESH 0 +#define IDC_CD_AUTOMESHCHECK 0 +#define IDC_CD_BDRYFORMAT 0 +#define IDC_CD_BDRYNAME 0 +#define IDC_CD_BLKGROUP 0 +#define IDC_CD_BLOCKNAME 0 +#define IDC_CD_C0 0 +#define IDC_CD_C1 0 +#define IDC_CD_CIRCNAME 0 +#define IDC_CD_EDIT_DEPTH 0 +#define IDC_CD_EDIT_FREQ 0 +#define IDC_CD_EX 0 +#define IDC_CD_EXTERNAL 0 +#define IDC_CD_EY 0 +#define IDC_CD_ISDEFAULT 0 +#define IDC_CD_LENGTH_UNITS 0 +#define IDC_CD_LINEMESHSIZE 0 +#define IDC_CD_LTX 0 +#define IDC_CD_LTY 0 +#define IDC_CD_MAXSEG2 0 +#define IDC_CD_MINANG 0 +#define IDC_CD_MU1LABEL 0 +#define IDC_CD_MU1LABEL2 0 +#define IDC_CD_MU1LABEL3 0 +#define IDC_CD_MU2LABEL 0 +#define IDC_CD_MU2LABEL2 0 +#define IDC_CD_MU2LABEL3 0 +#define IDC_CD_NODE_COND 0 +#define IDC_CD_NODENAME 0 +#define IDC_CD_OX 0 +#define IDC_CD_OY 0 +#define IDC_CD_PRC 0 +#define IDC_CD_PROBNOTE 0 +#define IDC_CD_PROBTYPE 0 +#define IDC_CD_PTGRP 0 +#define IDC_CD_Q 0 +#define IDC_CD_QP 0 +#define IDC_CD_QS 0 +#define IDC_CD_RADIOAMP 0 +#define IDC_CD_RADIOVOLT 0 +#define IDC_CD_SEG_COND 0 +#define IDC_CD_SEGGRP 0 +#define IDC_CD_SEGHIDE 0 +#define IDC_CD_SETA 0 +#define IDC_CD_SETI 0 +#define IDC_CD_SIDELENGTH 0 +#define IDC_CD_V 0 +#define IDC_CD_VBDRY 0 +#define IDC_CD_VP 0 +#define IDC_CDUCT 0 +#define IDC_CELC 0 +#define IDC_CIRCBLK 0 +#define IDC_CIRCNAME 0 +#define IDC_CIRCRESULT 0 +#define IDC_CLEAR_INPUT 0 +#define IDC_CLEAR_OUTPUT 0 +#define IDC_COLORS 0 +#define IDC_COMBO1 0 +#define IDC_COMPILEDATE 0 +#define IDC_COORD1 0 +#define IDC_COORD2 0 +#define IDC_COORDS 0 +#define IDC_CV_AHIGH 0 +#define IDC_CV_ALOW 0 +#define IDC_CV_BINTTYPE 0 +#define IDC_CV_CIRCNAME 0 +#define IDC_CV_CIRCRESULT 0 +#define IDC_CV_DFLT1 0 +#define IDC_CV_DPLOTTYPE 0 +#define IDC_CV_FILEFORMAT 0 +#define IDC_CV_GSCALE2 0 +#define IDC_CV_LB2 0 +#define IDC_CV_LINTTYPE 0 +#define IDC_CV_NPOINTS 0 +#define IDC_CV_NUMCONTOURS 0 +#define IDC_CV_RESBTN2 0 +#define IDC_CV_SCALEFACTOR 0 +#define IDC_CV_SHOW_A 0 +#define IDC_CV_SHOW_A2 0 +#define IDC_CV_SHOW_LEG2 0 +#define IDC_CV_SHOW_MASK2 0 +#define IDC_CV_SHOWIT 0 +#define IDC_CV_TOFILE 0 +#define IDC_CV_UB2 0 +#define IDC_CV_VPLOTTYPE 0 +#define IDC_CV_XYPLOTTYPE 0 +#define IDC_DACTION 0 +#define IDC_DCOLOR 0 +#define IDC_DCOORD 0 +#define IDC_DDEPTH 0 +#define IDC_DEF_DOC 0 +#define IDC_DEF_LUA_CONSOLE 0 +#define IDC_DEF_SHOWOUTWND 0 +#define IDC_DEF_SMARTMESH 0 +#define IDC_DEF_XYPLOT 0 +#define IDC_DEL_PROP 0 +#define IDC_DELTAX 0 +#define IDC_DELTAY 0 +#define IDC_DENSITYPLOT 0 +#define IDC_DFLT1 0 +#define IDC_DFREQ 0 +#define IDC_DGRIDSIZE 0 +#define IDC_DLENGTH 0 +#define IDC_DMINANGLE 0 +#define IDC_DOCTYPES 0 +#define IDC_DPIXELS 0 +#define IDC_DPREC 0 +#define IDC_DSHOWGRID 0 +#define IDC_DSNAPGRID 0 +#define IDC_DSOLVER 0 +#define IDC_DTYPE 0 +#define IDC_DXFTOL 0 +#define IDC_EDIT_DEPTH 0 +#define IDC_EDIT_FREQ 0 +#define IDC_EDIT1 0 +#define IDC_EDITACTION 0 +#define IDC_EDITCURVE 0 +#define IDC_EVALUATE 0 +#define IDC_EX 0 +#define IDC_EY 0 +#define IDC_FAHR 0 +#define IDC_FE_EXTERNAL 0 +#define IDC_FE_ISDEFAULT 0 +#define IDC_FILEFORMAT 0 +#define IDC_FOLDERNAME 0 +#define IDC_FOLDERURL 0 +#define IDC_FOLDERVENDOR 0 +#define IDC_FV_CIRCNAME 0 +#define IDC_FV_MODBTN 0 +#define IDC_FV_RESET 0 +#define IDC_GAPINTTYPE 0 +#define IDC_GAUSS 0 +#define IDC_GREY 0 +#define IDC_GRIDSIZE 0 +#define IDC_GROUPNUMBER 0 +#define IDC_H_ 0 +#define IDC_H_C 0 +#define IDC_H1LABEL 0 +#define IDC_H2LABEL 0 +#define IDC_HD_ACKBLK 0 +#define IDC_HD_ACKNODE 0 +#define IDC_HD_ACKSEG 0 +#define IDC_HD_ARCGRP 0 +#define IDC_HD_ARCHIDE 0 +#define IDC_HD_ARCSEG_COND 0 +#define IDC_HD_ARCSEGBDRY2 0 +#define IDC_HD_AUTOMESH 0 +#define IDC_HD_AUTOMESHCHECK 0 +#define IDC_HD_BDRYFORMAT 0 +#define IDC_HD_BDRYNAME 0 +#define IDC_HD_BETA 0 +#define IDC_HD_BLKGROUP 0 +#define IDC_HD_BLOCKNAME 0 +#define IDC_HD_CIRCNAME 0 +#define IDC_HD_DT 0 +#define IDC_HD_EDIT_DEPTH 0 +#define IDC_HD_EX 0 +#define IDC_HD_EXTERNAL 0 +#define IDC_HD_EY 0 +#define IDC_HD_HTC 0 +#define IDC_HD_ISDEFAULT 0 +#define IDC_HD_KT 0 +#define IDC_HD_LENGTH_UNITS 0 +#define IDC_HD_LINEMESHSIZE 0 +#define IDC_HD_MAXSEG2 0 +#define IDC_HD_MINANG 0 +#define IDC_HD_MU1LABEL 0 +#define IDC_HD_MU2LABEL 0 +#define IDC_HD_NODE_COND 0 +#define IDC_HD_NODENAME 0 +#define IDC_HD_PRC 0 +#define IDC_HD_PREVSOLN 0 +#define IDC_HD_PROBNOTE 0 +#define IDC_HD_PROBTYPE 0 +#define IDC_HD_PTGRP 0 +#define IDC_HD_Q 0 +#define IDC_HD_QP 0 +#define IDC_HD_QS 0 +#define IDC_HD_QV 0 +#define IDC_HD_RADIOAMP 0 +#define IDC_HD_RADIOVOLT 0 +#define IDC_HD_SEG_COND 0 +#define IDC_HD_SEGGRP 0 +#define IDC_HD_SEGHIDE 0 +#define IDC_HD_SETA 0 +#define IDC_HD_SETI 0 +#define IDC_HD_SIDELENGTH 0 +#define IDC_HD_TBDRY 0 +#define IDC_HD_TINF1 0 +#define IDC_HD_TINF2 0 +#define IDC_HD_V 0 +#define IDC_HD_VP 0 +#define IDC_HDATA 0 +#define IDC_HFIRST 0 +#define IDC_HV_AHIGH 0 +#define IDC_HV_ALOW 0 +#define IDC_HV_BINTTYPE 0 +#define IDC_HV_CIRCNAME 0 +#define IDC_HV_CIRCRESULT 0 +#define IDC_HV_DFLT1 0 +#define IDC_HV_DPLOTTYPE 0 +#define IDC_HV_FILEFORMAT 0 +#define IDC_HV_GSCALE2 0 +#define IDC_HV_LB2 0 +#define IDC_HV_LINTTYPE 0 +#define IDC_HV_NPOINTS 0 +#define IDC_HV_NUMCONTOURS 0 +#define IDC_HV_RESBTN2 0 +#define IDC_HV_SCALEFACTOR 0 +#define IDC_HV_SHOW_A 0 +#define IDC_HV_SHOW_LEG2 0 +#define IDC_HV_SHOW_MASK2 0 +#define IDC_HV_SHOWIT 0 +#define IDC_HV_TOFILE 0 +#define IDC_HV_UB2 0 +#define IDC_HV_VPLOTTYPE 0 +#define IDC_HV_XYPLOTTYPE 0 +#define IDC_INGRP 0 +#define IDC_INNERANGLE 0 +#define IDC_J 0 +#define IDC_J_RE 0 +#define IDC_JR 0 +#define IDC_KAMPM 0 +#define IDC_KCAL 0 +#define IDC_KELV 0 +#define IDC_KFIRST 0 +#define IDC_KGAUSS 0 +#define IDC_KOERSTED 0 +#define IDC_KT 0 +#define IDC_L 0 +#define IDC_LABEL1 0 +#define IDC_LABEL2 0 +#define IDC_LAM_D 0 +#define IDC_LAM_DIR 0 +#define IDC_LAM_FILL 0 +#define IDC_LEGEND 0 +#define IDC_LENGTH_UNITS 0 +#define IDC_LINEMESHSIZE 0 +#define IDC_LINTTYPE 0 +#define IDC_LIPOINTS 0 +#define IDC_LOGPLOT_BHCURVE 0 +#define IDC_LTX 0 +#define IDC_LTY 0 +#define IDC_LUA_INPUT 0 +#define IDC_LUA_OUTPUT 0 +#define IDC_M 0 +#define IDC_MAGDIR 0 +#define IDC_MAXSEG 0 +#define IDC_MAXSEG2 0 +#define IDC_MINANG 0 +#define IDC_MOD_PROP 0 +#define IDC_MODBTN 0 +#define IDC_MU 0 +#define IDC_MU_X 0 +#define IDC_MU_Y 0 +#define IDC_MU1LABEL 0 +#define IDC_MU2LABEL 0 +#define IDC_MYLIST 0 +#define IDC_MYMSGBOXOUTPUT 0 +#define IDC_MYTREE 0 +#define IDC_NAME_LIST 0 +#define IDC_NCONT 0 +#define IDC_NCOPIES 0 +#define IDC_NLCOMBO 0 +#define IDC_NODENAME 0 +#define IDC_NPOINTS 0 +#define IDC_NS 0 +#define IDC_NSTRANDS 0 +#define IDC_NUMCONTOURS 0 +#define IDC_OERSTED 0 +#define IDC_ONRELOAD 0 +#define IDC_OUTBOX 0 +#define IDC_OUTERANGLE 0 +#define IDC_OX 0 +#define IDC_OY 0 +#define IDC_P 0 +#define IDC_PAX 0 +#define IDC_PAY 0 +#define IDC_PBX 0 +#define IDC_PBY 0 +#define IDC_PHI 0 +#define IDC_PLOT_BHCURVE 0 +#define IDC_PLOTPOINTS 0 +#define IDC_PRC 0 +#define IDC_PREVSOLN 0 +#define IDC_PREVTYPE 0 +#define IDC_PROBNOTE 0 +#define IDC_PROBTYPE 0 +#define IDC_PROGRESS1 0 +#define IDC_PTGRP 0 +#define IDC_QS 0 +#define IDC_QV 0 +#define IDC_RADIOAMP 0 +#define IDC_RADIOVOLT 0 +#define IDC_RANK 0 +#define IDC_READ_BHCURVE 0 +#define IDC_RESTORE 0 +#define IDC_RI 0 +#define IDC_RO 0 +#define IDC_ROTATE 0 +#define IDC_S 0 +#define IDC_SCALEFACTOR 0 +#define IDC_SCRBOTTOM 0 +#define IDC_SCRLEFT 0 +#define IDC_SCRRIGHT 0 +#define IDC_SCRTOP 0 +#define IDC_SEGGRP 0 +#define IDC_SEGHIDE 0 +#define IDC_SETA 0 +#define IDC_SETI 0 +#define IDC_SHIFTANGLE 0 +#define IDC_SHIFTH 0 +#define IDC_SHOW_A 0 +#define IDC_SHOW_A_IM 0 +#define IDC_SHOW_A_RE 0 +#define IDC_SHOW_MASK1 0 +#define IDC_SHOW_MASK2 0 +#define IDC_SHOW_ORIGIN 0 +#define IDC_SHOWGRID 0 +#define IDC_SHOWIMAGINARY 0 +#define IDC_SHOWMASK 0 +#define IDC_SHOWMESH 0 +#define IDC_SHOWNAMES 0 +#define IDC_SHOWNAMEZ 0 +#define IDC_SHOWPTS 0 +#define IDC_SHOWREAL 0 +#define IDC_SIDELENGTH 0 +#define IDC_SIGMA 0 +#define IDC_SMOOTHING 0 +#define IDC_SNAPGRID 0 +#define IDC_SOLVER 0 +#define IDC_STATIC_SYMB1 0 +#define IDC_STATIC_SYMB2 0 +#define IDC_STATIC_SYMB3 0 +#define IDC_STATIC_SYMBOL1 0 +#define IDC_STATIC_SYMBOL2 0 +#define IDC_STATIC_SYMBOL3 0 +#define IDC_STATIC_SYMBOL4 0 +#define IDC_STATIC_SYMBOL5 0 +#define IDC_STATIC_SYMBOL6 0 +#define IDC_STATIC_SYMBOL7 0 +#define IDC_STATIC_SYMBOL8 0 +#define IDC_T 0 +#define IDC_TAB1 0 +#define IDC_TESLA 0 +#define IDC_TFIRST 0 +#define IDC_THETA_H 0 +#define IDC_THETA_HX 0 +#define IDC_THETA_HY 0 +#define IDC_TOFILE 0 +#define IDC_TOTCURRENT_RE 0 +#define IDC_TRANSLATE 0 +#define IDC_TURNS 0 +#define IDC_VBDRY 0 +#define IDC_VECTORPLOT 0 +#define IDC_VPLOT_SCALE 0 +#define IDC_VPLOTTYPE 0 +#define IDC_W 0 +#define IDC_WIRED 0 +#define IDC_WMK 0 +#define IDC_WST 0 +#define IDC_XYPLOTTYPE 0 +#define IDC_ZO 0 +#define IDD_ABOUTBOX 0 +#define IDD_ARCDLG 0 +#define IDD_BD_BDRYDLG 0 +#define IDD_BD_CIRCPROP 0 +#define IDD_BD_MATDLG 0 +#define IDD_BD_NODEPROP 0 +#define IDD_BD_OPARCSEGDLG 0 +#define IDD_BD_OPBLKDLG 0 +#define IDD_BD_OPNODEDLG 0 +#define IDD_BD_OPSEGDLG 0 +#define IDD_BD_PREF 0 +#define IDD_BD_PROBDLG 0 +#define IDD_BDRYDLG 0 +#define IDD_BENDCONTOUR 0 +#define IDD_BHCURVE 0 +#define IDD_BHDATAFILE 0 +#define IDD_BLOCKINT 0 +#define IDD_BV_BLOCKINT 0 +#define IDD_BV_CIRCPROPS 0 +#define IDD_BV_CPLOTDLG2 0 +#define IDD_BV_DPLOTDLG2 0 +#define IDD_BV_LINEINT 0 +#define IDD_BV_PREF 0 +#define IDD_BV_VPLOTDLG 0 +#define IDD_BV_XYPLOTDLG 0 +#define IDD_CD_BDRYDLG 0 +#define IDD_CD_CIRCPROP 0 +#define IDD_CD_MATDLG 0 +#define IDD_CD_NODEPROP 0 +#define IDD_CD_OPARCSEGDLG 0 +#define IDD_CD_OPBLKDLG 0 +#define IDD_CD_OPNODEDLG 0 +#define IDD_CD_OPSEGDLG 0 +#define IDD_CD_PREF 0 +#define IDD_CD_PROBDLG 0 +#define IDD_CIRCPROP 0 +#define IDD_CIRCPROPS 0 +#define IDD_COPYDLG 0 +#define IDD_CPLOTDLG 0 +#define IDD_CPLOTDLG2 0 +#define IDD_CV_BLOCKINT 0 +#define IDD_CV_CIRCPROPS 0 +#define IDD_CV_CPLOTDLG2 0 +#define IDD_CV_DPLOTDLG2 0 +#define IDD_CV_LINEINT 0 +#define IDD_CV_PREF 0 +#define IDD_CV_VPLOTDLG 0 +#define IDD_CV_XYPLOTDLG 0 +#define IDD_DXFIMPORT 0 +#define IDD_EDITPREF 0 +#define IDD_ENTERPT 0 +#define IDD_EXTERIORPROPS 0 +#define IDD_GAPINTEGRAL 0 +#define IDD_GAPPLOTDLG 0 +#define IDD_GENPREFS 0 +#define IDD_GRIDMOD 0 +#define IDD_GROUPNO 0 +#define IDD_HD_BDRYDLG 0 +#define IDD_HD_CIRCPROP 0 +#define IDD_HD_MATDLG 0 +#define IDD_HD_NODEPROP 0 +#define IDD_HD_OPARCSEGDLG 0 +#define IDD_HD_OPBLKDLG 0 +#define IDD_HD_OPNODEDLG 0 +#define IDD_HD_OPSEGDLG 0 +#define IDD_HD_PREF 0 +#define IDD_HD_PROBDLG 0 +#define IDD_HV_BLOCKINT 0 +#define IDD_HV_CIRCPROPS 0 +#define IDD_HV_CPLOTDLG2 0 +#define IDD_HV_DPLOTDLG2 0 +#define IDD_HV_LINEINT 0 +#define IDD_HV_PREF 0 +#define IDD_HV_VPLOTDLG 0 +#define IDD_HV_XYPLOTDLG 0 +#define IDD_KBDZOOM 0 +#define IDD_KCURVE 0 +#define IDD_LIBFOLDERINFO 0 +#define IDD_LINEINT 0 +#define IDD_LUACONSOLE 0 +#define IDD_MAKE_ABC 0 +#define IDD_MASKPROGRESS 0 +#define IDD_MATDLG 0 +#define IDD_MIRRORDLG 0 +#define IDD_MYMSGBOX 0 +#define IDD_NEWDOC 0 +#define IDD_NODEPROP 0 +#define IDD_OPARCSEGDLG 0 +#define IDD_OPBLKDLG 0 +#define IDD_OPGRPDLG 0 +#define IDD_OPNODEDLG 0 +#define IDD_OPSEGDLG 0 +#define IDD_OUTBOX 0 +#define IDD_PREFERENCES 0 +#define IDD_PROBDLG 0 +#define IDD_PROMPTBOX 0 +#define IDD_PTPROP 0 +#define IDD_SCALE 0 +#define IDD_TKDATAFILE 0 +#define IDD_TREETEST_DIALOG 0 +#define IDD_VIEWPREF 0 +#define IDD_VPLOTDLG 0 +#define IDD_XYPLOTDLG 0 +#define IDR_BELADRAWTYPE 0 +#define IDR_BELAVIEWTYPE 0 +#define IDR_CDRAWTYPE 0 +#define IDR_CVIEWTYPE 0 +#define IDR_FEMMETYPE 0 +#define IDR_FEMMPLOTTYPE 0 +#define IDR_FEMMVIEWTYPE 0 +#define IDR_HDRAWTYPE 0 +#define IDR_HVIEWTYPE 0 +#define IDR_LEFTBAR 0 +#define IDR_MAIN1 0 +#define IDR_MAIN2 0 +#define IDR_MAINFRAME 0 diff --git a/compat/malloc.h b/compat/malloc.h new file mode 100644 index 0000000..5e320f2 --- /dev/null +++ b/compat/malloc.h @@ -0,0 +1,3 @@ +// forwards malloc.h to stdlib.h. +#pragma once +#include diff --git a/compat/resource.h b/compat/resource.h new file mode 100644 index 0000000..792ee07 --- /dev/null +++ b/compat/resource.h @@ -0,0 +1,8 @@ +// stand-in for the deleted MFC resource header. +#pragma once + +#define IDC_FRAME1 0 +#define IDC_FRAME2 0 +#define IDC_FRAME3 0 + +#include "femm_resource_ids.h" diff --git a/csolv/CSOLV.H b/csolv/CSOLV.H new file mode 100644 index 0000000..44d9ea2 --- /dev/null +++ b/csolv/CSOLV.H @@ -0,0 +1,4 @@ +// solver entry point. +#pragma once + +void old_main(void *inptr); diff --git a/csolv/CSOLVDLG.CPP b/csolv/CSOLVDLG.CPP new file mode 100644 index 0000000..beccce1 --- /dev/null +++ b/csolv/CSOLVDLG.CPP @@ -0,0 +1,96 @@ +// csolvDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "csolv.h" +#include "csolvDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CcsolvDlg dialog + +CcsolvDlg::CcsolvDlg(CWnd* pParent /*=NULL*/) + : CDialog(CcsolvDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CcsolvDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CcsolvDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CcsolvDlg) + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CcsolvDlg, CDialog) + //{{AFX_MSG_MAP(CcsolvDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CcsolvDlg message handlers + +BOOL CcsolvDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + return FALSE; // return TRUE unless you set the focus to a control +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CcsolvDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CcsolvDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CcsolvDlg::OnOK() +{ +} diff --git a/csolv/CSOLVDLG.H b/csolv/CSOLVDLG.H new file mode 100644 index 0000000..fe4650a --- /dev/null +++ b/csolv/CSOLVDLG.H @@ -0,0 +1,20 @@ +// MFC-free CcsolvDlg with empty progress, label, and window-update calls. +#pragma once + +#include + +struct CProgressStub { void SetPos(int) {} }; + +class CcsolvDlg { +public: + CProgressStub m_prog1; + CProgressStub m_prog2; + void* m_hWnd = nullptr; + std::string ComLine; + void SetDlgItemText(int, const char*) {} + void SetWindowText(const char*) {} + void UpdateWindow() {} + int InvalidateRect(void* = nullptr, int = 1) { return 1; } +}; + +extern CcsolvDlg* TheView; diff --git a/csolv/CUTHILL.CPP b/csolv/CUTHILL.CPP new file mode 100644 index 0000000..bacec01 --- /dev/null +++ b/csolv/CUTHILL.CPP @@ -0,0 +1,267 @@ +// does Cuthill-McKee algorithm as described in Hoole; + +#include +#include +#include +#include +#include "complex.h" +#include "csolv.h" +#include "csolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +#define muo 1.2566370614359173e-6 + +BOOL CFemmeDocCore::SortElements() +{ + // Comb Sort -- see http://en.wikipedia.org/wiki/Comb_sort + int *Score; + int i,j,k,gap; + CElement e; + + Score=(int*)calloc(NumEls,sizeof(int)); + + for(k=0;k 1) + { + gap=(gap*10)/13; + if ((gap==10) || (gap==9)) gap=11; + + } + + //a single "comb" over the input list + for(j=0,i=0;(j+gap)Score[j+gap]) + { + k=j+gap; + i=Score[k];Score[k]=Score[j];Score[j]=i; + e=meshele[k];meshele[k]=meshele[j];meshele[j]=e; + i=1; + } + } + }while((gap>1)&&(i>0)); + + + free(Score); + return TRUE; +} + +BOOL CFemmeDocCore::Cuthill() +{ + + FILE *fp; + int i,j,k,n0,n1,n; + int newwide,*newnum,**ocon; + int *numcon,*nxtnum; + CNode swap; + char infile[256]; + + // allocate storage + nxtnum=(int *)calloc(NumNodes,sizeof(int)); + newnum=(int *)calloc(NumNodes,sizeof(int)); + numcon=(int *)calloc(NumNodes,sizeof(int)); + ocon=(int **)calloc(NumNodes,sizeof(int *)); + // initialize node array; + for(i=0;inewwide) + { + newwide=abs(newnum[n0]-ocon[n0][i]); + } + } + + BandWidth=newwide+1; + // } + + // free up the variables that we needed during the routine.... + free(numcon); + free(nxtnum); + free(ocon[0]); + free(ocon); + + // new mapping remains in newnum; + // apply this mapping to elements first. + for(i=0;i +#include +#include +#include +#include +#include "complex.h" +#include "csolv.h" +#include "csolvDlg.h" +#include "spars.h" +#include "mesh.h" +#include "FemmeDocCore.h" + +void old_main(void *inptr) +{ + CcsolvDlg *TheView; + CFemmeDocCore Doc; + char PathName[256]; + CFileDialog *fname_dia; + char outstr[1024]; + int i; + + TheView=(CcsolvDlg *) inptr; + + // get the name of the file to be processed, + // either from argv or from the user + if (__argc<2){ + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "cview datafile (*.fec) | *.fec; *.FEC | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + MsgBox("No file name!"); + exit(0); + } + + CString fname=fname_dia->GetPathName(); + fname=fname.Left(fname.GetLength()-4); + strcpy(PathName,fname); + delete[] fname_dia; + } + else strcpy(PathName,__argv[1]); + + Doc.PathName=PathName; + Doc.TheView=TheView; + + // load problem geometry + if (Doc.OnOpenDocument()!=TRUE){ + MsgBox("problem loading input file"); + exit(7); + } + + // load mesh + if (Doc.LoadMesh()!=TRUE){ + MsgBox("problem loading mesh"); + exit(2); + } + + // label the dialog to report which problem is being solved + char PaneText[256]; + char *ProbName; + ProbName=PathName; + for(i=0;i< (int) strlen(PathName);i++) + if(PathName[i]=='\\') ProbName=PathName+i; + if (strlen(PathName)>0){ + ProbName++; + sprintf(PaneText,"%s - csolve",ProbName); + } + + while(!IsWindow(TheView->m_hWnd)) Sleep(1); + TheView->SetWindowText(PaneText); + + // renumber using Cuthill-McKee + TheView->SetDlgItemText(IDC_STATUSWINDOW,"renumbering nodes"); + if (Doc.Cuthill()!=TRUE){ + MsgBox("problem renumbering nodes"); + exit(3); + } + + // display details about the problem to be solved + TheView->SetDlgItemText(IDC_STATUSWINDOW,"solving..."); + sprintf(outstr,"Problem Statistics:\n%i nodes\n%i elements\nPrecision: %3.2e\n", + Doc.NumNodes,Doc.NumEls,Doc.Precision); + TheView->SetDlgItemText(IDC_PROBSTATS,outstr); + + // initialize the problem, allocating the space required to solve it. + + CBigComplexLinProb L; + L.TheView=TheView; + L.Precision=Doc.Precision; + + if (L.Create(Doc.NumNodes+Doc.NumCircProps,Doc.BandWidth,Doc.NumNodes)==FALSE){ + MsgBox("couldn't allocate enough space for matrices"); + Doc.CleanUp(); + L.~CBigComplexLinProb(); + exit(4); + } + + // Create element matrices and solve the problem; + if (Doc.AnalyzeProblem(L)==FALSE) + { + MsgBox("Couldn't solve the problem"); + Doc.CleanUp(); + L.~CBigComplexLinProb(); + exit(5); + } + + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Problem solved"); + + // now that we have results, write 'em to dist + if (Doc.WriteResults(L)==FALSE) + { + MsgBox("couldn't write results to disk"); + Doc.CleanUp(); + L.~CBigComplexLinProb(); + exit(6); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"results written to disk"); + + // make sure that everything is freed up to avoid memory leaks + Doc.CleanUp(); + L.~CBigComplexLinProb(); + exit(0); +} diff --git a/csolv/MESH.H b/csolv/MESH.H new file mode 100644 index 0000000..f6393f4 --- /dev/null +++ b/csolv/MESH.H @@ -0,0 +1,101 @@ +#define PI 3.141592653589793238462643383 +#define eo 8.85418781762e-12 +#define AXISYMMETRIC 1 +#define PLANAR 0 + +class CNode +{ + public: + + double x,y; + int bc; + int InConductor; + + private: + +}; + +class CElement +{ + public: + + int p[3]; // nodes at the corners of the element + int e[3]; // boundary condition applied to each edge of the element + int blk; // block property applied to the element + int lbl; // block label associated with the element + + private: +}; + +class CBlockLabel +{ + public: + + double x,y; + double MaxArea; + int BlockType,InGroup; + BOOL IsExternal; + BOOL IsDefault; + private: + +}; + +class CCommonPoint +{ + public: + int x,y,t; + + private: +}; + +///////////////////////////////////////////////////////////////////////////// +// Classes that hold property data: CMaterialProp, CBoundaryProp, CPointProp + +class CMaterialProp +{ + public: + + CComplex ex,ey; // permittivity, relative + double ox,oy; // conductivity + CComplex kx,ky; + + private: +}; + +class CBoundaryProp +{ + public: + + int BdryFormat; // type of boundary condition we are applying + // 0 = fixed voltage + // 1 = mixed BC + // 2 = surface charge + // 3 = periodic + // 4 = antiperiodic + + CComplex V; // set value of V for BdryFormat=0; + CComplex qs; // surface current density + CComplex c0,c1; // coefficients for mixed BC + + private: +}; + +class CPointProp +{ + public: + + CComplex V; // fixed nodal voltage + CComplex qp; // point current density; + + private: +}; + +class CCircuit +{ + public: + + CComplex V,q; + int CircType; + + private: +}; diff --git a/csolv/PROB1BIG.CPP b/csolv/PROB1BIG.CPP new file mode 100644 index 0000000..0b5f342 --- /dev/null +++ b/csolv/PROB1BIG.CPP @@ -0,0 +1,378 @@ +#include +#include +#include +#include "complex.h" +#include "csolv.h" +#include "csolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +//conversion to internal working units of mm +double units[]={25.4,1.,10.,1000.,0.0254,0.001}; +double sq(double x){ return x*x; } + +BOOL CFemmeDocCore::AnalyzeProblem(CBigComplexLinProb &L) +{ + int i,j,k,pctr=0; + CComplex Me[3][3],be[3]; // element matrices; + double l[3],p[3],q[3]; // element shape parameters; + int n[3],ne[3]; // numbers of nodes for a particular element; + double a,r,z,kludge; + CComplex K; + CElement *El; + + double c = (1.e-6)/eo; + Depth*=units[LengthUnits]; + extRo*=units[LengthUnits]; + extRi*=units[LengthUnits]; + extZo*=units[LengthUnits]; + kludge=1; + + TheView->SetDlgItemText(IDC_FRAME1,"Matrix Construction"); + + // do some book-keeping related to fixed boundary conditions; + // The P vector denotes which nodes have an assigned value + // The V vector denotes the assigned value + for(i=0;i=0) + if(nodeproplist[meshnode[i].bc].qp==0) + { + L.V[i]=nodeproplist[meshnode[i].bc].V; + L.Q[i]=-1; + } + + if(meshnode[i].InConductor>=0) + if(circproplist[meshnode[i].InConductor].CircType==1) + { + L.V[i]=circproplist[meshnode[i].InConductor].V; + L.Q[i]=meshnode[i].InConductor; + } + } + + // account for fixed boundary conditions along segments; + for(i=0;i=0) + { + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + L.V[meshele[i].p[j]]=lineproplist[meshele[i].e[j]].V; + L.V[meshele[i].p[k]]=lineproplist[meshele[i].e[j]].V; + L.Q[meshele[i].p[j]]=-1; + L.Q[meshele[i].p[k]]=-1; + } + } + } + } + + + // build element matrices using the matrices derived in Allaire's book. + for(i=0;im_prog1.SetPos(pctr); } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++) Me[j][k]=0; + be[j]=0; + } + + // Determine shape parameters. + // l's are element side lengths; + // p's corresponds to the `b' parameter in Allaire + // q's corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( sq(meshnode[n[k]].x-meshnode[n[j]].x) + + sq(meshnode[n[k]].y-meshnode[n[j]].y) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + if (ProblemType==AXISYMMETRIC){ + Depth=2.*PI*r; + + // "Warp" the permeability of this element is part of + // the conformally mapped external region + if(labellist[meshele[i].lbl].IsExternal) + { + z=(meshnode[n[0]].y+meshnode[n[1]].y+meshnode[n[2]].y)/3. - extZo; + kludge=(r*r+z*z)/(extRi*extRo); + } + else kludge=1; + } + + + // x-contribution; + K = -Depth*blockproplist[El->blk].kx/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] += K*p[j]*p[k]; + if (j!=k) Me[k][j]+=K*p[j]*p[k]; + } + + // y-contribution; + K = -Depth*blockproplist[El->blk].ky/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] +=K*q[j]*q[k]; + if (j!=k) Me[k][j]+=K*q[j]*q[k]; + } + + for(j=0;j<3;j++) + { + if (El->e[j] >= 0) + { + k=j+1; if(k==3) k=0; + + if (ProblemType==AXISYMMETRIC) + Depth=PI*(meshnode[n[j]].x + meshnode[n[k]].x); + + // contributions to Me, be from derivative boundary conditions; + if (lineproplist[El->e[j]].BdryFormat==1) + { + K =-1000.*Depth*c*lineproplist[El->e[j]].c0*l[j]/6.; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K = 1000.*Depth*c*lineproplist[El->e[j]].c1*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + + // contribution to be[] from surface charge density; + if (lineproplist[El->e[j]].BdryFormat==2) + { + K =-1000.*Depth*c*lineproplist[El->e[j]].qs*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + } + } + + // process any prescribed nodal values; + for(j=0;j<3;j++) + { + if(L.Q[n[j]]!=-2) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + ne[j]=n[j]; + if(meshnode[n[j]].InConductor>=0) + if(circproplist[meshnode[n[j]].InConductor].CircType==0) + ne[j]=meshnode[n[j]].InConductor+NumNodes; + } + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.Put(L.Get(ne[j],ne[k])-Me[j][k],ne[j],ne[k]); + L.b[ne[j]]-=be[j]; + + if(ne[j]!=n[j]) + { + L.Put(L.Get(n[j],n[j])-Me[j][j],n[j],n[j]); + L.Put(L.Get(n[j],ne[j])+Me[j][j],n[j],ne[j]); + } + } + + } // end of loop that builds element matrices + + // add in contribution from point charge density; + for(i=0;i=0) && (L.Q[i]==-2)) + { + if (ProblemType==AXISYMMETRIC) Depth=2.*PI*meshnode[i].x; + L.b[i]+=((1.e6)*Depth*c*nodeproplist[meshnode[i].bc].qp); + L.Q[i]=-1; + } + + // some bookkeeping to denote which nodes we can smooth over + if(meshnode[i].InConductor>=0) L.Q[i]=meshnode[i].InConductor; + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0,pctr=0;k + +int MsgBox(const char* sz, ...); +int MsgBox(const std::string& s); diff --git a/csolv/complex.cpp b/csolv/complex.cpp new file mode 100644 index 0000000..7a6f454 --- /dev/null +++ b/csolv/complex.cpp @@ -0,0 +1,624 @@ +#include +#include "math.h" +#include "stdio.h" +#include "complex.h" + +CComplex::CComplex(double x) +{ + re=x; im=0.; +} + +CComplex::CComplex(int x) +{ + re=(double) x; + im=0.; +} + +CComplex::CComplex() +{ + re=0.; im=0.; +} + +CComplex::CComplex(double x, double y) +{ + re=x; im=y; +} + +CComplex CComplex::Sqrt() +{ + double w,z; + CComplex y; + + if((re==0) && (im==0)) w=0; + else if(fabs(re)>fabs(im)){ + z=im/re; + w=sqrt(fabs(re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=re/im; + w=sqrt(fabs(im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(re>=0){ + y.re=w; + y.im=im/(2.*w); + return y; + } + + if(im>=0){ + y.re=fabs(im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(im)/(2.*w); + y.im= (-w); + return y; +} + +CComplex CComplex::Conj() +{ + return CComplex(re,-im); +} + +double CComplex::Abs() +{ + if ((re==0) && (im==0)) return 0.; + + if (fabs(re)>fabs(im)) + return fabs(re)*sqrt(1.+(im/re)*(im/re)); + else + return fabs(im)*sqrt(1.+(re/im)*(re/im)); +} + +double CComplex::Arg() +{ + if ((re==0) && (im==0)) return 0.; + + return atan2(im,re); +} + +CComplex CComplex::Inv() +{ + double c; + CComplex z; + + if(fabs(re)>fabs(im)) + { + c=im/re; + z.re=1./(re*(1.+c*c)); + z.im=(-c)*z.re; + } + else{ + c=re/im; + z.im=(-1.)/(im*(1.+c*c)); + z.re=(-c)*z.im; + } + + return z; +} + +double CComplex::Re() +{ + return re; +} + +double CComplex::Im() +{ + return im; +} + +void CComplex::Set(double x, double y) +{ + re=x; im=y; +} + +char* CComplex::ToString(char *s) +{ + if (im<0) + sprintf(s,"%.3e - j %.3e",re,fabs(im)); + else + sprintf(s,"%.3e + j %.3e",re,im); + return s; +} + +//******* Addition *************************************************** + +CComplex CComplex::operator+( const CComplex& z ) +{ + return CComplex(re+z.re,im+z.im); +}; + +CComplex CComplex::operator+( int z ) +{ + return CComplex(re+((double) z),im); +}; + +CComplex CComplex::operator+( double z ) +{ + return CComplex(re+z,im); +}; + +void CComplex::operator+=( const CComplex& z) +{ + re+=z.re; + im+=z.im; +}; + +void CComplex::operator+=( double z ) +{ + re+=z; +}; + +void CComplex::operator+=( int z ) +{ + re+=(double) z; +}; + +CComplex operator+( int x, const CComplex& y ) +{ + return CComplex( ((double) x) + y.re, y.im ); +} + +CComplex operator+( double x, const CComplex& y ) +{ + return CComplex( x + y.re, y.im ); +} + +CComplex operator+( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re + y.re, x.im + y.im ); +} + + +//******* Subtraction *************************************************** +CComplex CComplex::operator-() +{ + return CComplex(-re,-im); +} + +CComplex CComplex::operator-( const CComplex& z) +{ + return CComplex(re-z.re,im-z.im); +}; + +CComplex CComplex::operator-( int z ) +{ + return CComplex(re-((double) z),im); +}; + +CComplex CComplex::operator-( double z ) +{ + return CComplex(re-z,im); +}; + +void CComplex::operator-=( const CComplex& z) +{ + re-=z.re; + im-=z.im; +}; + +void CComplex::operator-=( double z ) +{ + re-=z; +}; + +void CComplex::operator-=( int z ) +{ + re-=(double) z; +}; + +CComplex operator-( int x, const CComplex& y ) +{ + return CComplex( ((double) x) - y.re, - y.im ); +} + +CComplex operator-( double x, const CComplex& y ) +{ + return CComplex( x - y.re, - y.im ); +} + +CComplex operator-( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re - y.re, x.im - y.im ); +} + +CComplex operator-( const CComplex& y ) +{ + return CComplex( -y.re,-y.im ); +} +//******* Multiplication *************************************************** + +CComplex CComplex::operator*( const CComplex& z) +{ + return CComplex(re*z.re - im*z.im,re*z.im + im*z.re); +}; + +CComplex CComplex::operator*( int z ) +{ + return CComplex( re*((double) z),im*((double) z) ); +}; + +CComplex CComplex::operator*( double z ) +{ + return CComplex(re*z,im*z); +}; + +void CComplex::operator*=( const CComplex& z) +{ + CComplex x(re*z.re - im*z.im,re*z.im + im*z.re); + re=x.re; im=x.im; +}; + +void CComplex::operator*=( double z ) +{ + re*=z; im*=z; +}; + +void CComplex::operator*=( int z ) +{ + re*=(double) z; + im*=(double) z; +}; + +CComplex operator*( int x, const CComplex& y ) +{ + return CComplex( ((double) x) * y.re, ((double) x)*y.im ); +} + +CComplex operator*( double x, const CComplex& y ) +{ + return CComplex( x*y.re, x*y.im ); +} + +CComplex operator*( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re*y.re-x.im*y.im, x.re*y.im+x.im*y.re ); +} + +//******* Division *************************************************** + +CComplex CComplex::operator/( const CComplex& z) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return *this * y; +}; + + +CComplex CComplex::operator/( int z ) +{ + return CComplex(re/((double) z),im/((double) z)); +}; + +CComplex CComplex::operator/( double z ) +{ + return CComplex(re/z,im/z); +}; + +void CComplex::operator/=( const CComplex& z) +{ + *this=*this/z; +}; + +void CComplex::operator/=( double z ) +{ + re/=z; + im/=z; +}; + +void CComplex::operator/=( int z ) +{ + re/=(double) z; + im/=(double) z; +}; + +CComplex operator/( int x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*=(double) x; + y.im*=(double) x; + + return y; +} + +CComplex operator/( double x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*= x; + y.im*= x; + + return y; +} + +CComplex operator/( const CComplex& x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return x*y; +} + +//****** Equals definitions ******************************** + +void CComplex::operator=(double z) +{ + re=z; + im=0; +} + +void CComplex::operator=(int z) +{ + re=(double) z; + im=0; + +} + +//***** Tests *********************************************** +BOOL CComplex::operator==( const CComplex& z){ + if ((z.im==im) && (z.re==re)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator==(double z){ + if ((z==re) && (im==0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator==(int z){ + if ((re==(double) z) && (im==0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator!=( const CComplex& z){ + if ((z.re==re) && (z.im==im)) return FALSE; + return TRUE; +} + +BOOL CComplex::operator!=(double z){ + if ((re!=z) || (im!=0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator!=(int z){ + if ((re!=(double) z) || (im!=0)) return TRUE; + return FALSE; +} + +//***** Useful functions ************************************ + +CComplex conj( const CComplex& x) +{ + return CComplex(x.re,-x.im); +} + +CComplex exp( const CComplex& x) +{ + CComplex y; + + y.re=cos(x.im)*exp(x.re); + y.im=sin(x.im)*exp(x.re); + + return y; +} + +CComplex sqrt( const CComplex& x) +{ + double w,z; + CComplex y; + + if((x.re==0) && (x.im==0)) w=0; + else if(fabs(x.re)>fabs(x.im)){ + z=x.im/x.re; + w=sqrt(fabs(x.re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=x.re/x.im; + w=sqrt(fabs(x.im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(x.re>=0){ + y.re=w; + y.im=x.im/(2.*w); + return y; + } + + if(x.im>=0){ + y.re=fabs(x.im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(x.im)/(2.*w); + y.im= (-w); + + return y; +} + +CComplex tanh( const CComplex& x) +{ + CComplex y; + + if (x.re>0){ + y=(1-exp(-2*x))/(1+exp(-2*x)); + } + else{ + y=(exp(2*x)-1)/(exp(2*x)+1); + } + + return y; +} + +CComplex sinh( const CComplex& x) +{ + return (exp(x)-exp(-x))/2; +} + +CComplex cosh( const CComplex& x) +{ + return (exp(x)+exp(-x))/2; +} + + +CComplex cos( const CComplex& x) +{ + return (exp(I*x)+exp(-I*x))/2; +} + +CComplex acos( const CComplex& x) +{ + return PI/2. - arg(I*x + sqrt(1 - x*x)) + I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex sin( const CComplex& x) +{ + return (exp(I*x)-exp(-I*x))/(2*I); +} + +CComplex asin( const CComplex& x) +{ + return arg(I*x + sqrt(1 - x*x)) - I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex tan( const CComplex& x) +{ + return sin(x)/cos(x); +} + +CComplex atan( const CComplex& x) +{ + return (arg(1+I*x) - arg(1-I*x) - I*(log(abs(1+I*x)/abs(1-I*x))))/ 2; +} + +double abs( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + if (fabs(x.re)>fabs(x.im)) + return fabs(x.re)*sqrt(1.+(x.im/x.re)*(x.im/x.re)); + else + return fabs(x.im)*sqrt(1.+(x.re/x.im)*(x.re/x.im)); +} + +double arg( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + return atan2(x.im,x.re); +} + +CComplex log( const CComplex& x) +{ + CComplex y; + + y.im=arg(x); + y.re=log(abs(x)); + + return y; +} + +CComplex pow( const CComplex& x, double y) +{ + return exp(y*log(x)); +} + +CComplex pow( const CComplex& x, int y) +{ + if (y==0) return CComplex(1,0); + + int i; + CComplex z; + + if (y>0){ + z=x; + for(i=1;i // just needs afx.h to define BOOL, TRUE, and FALSE +#define PI 3.141592653589793238462643383 +#define SmallNo 1.e-14 +#define DEG 0.01745329251994329576923690768 + +class CComplex +{ + public: + // data members + double re,im; + + // member functions + CComplex(); + CComplex(double x); + CComplex(int x); + CComplex(double x, double y); + CComplex Sqrt(); + CComplex Conj(); + CComplex Inv(); + void Set(double x, double y); + double Abs(); + double Arg(); + double Re(); + double Im(); + char* ToString(char *s); + + //operator redefinition + //Addition + CComplex operator+( const CComplex& z ); + CComplex operator+(double z); + CComplex operator+(int z); + friend CComplex operator+( int x, const CComplex& y ); + friend CComplex operator+( double x, const CComplex& y ); + friend CComplex operator+( const CComplex& x, const CComplex& y ); + void operator+=( const CComplex& z); + void operator+=(double z); + void operator+=(int z); + + //Subtraction + CComplex operator-(); + CComplex operator-( const CComplex& z ); + CComplex operator-(double z); + CComplex operator-(int z); + friend CComplex operator-( int x, const CComplex& y ); + friend CComplex operator-( double x, const CComplex& y ); + friend CComplex operator-( const CComplex& x, const CComplex& y ); + friend CComplex operator-( const CComplex& x ); + void operator-=( const CComplex& z); + void operator-=(double z); + void operator-=(int z); + + //Multiplication + CComplex operator*( const CComplex& z ); + CComplex operator*(double z); + CComplex operator*(int z); + friend CComplex operator*( int x, const CComplex& y ); + friend CComplex operator*( double x, const CComplex& y ); + friend CComplex operator*( const CComplex& x, const CComplex& y ); + void operator*=( const CComplex& z); + void operator*=(double z); + void operator*=(int z); + + //Division + CComplex operator/( const CComplex& z ); + CComplex operator/(double z); + CComplex operator/(int z); + friend CComplex operator/( int x, const CComplex& y ); + friend CComplex operator/( double x, const CComplex& y ); + friend CComplex operator/( const CComplex &x, const CComplex& y ); + void operator/=( const CComplex& z); + void operator/=(double z); + void operator/=(int z); + + //Equals + void operator=(double z); + void operator=(int z); + + //Tests + BOOL operator==( const CComplex& z); + BOOL operator==(double z); + BOOL operator==(int z); + BOOL operator!=( const CComplex& z); + BOOL operator!=(double z); + BOOL operator!=(int z); + + private: + +}; + +// useful functions... +#define I CComplex(0,1) +double Re( const CComplex& a); +double Im( const CComplex& a); +double abs( const CComplex& x ); +double arg( const CComplex& x ); +CComplex conj( const CComplex& x); +CComplex exp( const CComplex& x ); +CComplex sqrt( const CComplex& x ); +CComplex tanh( const CComplex& x ); +CComplex sinh( const CComplex& x ); +CComplex cosh( const CComplex& x ); +CComplex cos( const CComplex& x ); +CComplex acos( const CComplex& x ); +CComplex sin( const CComplex& x ); +CComplex asin( const CComplex& x ); +CComplex tan( const CComplex& x ); +CComplex atan( const CComplex& x ); +CComplex log( const CComplex& x ); +CComplex pow( const CComplex& x, int y); +CComplex pow( const CComplex& x, double y); +CComplex pow( const CComplex& x, const CComplex& y); + + + diff --git a/csolv/csolv.cpp b/csolv/csolv.cpp new file mode 100644 index 0000000..2a0556e --- /dev/null +++ b/csolv/csolv.cpp @@ -0,0 +1,82 @@ +// csolv.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "csolv.h" +#include "csolvDlg.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CcsolvApp + +BEGIN_MESSAGE_MAP(CcsolvApp, CWinApp) + //{{AFX_MSG_MAP(CcsolvApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CcsolvApp construction + +CcsolvApp::CcsolvApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +CcsolvApp::~CcsolvApp() +{ + +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CcsolvApp object + +CcsolvApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CcsolvApp initialization + +BOOL CcsolvApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CcsolvDlg dlg; + m_pMainWnd = &dlg; + + dlg.ComLine=m_lpCmdLine; + // SetDialogBkColor(); + _beginthread( old_main, 0, (void *) &dlg ); + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/csolv/cspars.cpp b/csolv/cspars.cpp new file mode 100644 index 0000000..8c740c2 --- /dev/null +++ b/csolv/cspars.cpp @@ -0,0 +1,779 @@ +#include +#include +#include +#include "csolv.h" +#include "csolvDlg.h" +#include "complex.h" +#include "spars.h" + +#define KLUDGE + +CComplexEntry::CComplexEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigComplexLinProb::CBigComplexLinProb() +{ + n=0; +} + +CBigComplexLinProb::~CBigComplexLinProb() +{ + if (n==0) return; + + int i; + CComplexEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + free(Q); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + + free(M); +} + +int CBigComplexLinProb::Create(int d, int bw, int nodes) +{ + int i; + + bdw=bw; + NumNodes=nodes; + b=(CComplex *)calloc(d,sizeof(CComplex)); + V=(CComplex *)calloc(d,sizeof(CComplex)); + P=(CComplex *)calloc(d,sizeof(CComplex)); + R=(CComplex *)calloc(d,sizeof(CComplex)); + U=(CComplex *)calloc(d,sizeof(CComplex)); + Z=(CComplex *)calloc(d,sizeof(CComplex)); + Q=(BOOL *)calloc(d,sizeof(BOOL)); + + M=(CComplexEntry **)calloc(d,sizeof(CComplexEntry *)); + n=d; + + for(i=0;ic = i; + } + + return 1; +} + +void CBigComplexLinProb::Put(CComplex v, int p, int q) +{ + CComplexEntry *e,*l; + int i; + + if(qc < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CComplexEntry *m = new CComplexEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + + return; +} + +CComplex CBigComplexLinProb::Get(int p, int q) +{ + CComplexEntry *e; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) return e->x; + + // if no entry in the list, this entry must be zero... + return CComplex(0,0); +} + +void CBigComplexLinProb::MultA(CComplex *X, CComplex *Y) +{ + int i; + CComplexEntry *e; + + for(i=0;ix*X[i]); + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=(e->x*X[e->c]); + Y[e->c]+=(e->x*X[i]); + e=e->next; + } + } +} + +void CBigComplexLinProb::MultConjA(CComplex *X, CComplex *Y) +{ + int i; + CComplexEntry *e; + + for(i=0;ix.Conj()*X[i]); + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=(e->x.Conj()*X[e->c]); + Y[e->c]+=(e->x.Conj()*X[i]); + e=e->next; + } + } +} + +void CBigComplexLinProb::MultAPPA(CComplex *X, CComplex *Y) +{ + int i; + MultA(X,Z); + MultPC(Z,Y); + for(i=0;ix; */ + + // SSOR preconditioner + int i; + CComplex c; + CComplexEntry *e; + + c= Lambda*(2-Lambda); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * Lambda; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * Lambda; + e=e->next; + } + Y[i]/= M[i]->x; + } +} + +int CBigComplexLinProb::PBCGSolve(int flag) +{ + int i; + CComplex res,res_new,del,rho,pAp; + double er,res_o; + + // quick check for most obvious sign of singularity; + for(i=0;ix.re==0) && (M[i]->x.im==0)){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"BiConjugate Gradient Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // Guess for best relaxation parameter + Lambda=1.5; + + // residual with V=0 + MultPC(b,Z); + res_o=abs(Dot(Z,b)); + if(res_o==0) return 1; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>(Precision*0.01)); + + return 1; +} + +void CBigComplexLinProb::SetValue(int i, CComplex x) +{ + int k,fst,lst; + CComplex z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>NumNodes) lst=NumNodes; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigComplexLinProb::AntiPeriodicity(int i, int j) +{ + int k,fst,lst; + CComplex v1,v2,c; + +#ifdef KLUDGE + int tmpbdw=bdw; + bdw=0; +#endif + + if (jNumNodes-1) lst=NumNodes-1; + } + + for(k=fst;kNumNodes-1) lst=NumNodes-1; + } + + for(k=fst;kx.re==0) && (M[i]->x.im==0)){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"QMR Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er > Precision); + + return 1; +} + +// Make into a Hermitian problem and solve. +// This ought to be slower than BiPCG, but the idea is to avoid +// the situations where BiPCG breaks down. +// This works, but to do the whole problem this way can be +// painfully slow in practice. +int CBigComplexLinProb::PCGSQSolve(int flag) +{ + int i; + CComplex res,res_new,del,rho,pAp; + double er,res_o; + + // quick check for most obvious sign of singularity; + for(i=0;ix.re==0) && (M[i]->x.im==0)){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"Conjugate Gradient Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // Guess for best relaxation parameter + Lambda=1.0; + + // Operate on RHS to scale for squared problem + MultPC(b,Z); + for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>Precision); + + return 1; +} + +// Make into a Hermitian problem and solve. +// Just use for a few iterations to get a good starting point +// for the regular BiPCG, which can sometimes get initialized +// with a pathological starting point. +int CBigComplexLinProb::PCGSQStart(int flag) +{ + int i,k; + CComplex res,res_new,del,rho,pAp; + + // quick check for most obvious sign of singularity; + for(i=0;ix.re==0) && (M[i]->x.im==0)){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // Guess for best relaxation parameter + Lambda=1.0; + + // Operate on RHS to scale for squared problem + MultPC(b,Z); + for(i=0;im_prog1.SetPos(0); + int prg1=0; + int prg2; + + // get starting point; singularity check; + if(flag==FALSE){ + TheView->SetDlgItemText(IDC_FRAME1,"Initializing Solver"); + if (PCGSQStart(flag)==0) return 0; + } + TheView->SetDlgItemText(IDC_FRAME1,"BiConjugate Gradient Solver"); + + // Guess for best relaxation parameter + Lambda=1.5; + + // residual with V from PCGSQ + // if flag==TRUE, carry residual target over from the last iteration. + if (flag==FALSE) + { + MultPC(V,Z); + res_o=abs(Dot(Z,V)); + if(res_o==0) return 1; + } + + // form residual; + MultA(V,R); + for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>(Precision*0.01)); + + return 1; +} diff --git a/csolv/femmedoccore.cpp b/csolv/femmedoccore.cpp new file mode 100644 index 0000000..8fd1705 --- /dev/null +++ b/csolv/femmedoccore.cpp @@ -0,0 +1,682 @@ +// FemmeDocCore.cpp : implementation of the CFemmeDocCore class +// + + +#include +#include +#include +#include +#include +#include "complex.h" +#include "csolv.h" +#include "csolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDocCore construction/destruction + +CFemmeDocCore::CFemmeDocCore() +{ + TheView=NULL; + Precision=NULL; + LengthUnits=NULL; + ProblemType=NULL; + Coords=NULL; + BandWidth=NULL; + NumNodes=NULL; + NumEls=NULL; + NumBlockProps=NULL; + NumPBCs=NULL; + NumLineProps=NULL; + NumPointProps=NULL; + NumCircProps=NULL; + NumBlockLabels=NULL; + + meshnode=NULL; + meshele=NULL; + blockproplist=NULL; + lineproplist=NULL; + nodeproplist=NULL; + circproplist=NULL; + labellist=NULL; + pbclist=NULL; + PathName=NULL; + + extRo=extRi=extZo=NULL; +} + +CFemmeDocCore::~CFemmeDocCore() +{ + // This space for rent. +} + +void CFemmeDocCore::CleanUp() +{ + if (meshnode!=NULL) free(meshnode); + if (meshele!=NULL) free(meshele); + if (blockproplist!=NULL) free(blockproplist); + if (lineproplist!=NULL) free(lineproplist); + if (nodeproplist!=NULL) free(nodeproplist); + if (circproplist!=NULL) free(circproplist); + if (labellist!=NULL) free(labellist); + if (pbclist!=NULL) free(pbclist); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDocCore commands + +char* StripKey(char *c) +{ + char *d; + int i,k; + + k=(int)strlen(c); + + for(i=0;i0) nodeproplist=(CPointProp *)calloc(k,sizeof(CPointProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + PProp.V=0; + PProp.qp=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + nodeproplist[NumPointProps]=PProp; + NumPointProps++; + q[0]=NULL; + } + + // Boundary Properties; + if( _strnicmp(q,"[bdryprops]",11)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) lineproplist=(CBoundaryProp *)calloc(k,sizeof(CBoundaryProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + BProp.BdryFormat=0; + BProp.V=0; + BProp.qs=0; + BProp.c0=0; + BProp.c1=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0){ + v=StripKey(s); + sscanf(v,"%i",&BProp.BdryFormat); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0.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.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c1.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + lineproplist[NumLineProps]=BProp; + NumLineProps++; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"[blockprops]",12)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) blockproplist=(CMaterialProp *)calloc(k,sizeof(CMaterialProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0){ + MProp.ex=1; + MProp.ey=1; + MProp.ox=1; + MProp.oy=1; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ox); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.oy); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ex.re); + MProp.ex.im=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey.re); + MProp.ey.im=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + double lt; + sscanf(v,"%lf",<); + lt=-atan(lt); + MProp.ex=MProp.ex*exp(I*lt); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + double lt; + sscanf(v,"%lf",<); + lt=-atan(lt); + MProp.ey=MProp.ey*exp(I*lt); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + MProp.kx=MProp.ox/eo+I*Frequency*MProp.ex; + MProp.ky=MProp.oy/eo+I*Frequency*MProp.ey; + blockproplist[NumBlockProps]=MProp; + NumBlockProps++; + q[0]=NULL; + } + + // Conductor Properties + if( _strnicmp(q,"[conductorprops]",16)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) circproplist=(CCircuit *)calloc(k,sizeof(CCircuit)); + q[0]=NULL; + } + + if( _strnicmp(q,"",16)==0){ + CProp.V=0; + CProp.q=0; + CProp.CircType=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.q.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.q.im); + 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[NumCircProps]=CProp; + NumCircProps++; + q[0]=NULL; + } + + // read in regional attributes + if(_strnicmp(q,"[numblocklabels]",13)==0){ + int i; + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) labellist=(CBlockLabel *)calloc(k, sizeof(CBlockLabel)); + NumBlockLabels=k; + for(i=0;i1){ + // strip off point BC number; + j=n & 0xffff; + j=j-2; + if (j<0) j=-1; + + // strip off Conductor number + n= (n - (n & 0xffff))/0x10000 - 1; + } + else{ + j=-1; + n=-1; + } + node.bc=j; + node.InConductor=n; + + // convert all lengths to internal working units of mm + node.x*=c[LengthUnits]; + node.y*=c[LengthUnits]; + + meshnode[i]=node; + } + fclose(fp); + + //read in periodic boundary conditions; + sprintf(infile,"%s.pbc",PathName); + if((fp=fopen(infile,"rt"))==NULL){ + return FALSE; + } + fgets(s,1024,fp); + sscanf(s,"%i",&NumPBCs); + + if (NumPBCs!=0) pbclist=(CCommonPoint *)calloc(NumPBCs,sizeof(CCommonPoint)); + CCommonPoint pbc; + for(i=0;i=0) + { + meshnode[n0].InConductor=n; + meshnode[n1].InConductor=n; + } + } + else j=-1; + + if (j>=0) + { + // search through elements to find one containing the line; + // set corresponding edge equal to the bc number + for(q=0,n=FALSE;q + = "Copper" + = 58000000 + = 58000000 + = 1 + = 1 + = 0 + = 0 + + + + = "Aluminum" + = 37700000 + = 37700000 + = 1 + = 1 + = 0 + = 0 + + diff --git a/debug/heatlib.dat b/debug/heatlib.dat new file mode 100644 index 0000000..52e4b1d --- /dev/null +++ b/debug/heatlib.dat @@ -0,0 +1,1537 @@ + + = "Metallic Solids" + + = "Aluminum" + + = "Aluminum, 2024-T6" + = 171 + = 171 + = 0 + = 0 + = 2 + 273 171 + 473 186 + + + + = "Aluminum, Pure" + = 236 + = 236 + = 0 + = 0 + = 4 + 273 236 + 473 238 + 673 228 + 873 215 + + + + + = "Beryllium" + = 218 + = 218 + = 0 + = 0 + = 6 + 273 218 + 473 144 + 673 118 + 873 100 + 1073 83 + 1273 69 + + + + = "Boron" + = 31.699999999999999 + = 31.699999999999999 + = 0 + = 0 + = 6 + 273 31.699999999999999 + 473 18.300000000000001 + 673 10 + 873 7.4000000000000004 + 1073 5.9000000000000004 + 1273 4.7999999999999998 + + + + = "Cadmium" + = 104 + = 104 + = 0 + = 0 + = 2 + 273 104 + 473 99 + + + + = "Chromium" + = 95 + = 95 + = 0 + = 0 + = 6 + 273 95 + 473 86 + 673 77 + 873 69 + 1073 64 + 1273 62 + + + + = "Cobalt" + = 104 + = 104 + = 0 + = 0 + + + + = "Copper" + + = "Constantan" + = 22 + = 22 + = 0 + = 0 + = 2 + 273 22 + 473 26 + + + + = "Copper, Pure" + = 401 + = 401 + = 0 + = 0 + = 6 + 273 401 + 473 389 + 673 378 + 873 366 + 1073 352 + 1273 336 + + + + = "Brass" + = 110 + = 110 + = 0 + = 0 + = 3 + 273 110 + 473 142 + 673 151 + + + + = "Bronze" + = 49 + = 49 + = 0 + = 0 + = 3 + 273 49 + 473 54 + 673 61 + + + + + = "Germanium" + = 67 + = 67 + = 0 + = 0 + = 4 + 273 67 + 473 40 + 673 19 + 873 17 + + + + = "Gold" + = 318 + = 318 + = 0 + = 0 + = 6 + 273 318 + 473 309 + 673 299 + 873 286 + 1073 273 + 1273 254 + + + + = "Iron" + + = "Iron, Wrought" + = 59 + = 59 + = 0 + = 0 + = 4 + 273 59 + 473 52 + 673 45 + 873 33 + + + + = "Iron, Pure" + = 83 + = 83 + = 0 + = 0 + = 6 + 273 83 + 473 66 + 673 53 + 873 41 + 1073 32 + 1273 30 + + + + = "Iron, Cast (4% C)" + = 52 + = 52 + = 0 + = 0 + = 5 + 273 52 + 473 40 + 673 34 + 873 24 + 1073 21 + + + + = "Iron, Armco" + = 75 + = 75 + = 0 + = 0 + = 6 + 273 75 + 473 62 + 673 49 + 873 38 + 1073 29 + 1273 29 + + + + + = "Steels" + + = "Steel, 1% Chrome" + = 62 + = 62 + = 0 + = 0 + = 5 + 273 62 + 473 52 + 673 42 + 873 36 + 1073 33 + + + + = "Steel, 1% Carbon" + = 43 + = 43 + = 0 + = 0 + = 5 + 273 43 + 473 42 + 673 36 + 873 29 + 1073 28 + + + + = "347 Stainless Steel" + = 14 + = 14 + = 0 + = 0 + = 6 + 273 14 + 473 17 + 673 19 + 873 23 + 1073 25 + 1273 26 + + + + = "304 Stainless Steel" + = 14 + = 14 + = 0 + = 0 + = 5 + 273 14 + 473 18 + 673 21 + 873 24 + 1073 26 + + + + + = "Lead" + = 36 + = 36 + = 0 + = 0 + = 2 + 273 36 + 473 33 + + + + = "Lithium" + = 79 + = 79 + = 0 + = 0 + + + + = "Magnesium" + = 157 + = 157 + = 0 + = 0 + = 4 + 273 157 + 473 151 + 673 147 + 873 145 + + + + = "Manganese" + = 7.7000000000000002 + = 7.7000000000000002 + = 0 + = 0 + + + + = "Molybdenum" + = 139 + = 139 + = 0 + = 0 + = 6 + 273 139 + 473 131 + 673 123 + 873 116 + 1073 109 + 1273 103 + + + + = "Nickel" + + = "Nickel, Pure" + = 94 + = 94 + = 0 + = 0 + = 6 + 273 94 + 473 74 + 673 65 + 873 69 + 1073 73 + 1273 78 + + + + = "Nichrome" + = 12 + = 12 + = 0 + = 0 + = 4 + 273 12 + 473 15 + 673 18 + 873 23 + + + + = "Inconel-X" + = 11 + = 11 + = 0 + = 0 + = 6 + 273 11 + 473 14 + 673 18 + 873 22 + 1073 25 + 1273 29 + + + + + = "Platinum" + + = "Platnium, Pure" + = 72 + = 72 + = 0 + = 0 + = 6 + 273 72 + 473 72 + 673 74 + 873 76 + 1073 80 + 1273 84 + + + + = "60% Pt, 40% Rh" + = 46 + = 46 + = 0 + = 0 + = 6 + 273 46 + 473 54 + 673 62 + 873 66 + 1073 70 + 1273 74 + + + + + = "Rhenium" + = 49 + = 49 + = 0 + = 0 + = 6 + 273 49 + 473 45 + 673 44 + 873 44 + 1073 45 + 1273 46 + + + + = "Rhodium" + = 151 + = 151 + = 0 + = 0 + = 6 + 273 151 + 473 141 + 673 132 + 873 125 + 1073 119 + 1273 113 + + + + = "Silicon" + = 168 + = 168 + = 0 + = 0 + = 6 + 273 168 + 473 93 + 673 59 + 873 41 + 1073 30 + 1273 25 + + + + = "Silver" + = 428 + = 428 + = 0 + = 0 + = 6 + 273 428 + 473 415 + 673 399 + 873 383 + 1073 368 + 1273 355 + + + + = "Sodium" + = 135 + = 135 + = 0 + = 0 + + + + = "Tin" + = 68 + = 68 + = 0 + = 0 + = 2 + 273 68 + 473 60 + + + + = "Titanium" + = 22 + = 22 + = 0 + = 0 + = 6 + 273 22 + 473 20 + 673 19 + 873 20 + 1073 21 + 1273 23 + + + + = "Tungsten" + = 182 + = 182 + = 0 + = 0 + = 6 + 273 182 + 473 152 + 673 134 + 873 125 + 1073 118 + 1273 114 + + + + = "Uranium" + = 27 + = 27 + = 0 + = 0 + = 5 + 273 27 + 473 30 + 673 35 + 873 39 + 1073 45 + + + + = "Vanadium" + = 31 + = 31 + = 0 + = 0 + = 6 + 273 31 + 473 33 + 673 35 + 873 37 + 1073 40 + 1273 44 + + + + = "Zinc" + = 122 + = 122 + = 0 + = 0 + = 3 + 273 122 + 473 112 + 673 102 + + + + = "Zirconium" + = 23 + = 23 + = 0 + = 0 + = 6 + 273 23 + 473 21 + 673 21 + 873 22 + 1073 24 + 1273 26 + + + + + = "Nonmetallic Solids" + + = "Aluminum Oxide" + = 40 + = 40 + = 0 + = 0 + = 6 + 273 40 + 473 22 + 673 13 + 873 9.3000000000000007 + 1073 7.2999999999999998 + 1273 6.2000000000000002 + + + + = "Asbestos" + = 0.11 + = 0.11 + = 0 + = 0 + + + + = "Beryllium Oxide" + = 302 + = 302 + = 0 + = 0 + = 6 + 273 302 + 473 159 + 673 93 + 873 60 + 1073 41 + 1273 30 + + + + = "Bricks" + + = "Brick, Common" + = 0.69999999999999996 + = 0.69999999999999996 + = 0 + = 0 + + + + = "Brick, Chrome" + = 2.2000000000000002 + = 2.2000000000000002 + = 0 + = 0 + = 5 + 273 2.2000000000000002 + 473 2.2999999999999998 + 673 2.3999999999999999 + 873 2.3999999999999999 + 1073 2.1000000000000001 + + + + = "Brick, Fireclay" + = 1 + = 1 + = 0 + = 0 + = 2 + 273 1 + 1273 1.1000000000000001 + + + + = "Brick, Magnesite" + = 4 + = 4 + = 0 + = 0 + = 6 + 273 4 + 473 3.6000000000000001 + 673 2.7999999999999998 + 873 2.3999999999999999 + 1073 2.1000000000000001 + 1273 1.8 + + + + = "Brick, Masonry" + = 0.66000000000000003 + = 0.66000000000000003 + = 0 + = 0 + + + + = "Brick, Silica" + = 1.1000000000000001 + = 1.1000000000000001 + = 0 + = 0 + + + + + = "Carbon" + = 1.6000000000000001 + = 1.6000000000000001 + = 0 + = 0 + = 6 + 273 1.6000000000000001 + 473 1.8999999999999999 + 673 2.2000000000000002 + 873 2.3999999999999999 + 1073 2.6000000000000001 + 1273 2.7999999999999998 + + + + = "Cement Mortar" + = 0.90000000000000002 + = 0.90000000000000002 + = 0 + = 0 + + + + = "Concrete" + = 1 + = 1 + = 0 + = 0 + + + + = "Coal" + = 0.23999999999999999 + = 0.23999999999999999 + = 0 + = 0 + + + + = "Diamonds" + + = "Type I" + = 1000 + = 1000 + = 0 + = 0 + = 2 + 273 1000 + 473 300 + + + + = "Type IIa" + = 2650 + = 2650 + = 0 + = 0 + = 2 + 273 2650 + 473 1300 + + + + = "Type IIb" + = 1510 + = 1510 + = 0 + = 0 + = 2 + 273 1510 + 473 780 + + + + + = "Earths" + + = "Clay" + = 1.3999999999999999 + = 1.3999999999999999 + = 0 + = 0 + + + + = "Diatomaceous" + = 1.3 + = 1.3 + = 0 + = 0 + + + + = "Sand" + = 0.29999999999999999 + = 0.29999999999999999 + = 0 + = 0 + + + + + = "Glasses" + + = "Corning 7740" + = 1.1000000000000001 + = 1.1000000000000001 + = 0 + = 0 + = 4 + 273 1.1000000000000001 + 473 1.3 + 673 1.5 + 873 1.8999999999999999 + + + + = "Pyroceram" + = 4.0999999999999996 + = 4.0999999999999996 + = 0 + = 0 + = 6 + 273 4.0999999999999996 + 473 3.6000000000000001 + 673 3.2000000000000002 + 873 3 + 1073 2.8999999999999999 + 1273 2.7999999999999998 + + + + = "Window" + = 0.83999999999999997 + = 0.83999999999999997 + = 0 + = 0 + + + + + = "Ice" + = 2.2000000000000002 + = 2.2000000000000002 + = 0 + = 0 + + + + = "Insulations" + + = "Cork, granular" + = 0.044999999999999998 + = 0.044999999999999998 + = 0 + = 0 + + + + = "Corkboard" + = 0.042999999999999997 + = 0.042999999999999997 + = 0 + = 0 + + + + = "Cellulose, loose" + = 0.037999999999999999 + = 0.037999999999999999 + = 0 + = 0 + + + + = "Feltboard" + = 0.035000000000000003 + = 0.035000000000000003 + = 0 + = 0 + + + + = "Glass Fiber" + = 0.035000000000000003 + = 0.035000000000000003 + = 0 + = 0 + + + + = "Glass Wool" + = 0.037999999999999999 + = 0.037999999999999999 + = 0 + = 0 + + + + = "Kapok" + = 0.035000000000000003 + = 0.035000000000000003 + = 0 + = 0 + + + + = "Magnesia, 85%" + = 0.065000000000000002 + = 0.065000000000000002 + = 0 + = 0 + = 2 + 273 0.065000000000000002 + 473 0.085000000000000006 + + + + = "Polystyrene" + = 0.025000000000000001 + = 0.025000000000000001 + = 0 + = 0 + + + + = "Rubber, Foam" + = 0.029999999999999999 + = 0.029999999999999999 + = 0 + = 0 + + + + = "Rock Wool" + = 0.058999999999999997 + = 0.058999999999999997 + = 0 + = 0 + + + + = "Sawdust" + = 0.058999999999999997 + = 0.058999999999999997 + = 0 + = 0 + + + + = "Vermiculite, loose" + = 0.058000000000000003 + = 0.058000000000000003 + = 0 + = 0 + + + + + = "Magnesium Oxide" + = 53 + = 53 + = 0 + = 0 + = 6 + 273 53 + 473 29 + 673 18 + 873 12 + 1073 8.8000000000000007 + 1273 7.2999999999999998 + + + + = "Plaster" + = 0.5 + = 0.5 + = 0 + = 0 + + + + = "Quartz, fused" + = 1.3 + = 1.3 + = 0 + = 0 + = 6 + 273 1.3 + 473 1.6000000000000001 + 673 1.8999999999999999 + 873 2.2999999999999998 + 1073 3.2000000000000002 + 1273 3.7999999999999998 + + + + = "Rocks" + + = "Granite" + = 3 + = 3 + = 0 + = 0 + + + + = "Limestone" + = 2 + = 2 + = 0 + = 0 + + + + = "Marble" + = 2.7000000000000002 + = 2.7000000000000002 + = 0 + = 0 + + + + = "Sandstone" + = 2.7999999999999998 + = 2.7999999999999998 + = 0 + = 0 + + + + + = "Rubber, hard" + = 0.16 + = 0.16 + = 0 + = 0 + + + + = "Skin, human" + = 0.37 + = 0.37 + = 0 + = 0 + + + + = "Snow" + + = "Snow, loose" + = 0.050000000000000003 + = 0.050000000000000003 + = 0 + = 0 + + + + = "Snow, packed" + = 0.19 + = 0.19 + = 0 + = 0 + + + + + = "Teflon" + = 0.34999999999999998 + = 0.34999999999999998 + = 0 + = 0 + + + + = "Woods" + + = "Balsa" + = 0.055 + = 0.055 + = 0 + = 0 + + + + = "Cypress" + = 0.097000000000000003 + = 0.097000000000000003 + = 0 + = 0 + + + + = "Fir" + = 0.11 + = 0.11 + = 0 + = 0 + + + + = "Maple" + = 0.17000000000000001 + = 0.17000000000000001 + = 0 + = 0 + + + + = "Oak" + = 0.17000000000000001 + = 0.17000000000000001 + = 0 + = 0 + + + + = "Pine, yellow" + = 0.14999999999999999 + = 0.14999999999999999 + = 0 + = 0 + + + + = "Pine, white" + = 0.11 + = 0.11 + = 0 + = 0 + + + + = "Plywood" + = 0.12 + = 0.12 + = 0 + = 0 + + + + + = "Wool" + = 0.037999999999999999 + = 0.037999999999999999 + = 0 + = 0 + + + + + = "Liquid Metals" + + = "Bismuth, liquid" + = 16.800000000000001 + = 16.800000000000001 + = 0 + = 0 + = 6 + 545 16.800000000000001 + 600 16.399999999999999 + 700 15.6 + 800 15.6 + 900 15.6 + 1000 15.6 + + + + = "Lead, liquid" + = 15.5 + = 15.5 + = 0 + = 0 + = 5 + 601 15.5 + 700 17.399999999999999 + 800 19 + 900 20.300000000000001 + 1000 21.5 + + + + = "Mercury" + = 142 + = 142 + = 0 + = 0 + = 7 + 234 142 + 273 140 + 300 139 + 350 138 + 400 137 + 500 136 + 600 134 + + + + = "Lithium, liquid" + = 43 + = 43 + = 0 + = 0 + = 7 + 454 43 + 500 44 + 600 48 + 700 51 + 800 54 + 900 57 + 1000 60 + + + + = "Potassium, liquid" + = 55 + = 55 + = 0 + = 0 + = 8 + 337 55 + 400 52 + 500 48 + 600 44 + 700 40 + 800 37 + 900 34 + 1000 31 + + + + = "Sodium, liquid" + = 88 + = 88 + = 0 + = 0 + = 8 + 371 88 + 400 87 + 500 82 + 600 76 + 700 72 + 800 67 + 900 63 + 1000 58 + + + + + = "Saturated Liquids" + + = "Ammonia" + = 0.54600000000000004 + = 0.54600000000000004 + = 0 + = 0 + = 5 + 233 0.54600000000000004 + 253 0.54600000000000004 + 273 0.54000000000000004 + 293 0.52100000000000002 + 313 0.49299999999999999 + + + + = "Ethyl Alcohol" + = 0.186 + = 0.186 + = 0 + = 0 + = 7 + 233 0.186 + 253 0.17899999999999999 + 273 0.17399999999999999 + 293 0.16800000000000001 + 313 0.16200000000000001 + 333 0.156 + 353 0.14999999999999999 + + + + = "Ethylene Glycol" + = 0.254 + = 0.254 + = 0 + = 0 + = 6 + 273 0.254 + 293 0.25700000000000001 + 313 0.25900000000000001 + 333 0.26200000000000001 + 353 0.26500000000000001 + 373 0.26700000000000002 + + + + = "Freon-12" + = 0.069000000000000006 + = 0.069000000000000006 + = 0 + = 0 + = 5 + 233 0.069000000000000006 + 253 0.070999999999999994 + 273 0.072999999999999995 + 293 0.072999999999999995 + 313 0.069000000000000006 + + + + = "Glycerin" + = 0.28199999999999997 + = 0.28199999999999997 + = 0 + = 0 + = 4 + 253 0.28199999999999997 + 273 0.28399999999999997 + 293 0.28699999999999998 + 313 0.28999999999999998 + + + + = "Unused Engine Oil" + = 0.14699999999999999 + = 0.14699999999999999 + = 0 + = 0 + = 2 + 273 0.14699999999999999 + 433 0.13200000000000001 + + + + = "Water" + = 0.56399999999999995 + = 0.56399999999999995 + = 0 + = 0 + = 12 + 273.19999999999999 0.56399999999999995 + 280 0.58199999999999996 + 300 0.60799999999999998 + 320 0.63700000000000001 + 340 0.65900000000000003 + 360 0.67400000000000004 + 373.19999999999999 0.68100000000000005 + 400 0.68600000000000005 + 450 0.67300000000000004 + 500 0.63500000000000001 + 550 0.57099999999999995 + 600 0.48099999999999998 + + + + + = "Gases at 1 atm" + + = "Air" + = 0.018100000000000002 + = 0.018100000000000002 + = 0 + = 0 + = 18 + 200 0.018100000000000002 + 250 0.0223 + 300 0.026100000000000002 + 350 0.029700000000000001 + 400 0.033099999999999997 + 450 0.036299999999999999 + 500 0.0395 + 550 0.042599999999999999 + 600 0.045600000000000002 + 700 0.051299999999999998 + 800 0.056899999999999999 + 900 0.0625 + 1000 0.067199999999999996 + 1200 0.075899999999999995 + 1400 0.083500000000000005 + 1600 0.090399999999999994 + 1800 0.097000000000000003 + 2000 0.1032 + + + + = "Ammonia" + = 0.015299999999999999 + = 0.015299999999999999 + = 0 + = 0 + = 9 + 200 0.015299999999999999 + 300 0.0246 + 400 0.036400000000000002 + 500 0.050599999999999999 + 600 0.065600000000000006 + 700 0.081100000000000005 + 800 0.097699999999999995 + 900 0.11459999999999999 + 1000 0.13170000000000001 + + + + = "Argon" + = 0.0124 + = 0.0124 + = 0 + = 0 + = 14 + 200 0.0124 + 300 0.0177 + 400 0.0223 + 500 0.0264 + 600 0.030099999999999998 + 700 0.033599999999999998 + 800 0.036900000000000002 + 900 0.039800000000000002 + 1000 0.042700000000000002 + 1200 0.048099999999999997 + 1400 0.053499999999999999 + 1600 0.058799999999999998 + 1800 0.064100000000000004 + 2000 0.069199999999999998 + + + + = "Carbon Dioxide" + = 0.0094999999999999998 + = 0.0094999999999999998 + = 0 + = 0 + = 7 + 200 0.0094999999999999998 + 500 0.032300000000000002 + 600 0.040300000000000002 + 800 0.056000000000000001 + 1000 0.068000000000000005 + 1200 0.078 + 1400 0.086699999999999999 + + + + = "Carbon Monoxide" + = 0.017500000000000002 + = 0.017500000000000002 + = 0 + = 0 + = 6 + 200 0.017500000000000002 + 400 0.032300000000000002 + 600 0.044400000000000002 + 800 0.054899999999999997 + 1000 0.064399999999999999 + 1200 0.073800000000000004 + + + + = "Helium" + = 0.115 + = 0.115 + = 0 + = 0 + = 6 + 200 0.115 + 400 0.17999999999999999 + 700 0.27800000000000002 + 1000 0.36299999999999999 + 1400 0.46899999999999997 + 2000 0.62 + + + + = "Hydrogen" + = 0.128 + = 0.128 + = 0 + = 0 + = 6 + 200 0.128 + 400 0.221 + 600 0.29099999999999998 + 900 0.39400000000000002 + 1000 0.42799999999999999 + 1200 0.495 + + + + = "Nitrogen" + = 0.0183 + = 0.0183 + = 0 + = 0 + = 7 + 200 0.0183 + 400 0.032500000000000001 + 600 0.0441 + 800 0.054100000000000002 + 1000 0.063100000000000003 + 1200 0.071300000000000002 + 1400 0.079699999999999993 + + + + = "Oxygen" + = 0.018200000000000001 + = 0.018200000000000001 + = 0 + = 0 + = 7 + 200 0.018200000000000001 + 400 0.034200000000000001 + 600 0.048000000000000001 + 800 0.060299999999999999 + 1000 0.0717 + 1200 0.082100000000000006 + 1400 0.092100000000000001 + + + + = "Steam" + = 0.0264 + = 0.0264 + = 0 + = 0 + = 7 + 400 0.0264 + 500 0.035700000000000003 + 600 0.046399999999999997 + 700 0.057200000000000001 + 800 0.068599999999999994 + 900 0.078 + 1000 0.086999999999999994 + + + diff --git a/debug/init.lua b/debug/init.lua new file mode 100644 index 0000000..a7b62fa --- /dev/null +++ b/debug/init.lua @@ -0,0 +1,679 @@ +-- Define some common quantities for use in Lua + + uo=PI*4.e-7; -- magnetic permeability of free space + eo=8.85418781762e-12; -- electrical permittivity of free space + Pi=PI; pi=PI; -- various ways that one might possibly denote PI + +-- Useful unit definitions + + meter=1; + meters=meter; Meter=meter; Meters=meter; + + inch=0.0254; + inches=inch; Inch=inch; Inches=inch; in=inch; + + cm=0.01; + centimeter=cm; centimeters=cm; Centimeters=cm; Centimeter=cm; + + mm=0.001; + millimeters=mm; millimeter=mm; Millimeter=mm; Millimeters=mm; milimeter=mm; milimeters=mm; + + um=0.000001; + micrometer=um; Micrometer=um; micrometers=um; Micrometers=um; + micron=um; Micron=um; microns=um; Microns=um; + + mil=0.001*inch; + mils=mil; Mils=mil; Mil=mil; + + Tesla = 1; + mTesla = 0.001; + Gauss = 0.0001; + kGauss = 0.1; + AmpMeter = 1; + kAmpMeter = 1000; + Oersted = 250/PI; + kOersted = 1000*Oersted; + +-- Useful functions + + -- Function to determine the diameter in mm of a specified AWG wire gauge + function AWG(awg) return 8.2514694*exp(-0.115943*awg) end + + -- Function to read in BH points for a material from a file + -- Contributed by Dr. Henning Kiel + function mi_setbhpointsfromfile(filename, materialname, unitb, unith, order) + fact_b = Tesla + fact_h = AmpMeter + bh = 1 + + if unitb ~= nil then + fact_b = unitb + end + if unith ~= nil then + fact_h = unith + end + if order == 1 then + bh = 0 + end + + bhfile = openfile(filename,"r") + if bhfile ~= nil then + mi_clearbhpoints(materialname) + if bh == 1 then + b, h = read(bhfile,"*n","*n") + else + h, b = read(bhfile,"*n","*n") + end + while b ~= nil do + mi_addbhpoint(materialname, b, h) + if bh == 1 then + b, h = read(bhfile,"*n","*n") + else + h, b = read(bhfile,"*n","*n") + end + end + closefile(bhfile) + end + end + + + +--permeability tables used to create asymptotic boundary conditions + uAx0 = {{10.06344410876133}, + {0.18870625462846807, 39.997500411566335}, + {4.374794457961015, 0.07511795918154143, 85.85566438727763}, + {0.28509610532711227, 12.493269046515916, 0.051874008856059424, 147.65207370446487}, + {3.0607674892527865, 0.11237818729856126, 22.026456394011774, 0.042316694272791736, 225.43020812455183}, + {0.3748159380792134, 8.172423914252851, 0.07400271964825651, 33.01915762825664, 0.037123381446484645, 319.2335657378115}, + {2.4089242666740582, 0.14929929105743517, 13.817592213008757, 0.05821722458526954, 45.655954531895645, 0.03386729523177279, 429.0464280099345}, + {0.4577193805314985, 6.152383059834071, 0.09519535460494778, 19.79502033933107, 0.04958213970480729, 60.00201778458946, 0.031639182082296755, 554.8893696637082}, + {2.0187133623041955, 0.1872419300750821, 10.322990689266506, 0.07322869764123259, 26.290072452745143, 0.0441395144643266, 76.08450824714102, 0.030019516604331355, 696.7499046385117}, + {0.5332409067449392, 4.931200653946399, 0.11642450959044752, 14.522111149156393, 0.0612363797098224, 33.37497351570902, 0.04039926157266519, 93.91981759395829, 0.028790057140879656, 854.6396765772441}, + {1.7619160942694887, 0.2265234822569949, 8.305694616317721, 0.08811132253969434, 18.911084918162924, 0.053672710920365976, 41.08415574149624, 0.03767250616088464, 113.51592772683063, 0.02782511889284403, 1028.551339640375}, + {0.6010640087773658, 4.100907065931257, 0.13795163994918203, 11.604922157909524, 0.07274062063786199, 23.5602014704398, 0.048468764953025635, 49.437385787628045, 0.035597711447375925, 134.87895858524496, 0.02704793878013551, 1218.4906640339432}}; + u2D0 = {{10.523809523809524}, + {0.14531359011819187, 32.14290974079077}, + {5.14939698507243, 0.053268993904189134, 54.10636468483519}, + {0.2419609512179885, 13.681253040072905, 0.03301443572330777, 76.07498920312688}, + {3.4661091134486472, 0.09209257399023746, 21.797339506447933, 0.02406322785653838, 98.05449854377491}, + {0.3336928992521675, 9.023667719158183, 0.05789695118959376, 29.573300006204246, 0.018966499540708268, 120.04039743815603}, + {2.649899689611667, 0.12953316809300527, 14.398967120915913, 0.04288257435633827, 37.197476986533054, 0.01566424606410637, 142.03015659052124}, + {0.4194212714207981, 6.739646495379991, 0.0807327554079406, 19.40925290947297, 0.034255287061558344, 44.73740232258131, 0.013346899201001426, 164.02239651319712}, + {2.1751715650719827, 0.16743379223593088, 10.885675868734184, 0.05987838745046158, 24.237375183864483, 0.028600398122246736, 52.225223074983184, 0.0116295354236669, 186.01632084646832}, + {0.4982294821100038, 5.3544134782776664, 0.10291820111116401, 14.696545405270147, 0.048003097591685244, 28.95632726953973, 0.024587012459820066, 59.67849241525681, 0.010305182059498453, 208.01143556937637}, + {1.8696806205952006, 0.2063934470334104, 8.775890039744148, 0.07607619682670601, 18.328256642424236, 0.04023921548166901, 33.60353647639198, 0.021581843440607016, 67.10765452494896, 0.009252450549701629, 230.0074236348898}, + {0.5695628007801712, 4.41799489542221, 0.12499429930905502, 11.902080658968998, 0.06098009575496433, 21.847988015751035, 0.03472775671050834, 38.20087849238854, 0.01924286302232932, 74.51932204012905, 0.00839537165467591, 252.00407064779833}}; + uAx1 = {{0.09090909090909091}, + {10.050515900211503, 0.04349612665401649}, + {0.16015012096541084, 31.212316587655547, 0.035617897941640685}, + {5.075223589959199, 0.06747975164123507, 58.83076738028796, 0.032496412704901965}, + {0.24983741484804536, 13.959519296714365, 0.04850942160789329, 93.62679411332631, 0.030834135426565015}, + {3.438673996192938, 0.10007632616355028, 23.68319910391683, 0.040588823403447945, 135.81886600712073, 0.029800226566381535}, + {0.33861114976053774, 9.11830816329029, 0.06748841981310061, 34.53152988922068, 0.03624009732510784, 185.4917052298402, 0.02909733301094425}, + {2.6364338943965455, 0.13486508168984512, 15.097445398169498, 0.05395605788825772, 46.75319306175651, 0.03349209595847733, 242.6651438041285, 0.028587355212278894}, + {0.4227311219273812, 6.773013674320017, 0.08745530894064872, 21.301429520550652, 0.04651420711694375, 60.44151623434645, 0.03160001126426384, 307.3631853353253, 0.028201318378415573}, + {2.1675591338727647, 0.171316009911807, 11.198891625678383, 0.0680375716016307, 27.948228063433724, 0.041804487302954434, 75.63799976250523, 0.030217675069207188, 379.586805599126, 0.027898435150547626}, + {0.5005548322806631, 5.365891158623955, 0.1079474936583888, 15.594898520264833, 0.05739172309462815, 35.12584682017268, 0.03855673261275498, 92.36682653198929, 0.029164062639383995, 459.3468429136272, 0.027654812310257123}, + {1.864938491614021, 0.20938145992414733, 8.933546101982833, 0.08240945574778373, 20.142380617987286, 0.05066029544301638, 42.87550155678245, 0.036182409831124134, 110.63472923382548, 0.0283338992149914, 546.6150102543896, 0.027453323354323905}}; + u2D1 = {{0.09502262443438914}, + {6.88166880459455, 0.031111060201589526}, + {0.19419749592018187, 18.77264665066931, 0.018482113995736214}, + {4.13289828365353, 0.07309272016758717, 30.28978015498877, 0.013144924639159823}, + {0.28850793996067764, 10.858638831248303, 0.04587715852680953, 41.55718451247941, 0.010198410219328852}, + {2.9967673937356176, 0.1108196834283798, 17.27206665382645, 0.0338142851758244, 52.724541914214335, 0.008330528899783033}, + {0.37737277525645235, 7.720030434644211, 0.0694494258951436, 23.31949550539958, 0.026883543752277105, 63.83965087550882, 0.0070407582729502555}, + {2.384237702546398, 0.14837573304995255, 12.386546277094604, 0.05152181760881001, 29.192574288770942, 0.022352660997929614, 74.923770274119, 0.006096728349565376}, + {0.45973385090978197, 5.972510009155741, 0.09186384125878651, 16.700516539917132, 0.04125859307841753, 34.96454824599637, 0.019147835875477914, 85.98795769304176, 0.005375872372109578}, + {2.007107238545973, 0.1867618188354154, 9.71645432200938, 0.06804320147518493, 20.83198897925314, 0.0345347664671527, 40.67187917337226, 0.01675645545872318, 97.03855732255441, 0.004807428001555607}, + {0.5348507060428623, 4.845115067234294, 0.11394855626850516, 13.144715978348659, 0.05456056293348216, 24.85137913425649, 0.029758772583431677, 46.33524484374972, 0.014901429756097718, 108.07947522964582, 0.004347685758123113}, + {1.755732640246568, 0.22634702476369292, 8.00036486086015, 0.08401892313227052, 16.39879353450492, 0.04577080504067754, 28.795410205618264, 0.026177408464552673, 51.96731893999375, 0.013419338402750022, 119.11324967287628, 0.003968189868637491}}; + +function mi_drawarc(x1,y1,x2,y2,tta,dtta) + mi_addnode(x1,y1); + mi_addnode(x2,y2); + mi_addarc(x1,y1,x2,y2,tta,dtta); +end + +function mi_drawline(x1,y1,x2,y2) + mi_addnode(x1,y1); + mi_addnode(x2,y2); + mi_addsegment(x1,y1,x2,y2); +end + +function mi_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R, n + + x0, x1, y0, y1 = mi_getboundingbox(); + flag, p1, p2, p3 = mi_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + bctype=0; + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + mi_drawarc(x, y + R, x, y - R, 180, 1); + else + mi_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + mi_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + mi_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + mi_addblocklabel(x+re(z),y+im(z)); + mi_selectlabel(x+re(z),y+im(z)); + mi_setblockprop("u" .. k, 1, 0, "", 0, 0, 1); + mi_clearselected(); + if(flag == 0) then + if (bctype==0) then + mi_addmaterial("u" .. k, u2D0[n][k]); + else + mi_addmaterial("u" .. k, u2D1[n][k]); + end + mi_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + mi_addmaterial("u" .. k, uAx0[n][k]); + else + mi_addmaterial("u" .. k, uAx1[n][k]); + end + end + end + + if (bctype==0) then + mi_addboundprop("A=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + mi_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + mi_selectarcsegment(-1.1*R+x, y); + end + mi_setarcsegmentprop(1, "A=0", 0, 0); + mi_clearselected(); + end + + mi_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for electrostatic problems + +function ei_drawarc(x1,y1,x2,y2,tta,dtta) + ei_addnode(x1,y1); + ei_addnode(x2,y2); + ei_addarc(x1,y1,x2,y2,tta,dtta); +end + +function ei_drawline(x1,y1,x2,y2) + ei_addnode(x1,y1); + ei_addnode(x2,y2); + ei_addsegment(x1,y1,x2,y2); +end + +function ei_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = ei_getboundingbox(); + flag, p1, p2, p3 = ei_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + ei_drawarc(x, y + R, x, y - R, 180, 1); + else + ei_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + ei_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + ei_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + ei_addblocklabel(x+re(z),y+im(z)); + ei_selectlabel(x+re(z),y+im(z)); + ei_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + ei_clearselected(); + if(flag == 0) then + if (bctype==0) then + ei_addmaterial("e" .. k, u2D1[n][k]); + else + ei_addmaterial("e" .. k, u2D0[n][k]); + end + ei_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + ei_addmaterial("e" .. k, uAx1[n][k]); + else + ei_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + ei_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + ei_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + ei_selectarcsegment(-1.1*R+x, y); + end + ei_setarcsegmentprop(1, "V=0", 0, 0); + ei_clearselected(); + end + + ei_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for current flow problems + +function ci_drawarc(x1,y1,x2,y2,tta,dtta) + ci_addnode(x1,y1); + ci_addnode(x2,y2); + ci_addarc(x1,y1,x2,y2,tta,dtta); +end + +function ci_drawline(x1,y1,x2,y2) + ci_addnode(x1,y1); + ci_addnode(x2,y2); + ci_addsegment(x1,y1,x2,y2); +end + +function ci_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = ci_getboundingbox(); + flag, p1, p2, p3 = ci_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + ci_drawarc(x, y + R, x, y - R, 180, 1); + else + ci_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + ci_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + ci_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + ci_addblocklabel(x+re(z),y+im(z)); + ci_selectlabel(x+re(z),y+im(z)); + ci_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + ci_clearselected(); + if(flag == 0) then + if (bctype==0) then + ci_addmaterial("e" .. k, u2D1[n][k]); + else + ci_addmaterial("e" .. k, u2D0[n][k]); + end + ci_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + ci_addmaterial("e" .. k, uAx1[n][k]); + else + ci_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + ci_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + ci_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + ci_selectarcsegment(-1.1*R+x, y); + end + ci_setarcsegmentprop(1, "V=0", 0, 0); + ci_clearselected(); + end + + ci_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for heat flow problems + +function hi_drawarc(x1,y1,x2,y2,tta,dtta) + hi_addnode(x1,y1); + hi_addnode(x2,y2); + hi_addarc(x1,y1,x2,y2,tta,dtta); +end + +function hi_drawline(x1,y1,x2,y2) + hi_addnode(x1,y1); + hi_addnode(x2,y2); + hi_addsegment(x1,y1,x2,y2); +end + +function hi_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = hi_getboundingbox(); + flag, p1, p2, p3 = hi_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + hi_drawarc(x, y + R, x, y - R, 180, 1); + else + hi_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + hi_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + hi_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + hi_addblocklabel(x+re(z),y+im(z)); + hi_selectlabel(x+re(z),y+im(z)); + hi_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + hi_clearselected(); + if(flag == 0) then + if (bctype==0) then + hi_addmaterial("e" .. k, u2D1[n][k]); + else + hi_addmaterial("e" .. k, u2D0[n][k]); + end + hi_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + hi_addmaterial("e" .. k, uAx1[n][k]); + else + hi_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + hi_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + hi_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + hi_selectarcsegment(-1.1*R+x, y); + end + hi_setarcsegmentprop(1, "V=0", 0, 0); + hi_clearselected(); + end + + hi_zoomnatural(); +end + +-- convenience functions + +function mi_drawrectangle(x1,y1,x2,y2) + mi_drawline(x1,y1,x2,y1); + mi_drawline(x2,y1,x2,y2); + mi_drawline(x2,y2,x1,y2); + mi_drawline(x1,y2,x1,y1); +end + +function ei_drawrectangle(x1,y1,x2,y2) + ei_drawline(x1,y1,x2,y1); + ei_drawline(x2,y1,x2,y2); + ei_drawline(x2,y2,x1,y2); + ei_drawline(x1,y2,x1,y1); +end + +function ci_drawrectangle(x1,y1,x2,y2) + ci_drawline(x1,y1,x2,y1); + ci_drawline(x2,y1,x2,y2); + ci_drawline(x2,y2,x1,y2); + ci_drawline(x1,y2,x1,y1); +end + +function hi_drawrectangle(x1,y1,x2,y2) + hi_drawline(x1,y1,x2,y1); + hi_drawline(x2,y1,x2,y2); + hi_drawline(x2,y2,x1,y2); + hi_drawline(x1,y2,x1,y1); +end \ No newline at end of file diff --git a/debug/license.txt b/debug/license.txt new file mode 100644 index 0000000..5d33c0d --- /dev/null +++ b/debug/license.txt @@ -0,0 +1,412 @@ + +Finite Element Method Magnetics is distributed under +the terms of the Aladdin Free Public License: + +------------------------------------------------------ + +Aladdin Free Public License +(Version 8, November 18, 1999) +Copyright (C) 1994, 1995, 1997, 1998, 1999 +Aladdin Enterprises,Menlo Park, California, U.S.A. +All rights reserved. + +NOTE: This License is not the same as any of the GNU +Licenses published by the Free Software Foundation. +Its terms are substantially different from those of +the GNU Licenses. If you are familiar with the GNU +Licenses, please read this license with extra care. + +Aladdin Enterprises hereby grants to anyone the +permission to apply this License to their own work, +as long as the entire License (including the above +notices and this paragraph) is copied with no +changes, additions, or deletions except for changing +the first paragraph of Section 0 to include a +suitable description of the work to which the +license is being applied and of the person or entity +that holds the copyright in the work, and, if the +License is being applied to a work created in a +country other than the United States, replacing the +first paragraph of Section 6 with an appropriate +reference to the laws of the appropriate country. + +0. Subject Matter + +This License applies to the computer program known +as "Finite Element Method Magnetics." The "Program", +below, refers to such program. The Program is a +copyrighted work whose copyright is held by David C. +Meeker of Natick, MA, dmeeker@ieee.org (the +"Licensor"). Please note that the program Triangle, +written by Jonathan Shewchuk and used by FEMM +for the purposes of mesh generation is NOT covered +by this license and is subject to its own licensure terms. +The licensure terms for Triangle are attached after +this license. The Lua scripting language used by +FEMM is also distributed under its own licensing +terms. The licensing terms of Lua are also attached. + +A "work based on the Program" means either the +Program or any derivative work of the Program, as +defined in the United States Copyright Act of 1976, +such as a translation or a modification. + +BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY +WORK BASED ON THE PROGRAM), YOU INDICATE YOUR +ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL ITS +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR +MODIFYING THE PROGRAM OR WORKS BASED ON IT. NOTHING +OTHER THAN THIS LICENSE GRANTS YOU PERMISSION TO +MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE +WORKS. THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU +DO NOT ACCEPT THESE TERMS AND CONDITIONS, DO NOT +MODIFY OR DISTRIBUTE THE PROGRAM. + +1. Licenses. + +Licensor hereby grants you the following rights, +provided that you comply with all of the +restrictions set forth in this License and provided, +further, that you distribute an unmodified copy of +this License with the Program: + +(a) You may copy and distribute literal (i.e., +verbatim) copies of the Program's source code as you +receive it throughout the world, in any medium. + +(b) You may modify the Program, create works based +on the Program and distribute copies of such +throughout the world, in any medium. + +2. Restrictions. + +This license is subject to the following restrictions: + +(a) Distribution of the Program or any work based on +the Program by a commercial organization to any +third party is prohibited if any payment is made in +connection with such distribution, whether directly +(as in payment for a copy of the Program) or +indirectly (as in payment for some service related +to the Program, or payment for some product or +service that includes a copy of the Program "without +charge"; these are only examples, and not an +exhaustive enumeration of prohibited activities). +The following methods of distribution involving +payment shall not in and of themselves be a +violation of this restriction: + +(i) Posting the Program on a public access + information storage and retrieval service for + which a fee is received for retrieving + information (such as an on-line service), + provided that the fee is not content- dependent + (i.e., the fee would be the same for retrieving + the same volume of information consisting of + random data) and that access to the service and + to the Program is available independent of any + other product or service. An example of a + service that does not fall under this section + is an on-line service that is operated by a + company and that is only available to customers + of that company. (This is not an exhaustive + enumeration.) + +(ii) Distributing the Program on removable + computer-readable media, provided that the + files containing the Program are reproduced + entirely and verbatim on such media, that all + information on such media be redistributable + for non-commercial purposes without charge, and + that such media are distributed by themselves + (except for accompanying documentation) + independent of any other product or service. + Examples of such media include CD-ROM, magnetic + tape, and optical storage media. (This is not + intended to be an exhaustive list.) An example + of a distribution that does not fall under this + section is a CD-ROM included in a book or + magazine. (This is not an exhaustive + enumeration.) + +(b) Activities other than copying, distribution and +modification of the Program are not subject to this +License and they are outside its scope. Functional +use (running) of the Program is not restricted, and +any output produced through the use of the Program +is subject to this license only if its contents +constitute a work based on the Program (independent +of having been made by running the Program). + +(c) You must meet all of the following conditions +with respect to any work that you distribute or +publish that in whole or in part contains or is +derived from the Program or any part thereof ("the +Work"): + +(i) If you have modified the Program, you must cause + the Work to carry prominent notices stating + that you have modified the Program's files and + the date of any change. In each source file + that you have modified, you must include a + prominent notice that you have modified the + file, including your name, your e-mail address + (if any), and the date and purpose of the + change; + +(ii) You must cause the Work to be licensed as a + whole and at no charge to all third parties + under the terms of this License; + +(iii) If the Work normally reads commands + interactively when run, you must cause it, at + each time the Work commences operation, to + print or display an announcement including an + appropriate copyright notice and a notice that + there is no warranty (or else, saying that you + provide a warranty). Such notice must also + state that users may redistribute the Work only + under the conditions of this License and tell + the user how to view the copy of this License + included with the Work. (Exceptions: if the + Program is interactive but normally prints or + displays such an announcement only at the + request of a user, such as in an "About box", + the Work is required to print or display the + notice only under the same circumstances; if + the Program itself is interactive but does not + normally print such an announcement, the Work + is not required to print an announcement.); + +(iv) You must accompany the Work with the complete + corresponding machine-readable source code, + delivered on a medium customarily used for + software interchange. The source code for a + work means the preferred form of the work for + making modifications to it. For an executable + work, complete source code means all the source + code for all modules it contains, plus any + associated interface definition files, plus the + scripts used to control compilation and + installation of the executable code. If you + distribute with the Work any component that is + normally distributed (in either source or + binary form) with the major components + (compiler, kernel, and so on) of the operating + system on which the executable runs, you must + also distribute the source code of that + component if you have it and are allowed to do + so; + +(v) If you distribute any written or printed + material at all with the Work, such material + must include either a written copy of this + License, or a prominent written indication that + the Work is covered by this License and written + instructions for printing and/or displaying the + copy of the License on the distribution medium; + +(vi) You may not impose any further restrictions on + the recipient's exercise of the rights granted + herein. If distribution of executable or + object code is made by offering the equivalent + ability to copy from a designated place, then + offering equivalent ability to copy the source + code from the same place counts as distribution + of the source code, even though third parties + are not compelled to copy the source code along + with the object code. + +3. Reservation of Rights. + +No rights are granted to the Program except as +expressly set forth herein. You may not copy, +modify, sublicense, or distribute the Program except +as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense or +distribute the Program is void, and will +automatically terminate your rights under this +License. However, parties who have received copies, +or rights, from you under this License will not have +their licenses terminated so long as such parties +remain in full compliance. + +4. Other Restrictions. + +If the distribution and/or use of the Program is +restricted in certain countries for any reason, +Licensor may add an explicit geographical +distribution limitation excluding those countries, +so that distribution is permitted only in or among +countries not thus excluded. In such case, this +License incorporates the limitation as if written in +the body of this License. + +5. Limitations. + +THE PROGRAM IS PROVIDED TO YOU "AS IS," WITHOUT +WARRANTY. THERE IS NO WARRANTY FOR THE PROGRAM, +EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR +AGREED TO IN WRITING WILL LICENSOR, OR ANY OTHER +PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT +LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH +ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +6. General. + +This License is governed by the laws of the +Commonwealth of Massachusetts, U.S.A., excluding +choice of law rules. + +If any part of this License is found to be in +conflict with the law, that part shall be +interpreted in its broadest meaning consistent with +the law, and no other parts of the License shall be +affected. + +For United States Government users, the Program is +provided with RESTRICTED RIGHTS. If you are a unit +or agency of the United States Government or are +acquiring the Program for any such unit or agency, +the following apply: + +If the unit or agency is the Department of Defense +("DOD"), the Program and its documentation are +classified as "commercial computer software" and +"commercial computer software documentation" +respectively and, pursuant to DFAR Section 227.7202, +the Government is acquiring the Program and its +documentation in accordance with the terms of this +License. If the unit or agency is other than DOD, +the Program and its documentation are classified as +"commercial computer software" and "commercial +computer software documentation" respectively and, +pursuant to FAR Section 12.212, the Government is +acquiring the Program and its documentation in +accordance with the terms of this License. + +------------------------------------------------------ + +Triangle +A Two-Dimensional Quality Mesh Generator +and Delaunay Triangulator. +Version 1.3 + +Copyright 1996 Jonathan Richard Shewchuk +School of Computer Science +Carnegie Mellon University +5000 Forbes Avenue +Pittsburgh, Pennsylvania 15213-3891 +Please send bugs and comments to jrs@cs.cmu.edu + +Created as part of the Archimedes project (tools for +parallel FEM). Supported in part by NSF Grant +CMS-9318163 and an NSERC 1967 Scholarship. There is +no warranty whatsoever. Use at your own risk. + +Triangle generates exact Delaunay triangulations, +constrained Delaunay triangulations, and quality +conforming Delaunay triangulations. The latter can +be generated with no small angles, and are thus +suitable for finite element analysis. + +Information on the algorithms used by Triangle, +including complete references, can be found in the +comments at the beginning of the triangle.c source +file. Another listing of these references, with +PostScript copies of some of the papers, is available +from the Web page + +http://www.cs.cmu.edu/~quake/triangle.research.html + +[Triangle] may be freely redistributed under the +condition that the copyright notices (including the +copy of this notice in the code comments and the +copyright notice printed when the `-h' switch is +selected) are not removed, and no compensation is +received. Private, research, and institutional use +is free. You may distribute modified versions of +this code UNDER THE CONDITION THAT THIS CODE AND ANY +MODIFICATIONS MADE TO IT IN THE SAME FILE REMAIN +UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE +AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT +CHARGE, AND CLEAR NOTICE IS GIVEN OF THE +MODIFICATIONS. Distribution of this code as part of +a commercial system is permissible ONLY BY DIRECT +ARRANGEMENT WITH THE AUTHOR. (If you are not +directly supplying this code to a customer, and you +are instead telling them how they can obtain it for +free, then you are not required to make any +arrangement with [JRS].) + +If you use Triangle, and especially if you use it to +accomplish real work, I would like very much to hear +from you. A short letter or email (to +jrs@cs.cmu.edu) describing how you use Triangle will +mean a lot to me. The more people I know are using +this program, the more easily I can justify spending +time on improvements and on the three-dimensional +successor to Triangle, which in turn will benefit +you. Also, I can put you on a list to receive email +whenever a new version of Triangle is available. + +If you use a mesh generated by Triangle, please +include an acknowledgment as well. + +Jonathan Richard Shewchuk +July 20, 1996 + +------------------------------------------------------ + +Lua Copyright Notice + +Copyright © 1994-2000 TeCGraf, PUC-Rio. All rights reserved. + +Permission is hereby granted, without written agreement +and without license or royalty fees, to use, copy, modify, +translate, and distribute this software and its documentation +(hereby called the "package") for any purpose, including +commercial applications, subject to the following conditions: + +* The above copyright notice and this permission notice shall + appear in all copies or substantial portions of this package. +* The origin of this package must not be misrepresented; + you must not claim that you wrote the original package. + If you use this package in a product, an acknowledgment + in the product documentation would be greatly appreciated + (but it is not required). +* Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original package. + +The authors specifically disclaim any warranties, including, +but not limited to, the implied warranties of merchantability +and fitness for a particular purpose. The package provided +hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, +enhancements, or modifications. In no event shall TeCGraf, +PUC-Rio, or the authors be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising +out of the use of this package and its documentation. + +The Lua language and this implementation have been entirely +designed and written by Waldemar Celes, Roberto Ierusalimschy +and Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio in Brazil. + +This implementation contains no third-party code. diff --git a/debug/matlib.dat b/debug/matlib.dat new file mode 100644 index 0000000..aba497a --- /dev/null +++ b/debug/matlib.dat @@ -0,0 +1,2602 @@ + + = "Air" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "PM Materials" + + = "Alnico Magnets" + + = "Alnico 5" + = 1.5 + = 1.5 + = 50963 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.12561 253.85213400000001 + 0.30829000000000001 707.44372199999998 + 0.48333999999999999 1452.2888559999999 + 0.61734 2162.915677 + 0.75499000000000005 3024.739693 + 0.84413000000000005 3845.9792000000002 + 0.92927999999999999 5110.4652230000002 + 0.98077000000000003 6495.9090020000003 + 1.02467 8023.0006810000004 + 1.0464 9234.1697980000008 + 1.0714999999999999 11043.761501000001 + 1.0929 12850.170104999999 + 1.1068 14650.212512 + 1.1242000000000001 16900.663407 + 1.1378999999999999 19147.135429000002 + 1.1516999999999999 21245.593353 + 1.1652 23790.480893 + 1.175 26182.579688000002 + 1.1915 30071.530722 + 1.2045999999999999 33361.263396000002 + 1.2177 36650.996070000001 + 1.2273000000000001 39490.320254999999 + 1.2397 43971.486832000002 + 1.2487999999999999 47704.784332000003 + 1.2544 50988.028258999999 + + + + = "Alnico 6" + = 3.2999999999999998 + = 3.2999999999999998 + = 59907 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.10402 1131.5899999999999 + 0.18934000000000001 2098.46 + 0.26712000000000002 3207.77 + 0.33743000000000001 4310.71 + 0.40393000000000001 5560.0799999999999 + 0.47026000000000001 7106.2700000000004 + 0.52539000000000002 8643.7000000000007 + 0.57662999999999998 10475.6 + 0.63507999999999998 12760.200000000001 + 0.69674999999999998 15942.6 + 0.74002000000000001 18661.700000000001 + 0.78312000000000004 21679.299999999999 + 0.81535999999999997 24090.5 + 0.84031 26198.5 + 0.87238000000000004 28908.099999999999 + 0.90412000000000003 32213.799999999999 + 0.92864999999999998 35065.800000000003 + 0.95318000000000003 37917.900000000001 + 0.97397999999999996 40767.5 + 0.99451999999999996 44062.800000000003 + 1.0149999999999999 47507.800000000003 + 1.0354000000000001 51102.300000000003 + 1.0487 53944.800000000003 + 1.0622 56489.599999999999 + 1.0751999999999999 59928.199999999997 + + + + = "Alnico 8" + = 6.6779999999999999 + = 6.6779999999999999 + = 109300 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.11536 8340 + 0.23438000000000001 18512 + 0.30429 24866 + 0.35666999999999999 29808 + 0.44341000000000003 39967 + 0.54315999999999998 54772 + 0.66569 77603 + 0.74668000000000001 95215 + 0.80359000000000003 109301 + + + + + = "NdFeB Magnets" + + = "NdFeB 32 MGOe" + = 1.0449999999999999 + = 1.0449999999999999 + = 883310 + = 0 + = 0 + = 0 + = 0.69399999999999995 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "NdFeB 37 MGOe" + = 1.048 + = 1.048 + = 950000 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "NdFeB 40 MGOe" + = 1.0489999999999999 + = 1.0489999999999999 + = 979000 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "NdFeB 10 MGOe (Bonded)" + = 1.2230000000000001 + = 1.2230000000000001 + = 445634 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "NdFeB 52 MGOe" + = 1.05 + = 1.05 + = 891300 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 6 + 0 0 + 0.42799999999999999 95490 + 0.53300000000000003 175100 + 0.63800000000000001 254600 + 0.84799999999999998 413800 + 1.478 891300 + + + + + = "Ceramic Magnets" + + = "Ceramic 5" + = 1.8859999999999999 + = 1.8859999999999999 + = 191262 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 25 + 0 0 + 0.10034800000000001 8233.8839250000001 + 0.14876 16191.633925 + 0.15992100000000001 24149.383924999998 + 0.17108200000000001 32107.133924999998 + 0.18224399999999999 40064.883925000002 + 0.19340499999999999 48022.633925000002 + 0.204566 55980.383925000002 + 0.215728 63938.133925000002 + 0.22688900000000001 71895.883925000002 + 0.23805000000000001 79853.633925000002 + 0.24921099999999999 87811.383925000002 + 0.26037300000000002 95769.133925000002 + 0.271534 103726.883925 + 0.28269499999999997 111684.633925 + 0.29385600000000001 119642.383925 + 0.30501800000000001 127600.133925 + 0.31617899999999999 135557.883925 + 0.32734000000000002 143515.633925 + 0.338501 151473.383925 + 0.349663 159431.133925 + 0.36082399999999998 167388.883925 + 0.37198500000000001 175346.633925 + 0.38314700000000002 183304.383925 + 0.39430799999999999 191262.133925 + + + + = "Ceramic 8" + = 1.4384600000000001 + = 1.4384600000000001 + = 233568 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.040029000000000002 1488.09925 + 0.069106000000000001 5665.9179999999997 + 0.087951000000000001 15231.1335 + 0.11024 30247.407749999998 + 0.15995000000000001 63009.464500000002 + 0.24912000000000001 128493.78925 + 0.32113999999999998 180339.326275 + 0.39145000000000002 233567.92025 + + + + + = "SmCo Magnets" + + = "SmCo 20 MGOe" + = 1.0345 + = 1.0345 + = 693000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo 24 MGOe" + = 1.1100000000000001 + = 1.1100000000000001 + = 724000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo 27 MGOe" + = 1.103 + = 1.103 + = 772000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + + = "Soft Magnetic Materials" + + = "US Steel Type 2-S 0.018 inch thickness" + = 9400 + = 9400 + = 0 + = 0 + = 0 + = 0 + = 6.25 + = 0.4572 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 57 + 0 0 + 0.0044450000000000002 9.5103069999999992 + 0.0058190000000000004 11.21247 + 0.0071929999999999997 13.219414 + 0.0085679999999999992 15.585253 + 0.012898 18.371262000000002 + 0.017228 21.656220999999999 + 0.027470000000000001 25.5213 + 0.046579000000000002 30.061992 + 0.092288999999999996 35.364241 + 0.22076000000000001 41.430433999999998 + 0.4113 48.386302999999998 + 0.60185 56.510370000000002 + 0.77170000000000005 66.066035999999997 + 0.91495000000000004 77.340575999999999 + 1.0464 90.591025999999999 + 1.1600999999999999 106.21208900000001 + 1.2619 124.594492 + 1.3431 146.31119100000001 + 1.3947000000000001 172.06246999999999 + 1.4286000000000001 202.52473699999999 + 1.4507000000000001 238.525598 + 1.4668000000000001 281.01202599999999 + 1.4830000000000001 331.05831499999999 + 1.4932000000000001 390.144609 + 1.5064 459.69534399999998 + 1.5166999999999999 541.73178900000005 + 1.5268999999999999 638.41049399999997 + 1.5371999999999999 752.33364300000005 + 1.5474000000000001 886.57292700000005 + 1.5576000000000001 1044.772997 + 1.5679000000000001 1231.22308 + 1.5840000000000001 1450.5386699999999 + 1.5972 1709.1655450000001 + 1.6104000000000001 2013.867792 + 1.6266 2372.5235849999999 + 1.6427 2795.1596880000002 + 1.6589 3292.9965269999998 + 1.6779999999999999 3878.9256599999999 + 1.6971000000000001 4569.1013169999997 + 1.7161999999999999 5382.0650580000001 + 1.7353000000000001 6339.7006929999998 + 1.7604 7465.5631620000004 + 1.7854000000000001 8791.7222000000002 + 1.8104 10352.236975 + 1.8384 12188.885675 + 1.8723000000000001 14347.823249999999 + 1.9060999999999999 16887.93705 + 1.9459 19872.0933 + 1.9886999999999999 23380.665274999999 + 2.0344000000000002 27504.371325 + 2.0741999999999998 32364.965025000001 + 2.1080999999999999 38095.340799999998 + 2.1389999999999998 44847.491674999997 + 2.1610999999999998 52819.565625000003 + 2.1772 62227.217675 + 2.1903999999999999 73321.116949999996 + + + + = "Carpenter Electrical Iron" + = 2065 + = 2065 + = 0 + = 0 + = 0 + = 0 + = 7.6900000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 22 + 0 0 + 0.40103 157.72260499999999 + 0.45408999999999999 174.18718999999999 + 0.51795000000000002 197.93311600000001 + 0.58221000000000001 221.742704 + 0.64024999999999999 246.66637700000001 + 0.70408000000000004 276.356742 + 0.77425999999999995 311.83239200000003 + 0.83909 344.435293 + 0.93633 399.86102199999999 + 1.0371999999999999 467.533728 + 1.1574 554.48806200000001 + 1.2452000000000001 634.68626700000004 + 1.3299000000000001 716.22137299999997 + 1.4202999999999999 813.99824699999999 + 1.5168999999999999 965.51380700000004 + 1.6082000000000001 1137.1624750000001 + 1.6927000000000001 1358.5470800000001 + 1.7557 1670.0134149999999 + 1.7946 2401.1714849999998 + 1.8078000000000001 4038.1602370000001 + 1.8478000000000001 6600.1578499999996 + + + + = "US Steel Type 2-S 0.024 inch thickness" + = 7400 + = 7400 + = 0 + = 0 + = 0 + = 0 + = 6.25 + = 0.60960000000000003 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 66 + 0 0 + 0.0046779999999999999 9.1307220000000004 + 0.0064009999999999996 10.474786 + 0.008123 12.016997999999999 + 0.0098449999999999996 13.786006 + 0.014524 15.816824 + 0.019202 18.147649000000001 + 0.023879999999999998 20.822248999999999 + 0.031514 23.893940000000001 + 0.048016000000000003 27.429568 + 0.067473000000000005 31.492000000000001 + 0.10170999999999999 36.179115000000003 + 0.15959000000000001 41.607095999999999 + 0.26477000000000001 47.948627000000002 + 0.39655000000000001 55.320686000000002 + 0.53718999999999995 63.850599000000003 + 0.67193000000000003 73.677623999999994 + 0.79779999999999995 84.980812 + 0.90297000000000005 97.936029000000005 + 1.0052000000000001 112.84885300000001 + 1.0955999999999999 129.96597299999999 + 1.1800999999999999 149.637531 + 1.2557 172.22162599999999 + 1.3165 198.08431300000001 + 1.3654999999999999 227.718974 + 1.3997999999999999 261.61103100000003 + 1.4252 300.436893 + 1.4446000000000001 344.928674 + 1.4611000000000001 395.961724 + 1.4717 454.42731400000002 + 1.4852000000000001 521.59868100000006 + 1.4987999999999999 598.69336299999998 + 1.5094000000000001 687.10396600000001 + 1.52 788.557321 + 1.5276000000000001 904.87575200000003 + 1.5382 1038.486375 + 1.5488 1191.832218 + 1.5593999999999999 1367.8576479999999 + 1.5729 1569.9844969999999 + 1.5834999999999999 1801.7937549999999 + 1.5941000000000001 2067.9009150000002 + 1.6047 2373.239783 + 1.6182000000000001 2724.0174019999999 + 1.6288 3126.281665 + 1.6424000000000001 3588.30863 + 1.6589 4119.2497100000001 + 1.6754 4728.7337829999997 + 1.7083999999999999 6231.5548699999999 + 1.7307999999999999 7155.3700669999998 + 1.7532000000000001 8216.3768749999999 + 1.7756000000000001 9433.9126250000008 + 1.8009999999999999 10834.476624999999 + 1.8292999999999999 12443.533675000001 + 1.8575999999999999 14292.119000000001 + 1.8889 16417.634024999999 + 1.9232 18861.459050000001 + 1.9574 21668.953249999999 + 1.9916 24894.229325 + 2.0287999999999999 28603.336599999999 + 2.0659999999999998 32864.711725000001 + 2.0973000000000002 37751.565999999999 + 2.1255999999999999 43359.392424999998 + 2.1480000000000001 49787.662875000002 + 2.1675 57161.314025 + 2.181 65610.852975000002 + 2.1945999999999999 75308.167125000007 + + + + = "Low Carbon Steel" + + = "1006 Steel" + = 1404 + = 1404 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 14 + 0 0 + 0.040000000000000001 23.873249999999999 + 0.080000000000000002 39.78875 + 0.28000000000000003 79.577500000000001 + 0.59999999999999998 119.36620000000001 + 0.88 175.07050000000001 + 1.2 286.47899999999998 + 1.52 795.77499999999998 + 1.6799999999999999 3183.0999999999999 + 1.8 7957.75 + 1.9199999999999999 15915.5 + 2.0800000000000001 31831 + 2.1640009999999998 56177.410000000003 + 2.2000000000000002 79577.5 + + + + = "1010 Steel" + = 902.60000000000002 + = 902.60000000000002 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 16 + 0 0 + 0.22520000000000001 159.155 + 0.50026000000000004 206.9015 + 0.85040000000000004 318.31 + 1.1006 477.46499999999997 + 1.2358 636.62 + 1.3109999999999999 795.77499999999998 + 1.492 1591.55 + 1.609 3183.0999999999999 + 1.681 4774.6499999999996 + 1.77 7957.75 + 1.9099999999999999 15915.5 + 2.0249999999999999 31831 + 2.0800000000000001 47746.5 + 2.1600000000000001 79577.5 + 2.2749999999999999 159155 + + + + = "1018 Steel" + = 529 + = 529 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 13 + 0 0 + 0.25030000000000002 238.73249999999999 + 0.92500000000000004 795.77499999999998 + 1.25 1591.55 + 1.3899999999999999 2387.3249999999998 + 1.5249999999999999 3978.875 + 1.71 7957.75 + 1.8700000000000001 15915.5 + 1.9550000000000001 23873.25 + 2.02 39788.75 + 2.1099999999999999 79577.5 + 2.2250000000000001 159155 + 2.4300000000000002 318310 + + + + = "1020 Steel" + = 760 + = 760 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.20000000000000001 159.155 + 0.52000000000000002 238.73249999999999 + 1 557.04250000000002 + 1.4199999999999999 1591.55 + 1.6000000000000001 3183.0999999999999 + 1.803582 7077.8066740000004 + 2.1378029999999999 29076.393005999998 + 2.2799999999999998 79577.5 + + + + = "1117 Steel" + = 1777 + = 1777 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.70040000000000002 238.73249999999999 + 1.351 795.77499999999998 + 1.6240000000000001 3183.0999999999999 + 1.77 7957.75 + 2 31831 + 2.1299999999999999 79577.5 + 2.25 159155 + 2.46 318310 + + + + + = "Magnetic Stainless Steel" + + = "416 Stainless Steel" + = 440 + = 440 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.20039999999999999 318.31 + 0.42559999999999998 477.46499999999997 + 0.76100000000000001 795.77499999999998 + 1.097 1591.55 + 1.2330000000000001 2387.3249999999998 + 1.335 3978.875 + 1.46 7957.75 + 1.5900000000000001 15915.5 + 1.6899999999999999 31831 + 1.724232 44456.279999999999 + 1.74 55704.25 + + + + = "430 Stainless Steel" + = 409 + = 409 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.20039999999999999 318.31 + 0.6008 636.62 + 1.1020000000000001 1591.55 + 1.3859999999999999 4774.6499999999996 + 1.4650000000000001 7957.75 + 1.667548 32902.232515999996 + 1.789509 92585.397305000006 + 1.878209 160685.354903 + 2.0800000000000001 318310 + + + + = "455 Stainless Steel" + = 470 + = 470 + = 0 + = 0 + = 0 + = 0 + = 1.6699999999999999 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.067337999999999995 342.70800000000003 + 0.10261000000000001 514.03099999999995 + 0.18909000000000001 713.09400000000005 + 0.29154000000000002 854.58199999999999 + 0.40999999999999998 995.75300000000004 + 0.55725000000000002 1107.72 + 0.73009999999999997 1247.9300000000001 + 0.86777000000000004 1417.4300000000001 + 0.97345000000000004 1616.1400000000001 + 1.0632999999999999 2273.6900000000001 + 1.1339999999999999 2931.6300000000001 + 1.224 4076.3600000000001 + 1.2724 4906.5900000000001 + 1.3500000000000001 6968.6800000000003 + 1.3761000000000001 8085.8699999999999 + 1.3991 9661.5 + 1.419 11438.5 + 1.4359999999999999 13874.299999999999 + 1.4462999999999999 15736.4 + 1.4533 17169.599999999999 + 1.464 19777.400000000001 + 1.478 22986.700000000001 + 1.4887999999999999 25795 + 1.4959 27715.200000000001 + 1.4995000000000001 28604.099999999999 + + + + + = "Silicon Iron" + + = "Carpenter Silicon Core Iron "A", 1066C Anneal" + = 7000 + = 7000 + = 0 + = 0 + = 0 + = 0 + = 4 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 35 + 0 0 + 0.076137999999999997 27.383403999999999 + 0.14288999999999999 31.395700000000001 + 0.21798000000000001 36.490250000000003 + 0.30552000000000001 42.403651000000004 + 0.39304 48.938552999999999 + 0.48466999999999999 55.704230000000003 + 0.58045000000000002 63.402555 + 0.68454999999999999 72.654231999999993 + 0.77612999999999999 81.009866000000002 + 0.85528000000000004 90.965007999999997 + 0.91776999999999997 100.076628 + 0.97614000000000001 110.875291 + 1.0510999999999999 124.506912 + 1.1262000000000001 144.71163200000001 + 1.1930000000000001 168.210859 + 1.2515000000000001 195.55367899999999 + 1.3058000000000001 225.79311799999999 + 1.3476999999999999 260.75150100000002 + 1.3937999999999999 309.50861800000001 + 1.4316 367.41714400000001 + 1.4694 436.172079 + 1.4990000000000001 525.02828399999999 + 1.5244 636.38899800000002 + 1.5414000000000001 745.35442899999998 + 1.5626 897.31556899999998 + 1.5839000000000001 1095.1451629999999 + 1.6094999999999999 1402.632513 + 1.6267 1771.9515590000001 + 1.6479999999999999 2223.0762450000002 + 1.6652 2713.5122019999999 + 1.6822999999999999 3335.0122550000001 + 1.7036 4042.6151319999999 + 1.7205999999999999 4767.5658979999998 + 1.7377 5779.3934479999998 + + + + = "M-15 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-19 Steel" + = 4416 + = 4416 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-22 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-27 Steel" + = 12138 + = 12138 + = 0 + = 0 + = 0 + = 0 + = 2 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 17.059828 + 0.10000000000000001 25.634971 + 0.14999999999999999 31.338353999999999 + 0.20000000000000001 35.778996999999997 + 0.25 39.602124000000003 + 0.29999999999999999 43.123142999999999 + 0.34999999999999998 46.520439000000003 + 0.40000000000000002 49.908177000000002 + 0.45000000000000001 53.368284000000003 + 0.5 56.966318000000001 + 0.55000000000000004 60.760271000000003 + 0.59999999999999998 64.806105000000002 + 0.65000000000000002 69.161803000000006 + 0.69999999999999996 73.890922000000003 + 0.75 79.066315000000003 + 0.80000000000000004 84.774675999999999 + 0.84999999999999998 91.122721999999996 + 0.90000000000000002 98.246298999999993 + 0.94999999999999996 106.324591 + 1 115.60341699999999 + 1.05 126.435124 + 1.1000000000000001 139.34975900000001 + 1.1499999999999999 155.187082 + 1.2 175.350538 + 1.25 202.312017 + 1.3 240.640455 + 1.3500000000000001 299.11802699999998 + 1.3999999999999999 394.99338599999999 + 1.45 561.72617700000001 + 1.5 859.32876299999998 + 1.55 1375.4668879999999 + 1.6000000000000001 2191.2469139999998 + 1.6499999999999999 3328.145908 + 1.7 4760.5061720000003 + 1.75 6535.3394490000001 + 1.8 8788.9706569999998 + 1.8500000000000001 11670.804346999999 + 1.8999999999999999 15385.186211 + 1.95 20246.553030999999 + 2 26995.131141000002 + 2.0499999999999998 38724.496369 + 2.1000000000000001 64917.284463000004 + 2.1499999999999999 101489.30933800001 + 2.2000000000000002 137202.82896099999 + 2.25 176835.706764 + 2.2999999999999998 216374.28360900001 + + + + = "M-36 Steel" + = 1616 + = 1616 + = 0 + = 0 + = 0 + = 0 + = 2 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 19.398586000000002 + 0.10000000000000001 29.611086 + 0.14999999999999999 36.311286000000003 + 0.20000000000000001 41.398969999999998 + 0.25 45.654680999999997 + 0.29999999999999999 49.463585000000002 + 0.34999999999999998 53.042856999999998 + 0.40000000000000002 56.529325 + 0.45000000000000001 60.018492000000002 + 0.5 63.584023999999999 + 0.55000000000000004 67.288555000000002 + 0.59999999999999998 71.190393999999998 + 0.65000000000000002 75.348315999999997 + 0.69999999999999996 79.825601000000006 + 0.75 84.694101000000003 + 0.80000000000000004 90.039004000000006 + 0.84999999999999998 95.965085000000002 + 0.90000000000000002 102.60559499999999 + 0.94999999999999996 110.135639 + 1 118.793308 + 1.05 128.91455500000001 + 1.1000000000000001 140.99328499999999 + 1.1499999999999999 155.78958700000001 + 1.2 174.53384 + 1.25 199.32994600000001 + 1.3 233.989035 + 1.3500000000000001 285.82186100000001 + 1.3999999999999999 369.57162599999998 + 1.45 515.788276 + 1.5 785.78510400000005 + 1.55 1282.7937979999999 + 1.6000000000000001 2108.172454 + 1.6499999999999999 3257.880122 + 1.7 4726.4426309999999 + 1.75 6512.0094010000003 + 1.8 8720.2655529999993 + 1.8500000000000001 11459.429228999999 + 1.8999999999999999 14887.904936999999 + 1.95 19350.577347999999 + 2 26042.602019000002 + 2.0499999999999998 39200.400310999998 + 2.1000000000000001 65518.130312000001 + 2.1499999999999999 100476.654669 + 2.2000000000000002 136976.920182 + 2.25 176029.81784199999 + 2.2999999999999998 215228.81031199999 + + + + = "M-43 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.6000000000000001 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 22.815826000000001 + 0.10000000000000001 34.292324000000001 + 0.14999999999999999 41.691794999999999 + 0.20000000000000001 47.276539 + 0.25 51.943272999999998 + 0.29999999999999999 56.124130000000001 + 0.34999999999999998 60.058388999999998 + 0.40000000000000002 63.894412000000003 + 0.45000000000000001 67.734109000000004 + 0.5 71.654736999999997 + 0.55000000000000004 75.720754999999997 + 0.59999999999999998 79.991001999999995 + 0.65000000000000002 84.523664999999994 + 0.69999999999999996 89.380326999999994 + 0.75 94.629947999999999 + 0.80000000000000004 100.353469 + 0.84999999999999998 106.649919 + 0.90000000000000002 113.64520899999999 + 0.94999999999999996 121.50566499999999 + 1 130.459825 + 1.05 140.83502200000001 + 1.1000000000000001 153.12108799999999 + 1.1499999999999999 168.08528999999999 + 1.2 186.98695799999999 + 1.25 211.991513 + 1.3 246.99227999999999 + 1.3500000000000001 299.27421299999997 + 1.3999999999999999 382.88283799999999 + 1.45 525.15514299999995 + 1.5 777.59279800000002 + 1.55 1226.4570960000001 + 1.6000000000000001 1979.929758 + 1.6499999999999999 3105.52556 + 1.7 4589.1826570000003 + 1.75 6410.9674969999996 + 1.8 8681.3394960000005 + 1.8500000000000001 11524.478784000001 + 1.8999999999999999 15121.416504000001 + 1.95 19833.366747 + 2 26795.523691999999 + 2.0499999999999998 40064.363461000001 + 2.1000000000000001 66950.843427999993 + 2.1499999999999999 103339.791774 + 2.2000000000000002 141054.369267 + 2.25 181684.21904299999 + 2.2999999999999998 223103.57263000001 + + + + = "M-45 Steel" + = 4689 + = 4689 + = 0 + = 0 + = 0 + = 0 + = 2.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 19.965330000000002 + 0.10000000000000001 29.906288 + 0.14999999999999999 36.398771000000004 + 0.20000000000000001 41.371668999999997 + 0.25 45.590262000000003 + 0.29999999999999999 49.424858999999998 + 0.34999999999999998 53.082279999999997 + 0.40000000000000002 56.692664000000001 + 0.45000000000000001 60.347374000000002 + 0.5 64.117637000000002 + 0.55000000000000004 68.064755000000005 + 0.59999999999999998 72.246370999999996 + 0.65000000000000002 76.720885999999993 + 0.69999999999999996 81.551123000000004 + 0.75 86.807958999999997 + 0.80000000000000004 92.574503000000007 + 0.84999999999999998 98.951520000000002 + 0.90000000000000002 106.06504700000001 + 0.94999999999999996 114.077777 + 1 123.20691100000001 + 1.05 133.75338500000001 + 1.1000000000000001 146.15173799999999 + 1.1499999999999999 161.05866800000001 + 1.2 179.51663400000001 + 1.25 203.267945 + 1.3 235.37974800000001 + 1.3500000000000001 281.52494799999999 + 1.3999999999999999 352.64841200000001 + 1.45 470.42617899999999 + 1.5 677.45154100000002 + 1.55 1051.0680359999999 + 1.6000000000000001 1703.275165 + 1.6499999999999999 2726.5179589999998 + 1.7 4137.9810520000001 + 1.75 5832.6197039999997 + 1.8 7939.5529399999996 + 1.8500000000000001 10565.294335000001 + 1.8999999999999999 13843.912965 + 1.95 17970.359698 + 2 23423.776431999999 + 2.0499999999999998 32234.325959999998 + 2.1000000000000001 51366.778966999998 + 2.1499999999999999 84577.843500999996 + 2.2000000000000002 121162.49332199999 + 2.25 160127.812767 + 2.2999999999999998 202470.28224500001 + + + + = "M-47 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 4.2999999999999998 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 0 + + + + + = "Cobalt Iron" + + = "Hiperco-50" + = 3520 + = 3520 + = 0 + = 0 + = 0 + = 0 + = 2.5 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 22 + 0 0 + 0.29072999999999999 81.170000000000002 + 0.42870999999999998 106.8 + 0.58955999999999997 136.84 + 0.79627000000000003 179.91 + 1.0201 233.41 + 1.1980999999999999 283.70999999999998 + 1.3989 344.75 + 1.5596000000000001 402.92000000000002 + 1.7835000000000001 536.63999999999999 + 1.8985000000000001 670.10000000000002 + 1.9906999999999999 893.79999999999995 + 2.0543999999999998 1290.4000000000001 + 2.1183999999999998 2209.8000000000002 + 2.1476999999999999 3233.6999999999998 + 2.177 4549 + 2.2065000000000001 7297.8000000000002 + 2.2416999999999998 11554 + 2.2711999999999999 18294 + 2.2890000000000001 25071 + 2.3126000000000002 36690 + 2.3410000000000002 62037 + + + + = "Vanadium Permedur" + = 6856 + = 6856 + = 0 + = 0 + = 0 + = 0 + = 2.5 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.59999999999999998 71.400000000000006 + 1 119 + 1.6000000000000001 175 + 1.8 268 + 2 493 + 2.1000000000000001 804 + 2.2000000000000002 1910 + 2.2599999999999998 4775 + 2.2999999999999998 15120 + 2.3399999999999999 42971 + 2.3900000000000001 79577 + + + + + = "Nickel Alloys" + + = "Supermalloy" + = 529095 + = 529095 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.45000099999999998 0.79577500000000001 + 0.57500200000000001 1.59155 + 0.62500299999999998 2.3873250000000001 + 0.65000400000000003 3.1831 + 0.680006 4.7746490000000001 + 0.70000799999999996 6.3662000000000001 + 0.72567300000000001 10.138479999999999 + 0.744506 15.68595 + 0.76002999999999998 23.873249999999999 + 0.78046000000000004 48 + 0.78510000000000002 79.577500000000001 + + + + = "Mu Metal" + = 82910 + = 82910 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 31 + 0 0 + 0.080001000000000003 0.79577500000000001 + 0.099140000000000006 1.0342340000000001 + 0.12679699999999999 1.344149 + 0.16478400000000001 1.7469330000000001 + 0.21423800000000001 2.270413 + 0.27441399999999999 2.9507569999999999 + 0.34069300000000002 3.8349700000000002 + 0.39480599999999999 4.9841449999999998 + 0.43570300000000001 6.4776769999999999 + 0.46653800000000001 8.4187550000000009 + 0.49254100000000001 10.941490999999999 + 0.51263599999999998 14.220181 + 0.53089299999999995 18.481352000000001 + 0.54834099999999997 24.019411000000002 + 0.56394500000000003 31.216987 + 0.57866499999999998 40.571362999999998 + 0.59203600000000001 52.728839999999998 + 0.60396099999999997 68.529386000000002 + 0.61424699999999999 89.064670000000007 + 0.62285900000000005 115.75348700000001 + 0.63014599999999998 150.439784 + 0.63628200000000001 195.52006 + 0.64158999999999999 254.10893899999999 + 0.64653300000000002 330.25436300000001 + 0.65073700000000001 429.217266 + 0.65423600000000004 557.835058 + 0.65707000000000004 724.99402199999997 + 0.65927800000000003 942.24327400000004 + 0.66090599999999999 1224.592701 + 0.66200000000000003 1591.55 + + + + + + = "Solid Non-Magnetic Conductors" + + = "Titanium" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.798 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "316 Stainless Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.3340000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "304 Stainless Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.45 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Copper" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Aluminum, 6061-T6" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 24.59 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Aluminum, 1100" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 34.450000000000003 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + = "Copper AWG Magnet Wire" + + = "10 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.58819648049692 + = 0 + + + + = "12 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.05253434114407 + = 0 + + + + = "14 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.6277346999432001 + = 0 + + + + = "16 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.2908530689539499 + = 0 + + + + = "18 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.02369363120782 + = 0 + + + + = "20 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.81182643925900699 + = 0 + + + + = "22 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.64380801773901497 + = 0 + + + + = "24 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.51056327271548796 + = 0 + + + + = "26 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.404895323238459 + = 0 + + + + = "28 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.32109677985343799 + = 0 + + + + = "30 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.254641474264512 + = 0 + + + + = "32 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.20193998969781299 + = 0 + + + + = "34 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.160145787550665 + = 0 + + + + = "36 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.12700145874326901 + = 0 + + + + + = "Copper SWG Magnet Wire" + + = "10 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 3.2511999999999999 + = 0 + + + + = "12 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.6415999999999999 + = 0 + + + + = "14 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.032 + = 0 + + + + = "16 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.6255999999999999 + = 0 + + + + = "18 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.2192000000000001 + = 0 + + + + = "20 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.91439999999999999 + = 0 + + + + = "22 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.71120000000000005 + = 0 + + + + = "24 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.55879999999999996 + = 0 + + + + = "26 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.4572 + = 0 + + + + = "28 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.37591999999999998 + = 0 + + + + = "30 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.31496000000000002 + = 0 + + + + = "32 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.27432000000000001 + = 0 + + + + = "34 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.23368 + = 0 + + + + = "36 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.19303999999999999 + = 0 + + + + = "38 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.15240000000000001 + = 0 + + + + = "40 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.12192 + = 0 + + + + + = "Copper Metric Magnet Wire" + + = "2.5mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.5 + = 0 + + + + = "2mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2 + = 0 + + + + = "1.6mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.6000000000000001 + = 0 + + + + = "1.25mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 1 + = 1.25 + = 0 + + + + = "1mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1 + = 0 + + + + = "0.8mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.80000000000000004 + = 0 + + + + = "0.63mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.63 + = 0 + + + + = "0.5mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.5 + = 0 + + + + = "0.4mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.40000000000000002 + = 0 + + + + = "0.315mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.315 + = 0 + + + + = "0.25mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.25 + = 0 + + + + = "0.2mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.20000000000000001 + = 0 + + + + = "0.16mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.16 + = 0 + + + + = "0.125mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.125 + = 0 + + + diff --git a/debug/statlib.dat b/debug/statlib.dat new file mode 100644 index 0000000..87b2f8d --- /dev/null +++ b/debug/statlib.dat @@ -0,0 +1,182 @@ + + = "Air" + = 1 + = 1 + = 0 + + + + = "Delrin" + = 3.7000000000000002 + = 3.7000000000000002 + = 0 + + + + = "Ethanol" + = 25 + = 25 + = 0 + + + + = "Germanium" + = 16 + = 16 + = 0 + + + + = "Kapton 100" + = 3.8999999999999999 + = 3.8999999999999999 + = 0 + + + + = "Kapton 150" + = 2.8999999999999999 + = 2.8999999999999999 + = 0 + + + + = "Lexan" + = 2.96 + = 2.96 + = 0 + + + + = "Marble" + = 8 + = 8 + = 0 + + + + = "Mica" + = 6 + = 6 + = 0 + + + + = "Mylar" + = 3.2000000000000002 + = 3.2000000000000002 + = 0 + + + + = "Nylon" + = 3.7999999999999998 + = 3.7999999999999998 + = 0 + + + + = "Paper" + = 3 + = 3 + = 0 + + + + = "Polyamide" + = 2.5 + = 2.5 + = 0 + + + + = "Polyethylene LDPE/HDPE" + = 2.2999999999999998 + = 2.2999999999999998 + = 0 + + + + = "Polypropylene" + = 2.2000000000000002 + = 2.2000000000000002 + = 0 + + + + = "Polystyrene" + = 2.5 + = 2.5 + = 0 + + + + = "Porcelain" + = 5.9000000000000004 + = 5.9000000000000004 + = 0 + + + + = "PVC" + = 3 + = 3 + = 0 + + + + = "Pyrex" + = 4.7000000000000002 + = 4.7000000000000002 + = 0 + + + + = "Rubber" + = 3 + = 3 + = 0 + + + + = "Silicon" + = 12 + = 12 + = 0 + + + + = "Teflon" + = 2.1000000000000001 + = 2.1000000000000001 + = 0 + + + + = "Transformer Oil" + = 4.5 + = 4.5 + = 0 + + + + = "Vinyl" + = 3 + = 3 + = 0 + + + + = "Water@20C" + = 80.400000000000006 + = 80.400000000000006 + = 0 + + + + = "Water@50C" + = 78.5 + = 78.5 + = 0 + + diff --git a/femm/ActiveFEMM.cpp b/femm/ActiveFEMM.cpp new file mode 100644 index 0000000..e3f99d5 --- /dev/null +++ b/femm/ActiveFEMM.cpp @@ -0,0 +1,222 @@ +// ActiveFEMM.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "lua.h" +#include "luadebug.h" +#include "luaconsoledlg.h" +#include "ActiveFEMM.h" +#include "mainfrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +extern lua_State *lua; +extern BOOL bLinehook; +extern BOOL lua_byebye; +extern HANDLE hProc; +extern int m_luaWindowStatus; +extern CFemmApp theApp; + +CString LuaResult; + +///////////////////////////////////////////////////////////////////////////// +// ActiveFEMM + +IMPLEMENT_DYNCREATE(ActiveFEMM, CCmdTarget) + +ActiveFEMM::ActiveFEMM() +{ + EnableAutomation(); + EnableTypeLib(); + + // To keep the application running as long as an OLE automation + // object is active, the constructor calls AfxOleLockApp. + + AfxOleLockApp(); + + lua_register(lua,"actxprint", lua_to_string); + lua_register(lua,"lua2matlab",lua_to_matlab); +} + +ActiveFEMM::~ActiveFEMM() +{ + // To terminate the application when all objects created with + // with OLE automation, the destructor calls AfxOleUnlockApp. + + AfxOleUnlockApp(); +} + + +void ActiveFEMM::OnFinalRelease() +{ + // When the last reference for an automation object is released + // OnFinalRelease is called. The base class will automatically + // deletes the object. Add additional cleanup required for your + // object before calling the base class. + + // We have to close things in a funny way so that FEMM shuts down + // the way that it expects to. First, the call to AfxOleSetUserCtrl + // makes it so that the the application won't get closed when the + // base class version of OnFinalRelease gets called. + AfxOleSetUserCtrl(TRUE); + + // Then, post a message to the main window requesting a shutdown. + // This is the way that FEMM likes to shut down. Since the message + // has been posted rather than sent, it will be acted upon after + // ActiveFEMM has shut itself down. + AfxGetMainWnd()->PostMessage(WM_CLOSE); + + // Then, call the base class to shut down ActiveFEMM + CCmdTarget::OnFinalRelease(); +} + + +BEGIN_MESSAGE_MAP(ActiveFEMM, CCmdTarget) + //{{AFX_MSG_MAP(ActiveFEMM) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +BEGIN_DISPATCH_MAP(ActiveFEMM, CCmdTarget) + //{{AFX_DISPATCH_MAP(ActiveFEMM) + DISP_FUNCTION(ActiveFEMM, "call2femm", call2femm, VT_BSTR, VTS_BSTR) + DISP_FUNCTION(ActiveFEMM, "mlab2femm", mlab2femm, VT_BSTR, VTS_BSTR) + //}}AFX_DISPATCH_MAP +END_DISPATCH_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Type library ID and version +// {04EF434A-1A91-495A-85AA-C625602B4AF4} +static const GUID _tlid = +{ 0x04EF434A, 0x1A91, 0x495A, { 0x85, 0xAA, 0xC6, 0x25, 0x60, 0x2B, 0x4A, 0xF4 } }; +const WORD _wVerMajor = 1; +const WORD _wVerMinor = 0; +IMPLEMENT_OLETYPELIB(ActiveFEMM, _tlid, _wVerMajor, _wVerMinor) + + + + +// Note: we add support for IID_IActiveFEMM to support typesafe binding +// from VBA. This IID must match the GUID that is attached to the +// dispinterface in the .ODL file. + +// {E08185B4-FEDF-4B1B-A88D-D40C97625060} +static const IID IID_IActiveFEMM = +{ 0xe08185b4, 0xfedf, 0x4b1b, { 0xa8, 0x8d, 0xd4, 0xc, 0x97, 0x62, 0x50, 0x60 } }; + +BEGIN_INTERFACE_MAP(ActiveFEMM, CCmdTarget) + INTERFACE_PART(ActiveFEMM, IID_IActiveFEMM, Dispatch) +END_INTERFACE_MAP() + +// {0A35D5BD-DCA9-4C39-9512-1D89A1A37047} +IMPLEMENT_OLECREATE2(ActiveFEMM, "femm.ActiveFEMM", 0xa35d5bd, 0xdca9, 0x4c39, 0x95, 0x12, 0x1d, 0x89, 0xa1, 0xa3, 0x70, 0x47) + +BOOL ActiveFEMM::GetDispatchIID(IID* pIID) +{ + *pIID = IID_IActiveFEMM; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// ActiveFEMM message handlers + +BSTR ActiveFEMM::call2femm(LPCTSTR luacmd) +{ + // executes the line contained in luacmd + // and returns a string containing the results + // of the command with the results separated + // by newline characters. + CString strToLua; + + theApp.MatlabLoveNote.Empty(); + strToLua=luacmd; + strToLua="actxprint(" + strToLua +")"; + DoLuaCmd(strToLua); + + // Returns the result of errors that are trapped + // via message boxes during a normal UI session + if(theApp.MatlabLoveNote.GetLength()>0) + { + LuaResult.Format("error: %s",theApp.MatlabLoveNote); + } + return LuaResult.AllocSysString(); +} + +BSTR ActiveFEMM::mlab2femm(LPCTSTR luacmd) +{ + // executes the line contained in luacmd + // and returns a string containing the results + // of the command formatted in matlab format. + // One would expect that all the results are + // real numbers, in which case we can eval() + // the result in matlab to get a vector of numbers. + CString strToLua; + + theApp.MatlabLoveNote.Empty(); + strToLua=luacmd; + strToLua="lua2matlab(" + strToLua +")"; + DoLuaCmd(strToLua); + + // Returns the result of errors that are trapped + // via message boxes during a normal UI session + if(theApp.MatlabLoveNote.GetLength()>0) + { + LuaResult.Format("error: %s",theApp.MatlabLoveNote); + } + + return LuaResult.AllocSysString(); +} + +void ActiveFEMM::DoLuaCmd(CString strToLua) +{ + LuaResult.Empty(); + if(m_luaWindowStatus==SW_SHOW) bLinehook=NormalLua; + else bLinehook=HiddenLua; + theApp.bActiveX=TRUE; + if (lua_dostring(lua,strToLua)!=0) LuaResult=theApp.LuaErrmsg; + theApp.bActiveX=FALSE; + lua_byebye=FALSE; + bLinehook=FALSE; +} + +int ActiveFEMM::lua_to_string(lua_State *L) +{ + CString s; + + int n = lua_gettop(L); + LuaResult=""; + + for(int k=1;k<=n;k++) + { + s=lua_tostring(L,k); + LuaResult = LuaResult + s +"\n"; + } + + return 0; +} + +int ActiveFEMM::lua_to_matlab(lua_State *L) +{ + CString s; + + int n = lua_gettop(L); + if(n>0){ + LuaResult="[ "; + for(int k=1;k<=n;k++) + { + s=lua_tostring(L,k); + LuaResult = LuaResult + s + " "; + } + LuaResult += "]"; + } + else LuaResult.Empty(); + + return 0; +} diff --git a/femm/ActiveFEMM.h b/femm/ActiveFEMM.h new file mode 100644 index 0000000..5c9edc0 --- /dev/null +++ b/femm/ActiveFEMM.h @@ -0,0 +1,69 @@ +#if !defined(AFX_ACTIVEFEMM_H__B28DBF46_5DAD_4398_AD40_58F1D7107DFA__INCLUDED_) +#define AFX_ACTIVEFEMM_H__B28DBF46_5DAD_4398_AD40_58F1D7107DFA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ActiveFEMM.h : header file +// + + + +///////////////////////////////////////////////////////////////////////////// +// ActiveFEMM command target + +class ActiveFEMM : public CCmdTarget +{ + DECLARE_DYNCREATE(ActiveFEMM) + + DECLARE_OLETYPELIB(ActiveFemm) + + ActiveFEMM(); // protected constructor used by dynamic creation + +// Attributes +public: + +// Operations +public: + + static int lua_to_string(lua_State *L); + static int lua_to_matlab(lua_State *L); + void DoLuaCmd(CString strToLua); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ActiveFEMM) + public: + virtual void OnFinalRelease(); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~ActiveFEMM(); + + // Generated message map functions + //{{AFX_MSG(ActiveFEMM) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() + DECLARE_OLECREATE(ActiveFEMM) + + // Generated OLE dispatch map functions + //{{AFX_DISPATCH(ActiveFEMM) + afx_msg BSTR call2femm(LPCTSTR luacmd); + afx_msg BSTR mlab2femm(LPCTSTR luacmd); + //}}AFX_DISPATCH + DECLARE_DISPATCH_MAP() + DECLARE_INTERFACE_MAP() + + virtual BOOL GetDispatchIID(IID* pIID); + +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ACTIVEFEMM_H__B28DBF46_5DAD_4398_AD40_58F1D7107DFA__INCLUDED_) diff --git a/femm/ArcDlg.cpp b/femm/ArcDlg.cpp new file mode 100644 index 0000000..352a6b6 --- /dev/null +++ b/femm/ArcDlg.cpp @@ -0,0 +1,75 @@ +// ArcDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "ArcDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CArcDlg dialog + + +CArcDlg::CArcDlg(CWnd* pParent /*=NULL*/) + : CDialog(CArcDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CArcDlg) + m_ArcAngle = 0.0; + m_MaxSeg = 0.0; + //}}AFX_DATA_INIT +} + + +void CArcDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CArcDlg) + DDX_Control(pDX, IDC_ARCSEGBDRY, m_ArcSegBdry); + DDX_Text(pDX, IDC_ARCANGLE, m_ArcAngle); + DDV_MinMaxDouble(pDX, m_ArcAngle, 1., 180.); + DDX_Text(pDX, IDC_MAXSEG, m_MaxSeg); + DDV_MinMaxDouble(pDX, m_MaxSeg, 1.e-002, 10.); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_ARCANGLE, mIDC_ARCANGLE); + DDX_Control(pDX, IDC_MAXSEG, m_IDC_MAXSEG); +} + + +BEGIN_MESSAGE_MAP(CArcDlg, CDialog) + //{{AFX_MSG_MAP(CArcDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CArcDlg message handlers + +BOOL CArcDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + + m_ArcSegBdry.AddString(""); + + for(i=0;i namelist; + +// Dialog Data + //{{AFX_DATA(CArcDlg) + enum { IDD = IDD_ARCDLG }; + CComboBox m_ArcSegBdry; + double m_ArcAngle; + double m_MaxSeg; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CArcDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CArcDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit mIDC_ARCANGLE, m_IDC_MAXSEG; +}; diff --git a/femm/BHData.cpp b/femm/BHData.cpp new file mode 100644 index 0000000..25950fd --- /dev/null +++ b/femm/BHData.cpp @@ -0,0 +1,440 @@ +// BHData.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "BHData.h" +#include "fullmatrix.h" +#include "BHPlot.h" +#include "BHDatafile.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBHData dialog + + +CBHData::CBHData(CWnd* pParent /*=NULL*/) + : CDialog(CBHData::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBHData) + m_Bdata = _T(""); + m_Hdata = _T(""); + m_BHname = _T(""); + //}}AFX_DATA_INIT + + logplot=FALSE; +} + + +void CBHData::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBHData) + DDX_Text(pDX, IDC_BDATA, m_Bdata); + DDX_Text(pDX, IDC_HDATA, m_Hdata); + DDX_Text(pDX, IDC_BHNAME, m_BHname); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BDATA, m_IDC_BDATA); + DDX_Control(pDX, IDC_HDATA, m_IDC_HDATA); +} + + +BEGIN_MESSAGE_MAP(CBHData, CDialog) + //{{AFX_MSG_MAP(CBHData) + ON_BN_CLICKED(IDC_PLOT_BHCURVE, OnPlotBHcurve) + ON_BN_CLICKED(IDC_LOGPLOT_BHCURVE, OnLogPlotBHcurve) + ON_BN_CLICKED(IDC_READ_BHCURVE, OnReadBhcurve) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBHData message handlers + +void CBHData::StripBHData() +{ + int k; + char *buff,*nptr,*endptr; + double z; + + B.RemoveAll(); + H.RemoveAll(); + BHpoints=0; + + if((m_Bdata.GetLength()==0) || (m_Hdata.GetLength()==0)) return; + + k=m_Bdata.GetLength()*2; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,m_Bdata); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; //catch special case + else nptr=endptr; + if(B.GetSize()>0){ // enforce monotonicity + if (z<=B[B.GetSize()-1]) + break; + } + else if(z!=0) B.Add(0); + B.Add(z); + } + free(buff); + + k=m_Hdata.GetLength()*2; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,m_Hdata); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; + else nptr=endptr; + if(H.GetSize()>0){ + if (z<=H[H.GetSize()-1]) + break; + } + else if(z!=0) H.Add(0); + H.Add(z); + } + + BHpoints=(int) B.GetSize(); + if ((int) H.GetSize()0) + { + u0=sqrt(u0); + X0=-(c1 + u0)/(2.*c2); + X1=(-c1 + u0)/(2.*c2); + } + + //now, see if we've struck gold! + if (((X0>=0.)&&(X0<=L))||((X1>=0.)&&(X1<=L))) + CurveOK=FALSE; + } + + if(CurveOK!=TRUE) //remedial action + { + // Smooth out input points + // to get rid of rapid transitions; + // Uses a 3-point moving average + for(i=1;i3.*m1) || (slope[i]>3.*m2)) + { + H[i]=(8.*H[i]+H[i-1]+H[i+1])/10.; + B[i]=(8.*B[i]+B[i-1]+B[i+1])/10.; + bDone=FALSE; + } + } + }while(!bDone); + + // do endpoints + slope[0]=(H[1]-H[0])/(B[1]-B[0]); + slope[i]=(H[i]-H[i-1])/(B[i]-B[i-1]); + + return; +} +*/ + +double CBHData::GetH(double x) +{ + double b,h,z,z2,l; + int i; + + b=fabs(x); + if ((BHpoints==0) || (b==0)) return 0; + + if(b>B[BHpoints-1]) + return (H[BHpoints-1] + slope[BHpoints-1]*(b-B[BHpoints-1])); + + for(i=0;i=B[i]) && (b<=B[i+1])){ + l=(B[i+1]-B[i]); + z=(b-B[i])/l; + z2=z*z; + h=(1.-3.*z2+2.*z2*z)*H[i] + + z*(1.-2.*z+z2)*l*slope[i] + + z2*(3.-2.*z)*H[i+1] + + z2*(z-1.)*l*slope[i+1]; + return h; + } + + return 0; +} + +void CBHData::OnLogPlotBHcurve() +{ + logplot=TRUE; + OnPlotBHcurve(); +} + +void CBHData::OnPlotBHcurve() +{ + CBHPlot xyplot; + int i; + double b,db; + BOOL logscale=logplot; + logplot=FALSE; + + slope=NULL; + UpdateData(); + StripBHData(); + + if (BHpoints<3){ + MsgBox("Must have at least 3 pairs of data points"); + return; + } + + // copy raw B-H data for plotting in comparison to + // splined (and possibly smoothed) curve + xyplot.NumPts=BHpoints; + xyplot.Pts=(CComplex *)calloc(BHpoints,sizeof(CComplex)); + for(i=0;iGetExecutablePath(); + + // Actually evaluate all the points on the line... + if(xyplot.Create(101,2)==FALSE){ + free(slope); + return; + } + + db=(B[BHpoints-1]-B[0])/100.; + + for(i=0,b=B[0];i<=100;i++,b+=db) + { + xyplot.M[i][1]=b; + xyplot.M[i][0]=GetH(b); + } + + sprintf(xyplot.lbls[0],"H, Amp/Meter"); + sprintf(xyplot.lbls[1],"B, Tesla"); + + // Create the plot, send it to the clipboard, spawn viewer... + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + xyplot.MakePlot(&Meta,logscale); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + { + MsgBox("Couldn't SetClipboardData"); + } + CloseClipboard(); + + // fire up plot viewer; +// ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + + // in this case call the external program rather than + // displaying in the window. Since dialog is running modal, + // it obscures the plotted BH curve--this is an annoying kludge. + char CommandLine[MAX_PATH]; + sprintf(CommandLine,"%sfemmplot.exe", (const char *) ((CFemmApp *)AfxGetApp())->GetExecutablePath()); + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,0, NULL, NULL, &StartupInfo2, &ProcessInfo2); + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } + + if (slope!=NULL) free(slope); +} + +void CBHData::OnReadBhcurve() +{ + // TODO: Add your control notification handler code here + + CFileDialog *fname_dia; + CString infile; + + fname_dia=new CFileDialog( + TRUE, + "dat | * ", + infile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Two column text data file (*.dat) | *.dat; *.DAT | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + infile=fname_dia->GetPathName(); + delete[] fname_dia; + + CBHDatafile dlg; + if(dlg.DoModal()==IDCANCEL) return; + + // read in data from text file; + m_Bdata.Empty(); + m_Hdata.Empty(); + + double bunits[]={1.,0.0001,0.1}; + double hunits[]={1.,1000.,79.5775,79577.5}; + char s[1024]; + double b_in,h_in,b_off,h_off; + + b_off=0;h_off=0; + FILE *fp=fopen(infile,"rt"); + if (fp==NULL){ + MsgBox("problem opening data file"); + return; + } + do{ + if(fgets(s,1024,fp)==NULL) break; + if(dlg.BHOrder==0) sscanf(s,"%lf %lf",&b_in,&h_in); + else sscanf(s,"%lf %lf",&h_in,&b_in); + b_in *= bunits[dlg.BUnits]; + if ((b_off==0) && (b_in<0)) b_off=fabs(b_in); + b_in += b_off; + h_in *= hunits[dlg.HUnits]; + if ((h_off==0) && (h_in<0)) h_off=fabs(h_in); + h_in += h_off; + sprintf(s,"%f\r\n",b_in); m_Bdata += s; + sprintf(s,"%f\r\n",h_in); m_Hdata += s; + } while(1>0); + + SetDlgItemText(IDC_BDATA,m_Bdata); + SetDlgItemText(IDC_HDATA,m_Hdata); + + fclose(fp); + + if(h_off!=0){ + sprintf(s,"Suggested Hc = %.0f A/m",h_off); + AfxMessageBox(s,MB_ICONINFORMATION); + } + +} diff --git a/femm/BHData.h b/femm/BHData.h new file mode 100644 index 0000000..35aa984 --- /dev/null +++ b/femm/BHData.h @@ -0,0 +1,53 @@ +// BHData.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBHData dialog +#include +#include "afxwin.h" + +class CBHData : public CDialog +{ +// Construction +public: + CBHData(CWnd* pParent = NULL); // standard constructor + CArray B; + CArray H; + int BHpoints; + double *slope; + BOOL logplot; + + void StripBHData(); + void GetSlopes(); + double GetH(double x); + +// Dialog Data + //{{AFX_DATA(CBHData) + enum { IDD = IDD_BHCURVE }; + CString m_Bdata; + CString m_Hdata; + CString m_BHname; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBHData) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBHData) + afx_msg void OnPlotBHcurve(); + afx_msg void OnLogPlotBHcurve(); + afx_msg void OnReadBhcurve(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_BDATA; + CLuaEdit m_IDC_HDATA; +}; diff --git a/femm/BHDatafile.cpp b/femm/BHDatafile.cpp new file mode 100644 index 0000000..33ce1f8 --- /dev/null +++ b/femm/BHDatafile.cpp @@ -0,0 +1,136 @@ +// BHDatafile.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "BHDatafile.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBHDatafile dialog + + +CBHDatafile::CBHDatafile(CWnd* pParent /*=NULL*/) + : CDialog(CBHDatafile::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBHDatafile) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CBHDatafile::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBHDatafile) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBHDatafile, CDialog) + //{{AFX_MSG_MAP(CBHDatafile) + ON_BN_CLICKED(IDC_AMPM, OnAmpm) + ON_BN_CLICKED(IDC_BFIRST, OnBfirst) + ON_BN_CLICKED(IDC_GAUSS, OnGauss) + ON_BN_CLICKED(IDC_KAMPM, OnKampm) + ON_BN_CLICKED(IDC_KGAUSS, OnKgauss) + ON_BN_CLICKED(IDC_KOERSTED, OnKoersted) + ON_BN_CLICKED(IDC_OERSTED, OnOersted) + ON_BN_CLICKED(IDC_TESLA, OnTesla) + ON_BN_CLICKED(IDC_HFIRST, OnHfirst) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBHDatafile message handlers + +BOOL CBHDatafile::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + BHOrder=0; + BUnits=0; + HUnits=0; + + CheckRadioButton( + IDC_BFIRST,// identifier of first radio button in group + IDC_HFIRST, // identifier of last radio button in group + IDC_BFIRST // identifier of radio button to select + ); + + CheckRadioButton( + IDC_TESLA,// identifier of first radio button in group + IDC_KGAUSS, // identifier of last radio button in group + IDC_TESLA // identifier of radio button to select + ); + + CheckRadioButton( + IDC_AMPM,// identifier of first radio button in group + IDC_KOERSTED, // identifier of last radio button in group + IDC_AMPM // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CBHDatafile::OnAmpm() +{ + // TODO: Add your control notification handler code here + HUnits=0; +} + +void CBHDatafile::OnBfirst() +{ + // TODO: Add your control notification handler code here + BHOrder=0; +} + +void CBHDatafile::OnGauss() +{ + // TODO: Add your control notification handler code here + BUnits=1; +} + +void CBHDatafile::OnKampm() +{ + // TODO: Add your control notification handler code here + HUnits=1; +} + +void CBHDatafile::OnKgauss() +{ + // TODO: Add your control notification handler code here + BUnits=2; +} + +void CBHDatafile::OnKoersted() +{ + // TODO: Add your control notification handler code here + HUnits=3; +} + +void CBHDatafile::OnOersted() +{ + // TODO: Add your control notification handler code here + HUnits=2; +} + +void CBHDatafile::OnTesla() +{ + // TODO: Add your control notification handler code here + BUnits=0; +} + +void CBHDatafile::OnHfirst() +{ + // TODO: Add your control notification handler code here + BHOrder=1; +} diff --git a/femm/BHDatafile.h b/femm/BHDatafile.h new file mode 100644 index 0000000..1b221da --- /dev/null +++ b/femm/BHDatafile.h @@ -0,0 +1,45 @@ +// BHDatafile.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBHDatafile dialog + +class CBHDatafile : public CDialog +{ +// Construction +public: + CBHDatafile(CWnd* pParent = NULL); // standard constructor + int BHOrder,BUnits,HUnits; + +// Dialog Data + //{{AFX_DATA(CBHDatafile) + enum { IDD = IDD_BHDATAFILE }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBHDatafile) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBHDatafile) + virtual BOOL OnInitDialog(); + afx_msg void OnAmpm(); + afx_msg void OnBfirst(); + afx_msg void OnGauss(); + afx_msg void OnKampm(); + afx_msg void OnKgauss(); + afx_msg void OnKoersted(); + afx_msg void OnOersted(); + afx_msg void OnTesla(); + afx_msg void OnHfirst(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/BdryDlg.cpp b/femm/BdryDlg.cpp new file mode 100644 index 0000000..e2a9d24 --- /dev/null +++ b/femm/BdryDlg.cpp @@ -0,0 +1,217 @@ +// BdryDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "BdryDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBdryDlg dialog + + +CBdryDlg::CBdryDlg(CWnd* pParent /*=NULL*/) + : CDialog(CBdryDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBdryDlg) + m_A0 = 0.0; + m_A1 = 0.0; + m_A2 = 0.0; + m_BdryName = _T(""); + m_c0 = 0.0; + m_c1 = 0.0; + m_Mu = 0.0; + m_Phi = 0.0; + m_Sig = 0.0; + m_innerangle = 0.0; + m_outerangle = 0.0; + //}}AFX_DATA_INIT +} + + +void CBdryDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBdryDlg) + DDX_Control(pDX, IDC_STATIC_SYMB3, m_static3); + DDX_Control(pDX, IDC_STATIC_SYMB2, m_static2); + DDX_Control(pDX, IDC_STATIC_SYMB1, m_static1); + DDX_Control(pDX, IDC_BDRYFORMAT, m_BdryFormat); + DDX_Text(pDX, IDC_A0, m_A0); + DDX_Text(pDX, IDC_A1, m_A1); + DDX_Text(pDX, IDC_A2, m_A2); + DDX_Text(pDX, IDC_BDRYNAME, m_BdryName); + DDX_Text(pDX, IDC_C0, m_c0); + DDX_Text(pDX, IDC_C1, m_c1); + DDX_Text(pDX, IDC_MU, m_Mu); + DDX_Text(pDX, IDC_PHI, m_Phi); + DDX_Text(pDX, IDC_SIGMA, m_Sig); + DDX_Text(pDX, IDC_INNERANGLE, m_innerangle); + DDX_Text(pDX, IDC_OUTERANGLE, m_outerangle); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_A0, m_IDC_A0); + DDX_Control(pDX, IDC_A1, m_IDC_A1); + DDX_Control(pDX, IDC_A2, m_IDC_A2); + DDX_Control(pDX, IDC_BDRYNAME, m_IDC_BDRYNAME); + DDX_Control(pDX, IDC_C0, m_IDC_c0); + DDX_Control(pDX, IDC_C1, m_IDC_c1); + DDX_Control(pDX, IDC_MU, m_IDC_Mu); + DDX_Control(pDX, IDC_PHI, m_IDC_Phi); + DDX_Control(pDX, IDC_SIGMA, m_IDC_Sig); + DDX_Control(pDX, IDC_INNERANGLE, m_IDC_INNERANGLE); + DDX_Control(pDX, IDC_OUTERANGLE, m_IDC_OUTERANGLE); +} + + +BEGIN_MESSAGE_MAP(CBdryDlg, CDialog) + //{{AFX_MSG_MAP(CBdryDlg) + ON_CBN_SELCHANGE(IDC_BDRYFORMAT, OnSelchangeBdryformat) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBdryDlg message handlers + +void CBdryDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + + CFont symbfont; + +// Dialog Data + //{{AFX_DATA(CBdryDlg) + enum { IDD = IDD_BDRYDLG }; + CStatic m_static3; + CStatic m_static2; + CStatic m_static1; + CComboBox m_BdryFormat; + double m_A0; + double m_A1; + double m_A2; + CString m_BdryName; + CComplex m_c0; + CComplex m_c1; + double m_Mu; + double m_Phi; + double m_Sig; + double m_innerangle; + double m_outerangle; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBdryDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBdryDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeBdryformat(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_IDC_A0, m_IDC_A1, m_IDC_A2, m_IDC_BDRYNAME; + CLuaEdit m_IDC_c0, m_IDC_c1, m_IDC_Mu, m_IDC_Phi, m_IDC_Sig; + CLuaEdit m_IDC_INNERANGLE, m_IDC_OUTERANGLE; + +}; diff --git a/femm/BendContourDlg.cpp b/femm/BendContourDlg.cpp new file mode 100644 index 0000000..29c7cb4 --- /dev/null +++ b/femm/BendContourDlg.cpp @@ -0,0 +1,39 @@ +// BendContourDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "BendContourDlg.h" + + +// CBendContourDlg dialog + +IMPLEMENT_DYNAMIC(CBendContourDlg, CDialog) +CBendContourDlg::CBendContourDlg(CWnd* pParent /*=NULL*/) + : CDialog(CBendContourDlg::IDD, pParent) + , m_angle(0) + , m_anglestep(1) +{ +} + +CBendContourDlg::~CBendContourDlg() +{ +} + +void CBendContourDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Text(pDX, IDC_BENDANGLE, m_angle); + DDV_MinMaxDouble(pDX, m_angle, -180, 180); + DDX_Text(pDX, IDC_BENDSEGMENT, m_anglestep); + DDV_MinMaxDouble(pDX, m_anglestep, 0, 180); + DDX_Control(pDX, IDC_BENDANGLE, m_IDC_angle); + DDX_Control(pDX, IDC_BENDSEGMENT, m_IDC_anglestep); +} + + +BEGIN_MESSAGE_MAP(CBendContourDlg, CDialog) +END_MESSAGE_MAP() + + +// CBendContourDlg message handlers diff --git a/femm/BendContourDlg.h b/femm/BendContourDlg.h new file mode 100644 index 0000000..720a220 --- /dev/null +++ b/femm/BendContourDlg.h @@ -0,0 +1,26 @@ +#pragma once + + +// CBendContourDlg dialog + +class CBendContourDlg : public CDialog +{ + DECLARE_DYNAMIC(CBendContourDlg) + +public: + CBendContourDlg(CWnd* pParent = NULL); // standard constructor + virtual ~CBendContourDlg(); + +// Dialog Data + enum { IDD = IDD_BENDCONTOUR }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + double m_angle; + double m_anglestep; + CLuaEdit m_IDC_angle; + CLuaEdit m_IDC_anglestep; +}; diff --git a/femm/BlockInt.cpp b/femm/BlockInt.cpp new file mode 100644 index 0000000..8bfd44b --- /dev/null +++ b/femm/BlockInt.cpp @@ -0,0 +1,62 @@ +// BlockInt.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "BlockInt.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBlockInt dialog + + +CBlockInt::CBlockInt(CWnd* pParent /*=NULL*/) + : CDialog(CBlockInt::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBlockInt) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CBlockInt::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBlockInt) + DDX_Control(pDX, IDC_BINTTYPE, m_binttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBlockInt, CDialog) + //{{AFX_MSG_MAP(CBlockInt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBlockInt message handlers + +BOOL CBlockInt::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + binttype=0; + m_binttype.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CBlockInt::OnOK() +{ + // TODO: Add extra validation here + binttype=m_binttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/BlockInt.h b/femm/BlockInt.h new file mode 100644 index 0000000..6aade18 --- /dev/null +++ b/femm/BlockInt.h @@ -0,0 +1,38 @@ +// BlockInt.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBlockInt dialog + +class CBlockInt : public CDialog +{ +// Construction +public: + CBlockInt(CWnd* pParent = NULL); // standard constructor + + int binttype; + +// Dialog Data + //{{AFX_DATA(CBlockInt) + enum { IDD = IDD_BLOCKINT }; + CComboBox m_binttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBlockInt) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBlockInt) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/CDRAWDOC.CPP b/femm/CDRAWDOC.CPP new file mode 100644 index 0000000..6955f0c --- /dev/null +++ b/femm/CDRAWDOC.CPP @@ -0,0 +1,2658 @@ +// cdrawDoc.cpp : implementation of the CcdrawDoc class +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cdrawView.h" +#include "cd_probdlg.h" +#include "cd_PtProp.h" +#include "cd_OpBlkDlg.h" +#include "cd_OpNodeDlg.h" +#include "cd_OpSegDlg.h" +#include "cd_OpArcSegDlg.h" +#include "OpGrp.h" +#include "ArcDlg.h" +#include "ExteriorProps.h" + +extern void *pcdrawDoc; +extern lua_State *lua; +extern BOOL bLinehook; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CcdrawDoc + +IMPLEMENT_DYNCREATE(CcdrawDoc, CDocument) + +BEGIN_MESSAGE_MAP(CcdrawDoc, CDocument) + //{{AFX_MSG_MAP(CcdrawDoc) + 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() + +///////////////////////////////////////////////////////////////////////////// +// CcdrawDoc construction/destruction + +CcdrawDoc::CcdrawDoc() +{ + // 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_frequency=60; + 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(); +} + +CcdrawDoc::~CcdrawDoc() +{ + if (pcdrawDoc==this) pcdrawDoc=NULL; +} + +BOOL CcdrawDoc::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; + MinAngle=d_minangle; + SmartMesh=theApp.d_SmartMesh; + Depth=d_depth; + LengthUnits=d_length; + ProblemType=d_type; + Coords=d_coord; + Frequency=d_frequency; + ProblemNote="Add comments here."; + extRo=extRi=extZo=0; + + + // reset view to default attributes + CcdrawView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + if (pos!=NULL){ + pView=(CcdrawView *)GetNextView(pos); + if (pView!=NULL) pView->OnNewDocument(); + } + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CcdrawDoc serialization + +void CcdrawDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CcdrawDoc diagnostics + +#ifdef _DEBUG +void CcdrawDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CcdrawDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CcdrawDoc commands + +void CcdrawDoc::OnDefineProblem() +{ + cdCProbDlg 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_depth = Depth; + pDlg.m_frequency = Frequency; + pDlg.lengthunits = LengthUnits; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + 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; + Frequency = pDlg.m_frequency; + } +} + +void CcdrawDoc::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 CcdrawDoc::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 CcdrawDoc::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 CcdrawDoc::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 CcdrawDoc::OpArcSegDlg() +{ + int i,j,k,nselected; + cdCOpArcSegDlg 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; + } + + // Frequency in Hz + if( _strnicmp(q,"[frequency]",11)==0){ + v=StripKey(s); + sscanf(v,"%lf",&Frequency); + 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; + } + + // 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; + } + + // 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.vp=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,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.vp.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.vp.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.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.vs=0; + BProp.qs=0; + BProp.c0=0; + BProp.c1=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,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.vs.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.vs.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==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,"",9)==0){ + lineproplist.Add(BProp); + q[0]=NULL; + } + + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.ex=1.; + MProp.ey=1.; + MProp.ox=0.; + MProp.oy=0.; + MProp.ltx=0.; + MProp.lty=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.ox); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.oy); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ltx); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.lty); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + blockproplist.Add(MProp); + q[0]=NULL; + } + + // Circuit Properties + if( _strnicmp(q,"",16)==0){ + CProp.CircName="New Conductor"; + CProp.vc=0.; + CProp.qc=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,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.vc.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.vc.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.qc.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.qc.im); + 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].vp.re); + fprintf(fp," = %.17g\n",nodeproplist[i].vp.im); + fprintf(fp," = %.17g\n",nodeproplist[i].qp.re); + fprintf(fp," = %.17g\n",nodeproplist[i].qp.im); + 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].vs.re); + fprintf(fp," = %.17g\n",lineproplist[i].vs.im); + fprintf(fp," = %.17g\n",lineproplist[i].qs.re); + fprintf(fp," = %.17g\n",lineproplist[i].qs.im); + 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," \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].ox); + fprintf(fp," = %.17g\n",blockproplist[i].oy); + fprintf(fp," = %.17g\n",blockproplist[i].ex); + fprintf(fp," = %.17g\n",blockproplist[i].ey); + fprintf(fp," = %.17g\n",blockproplist[i].ltx); + fprintf(fp," = %.17g\n",blockproplist[i].lty); + fprintf(fp," \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].vc.re); + fprintf(fp," = %.17g\n",circproplist[i].vc.im); + fprintf(fp," = %.17g\n",circproplist[i].qc.re); + fprintf(fp," = %.17g\n",circproplist[i].qc.im); + 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 CcdrawDoc::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 CcdrawDoc::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,"",7)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_frequency); + 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 CcdrawDoc::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 CcdrawDoc::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 CcdrawDoc::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) +#include + +#include "lua.h" +#include "luaconsoledlg.h" +#include "luadebug.h" + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +extern CFemmApp theApp; // + +// cdrawDoc.h : interface of the CcdrawDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CcdrawDoc : public CDocument +{ +protected: // create from serialization only + CcdrawDoc(); + DECLARE_DYNCREATE(CcdrawDoc) + +// Attributes +public: + + // General problem attributes + double Precision; + double MinAngle; + int SmartMesh; + double Depth; + double Frequency; + int LengthUnits; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL NoDraw; + + // default behaviors + double d_prec; + double d_minangle; + double d_depth; + double d_frequency; + int d_coord; + int d_length; + int d_type; + + CString BinDir; + + // lists of nodes, segments, and block labels + CArray< cdrawdata::CNode, cdrawdata::CNode&> nodelist; + CArray< cdrawdata::CSegment, cdrawdata::CSegment&> linelist; + CArray< cdrawdata::CArcSegment, cdrawdata::CArcSegment&> arclist; + CArray< cdrawdata::CBlockLabel, cdrawdata::CBlockLabel&> blocklist; + + // lists of nodes, segments, and block labels for undo purposes... + CArray< cdrawdata::CNode, cdrawdata::CNode&> undonodelist; + CArray< cdrawdata::CSegment, cdrawdata::CSegment&> undolinelist; + CArray< cdrawdata::CArcSegment, cdrawdata::CArcSegment&> undoarclist; + CArray< cdrawdata::CBlockLabel, cdrawdata::CBlockLabel&> undoblocklist; + + // CArrays containing the mesh information + CArray< CPoint, CPoint&> meshline; + CArray< CPoint, CPoint&> greymeshline; + CArray< cdrawdata::CNode, cdrawdata::CNode&> meshnode; + + // lists of properties + CArray< cdrawdata::CMaterialProp, cdrawdata::CMaterialProp& > blockproplist; + CArray< cdrawdata::CBoundaryProp, cdrawdata::CBoundaryProp& > lineproplist; + CArray< cdrawdata::CPointProp, cdrawdata::CPointProp& > nodeproplist; + CArray< cdrawdata::CCircuit, cdrawdata::CCircuit& > circproplist; + double extRo,extRi,extZo; + +// Operations +public: + + void UnselectAll(); + double ShortestDistance(double p, double q, int segm); + + BOOL AddNode(double x, double y, double d); + + BOOL AddSegment(int n0, int n1, double tol=0); + BOOL AddSegment(int n0, int n1, cdrawdata::CSegment *parsegm, double tol=0); + BOOL AddArcSegment(cdrawdata::CArcSegment &asegm, double tol=0); + BOOL AddBlockLabel(double x, double y, double d); + BOOL AddNode(cdrawdata::CNode &node, double d); + BOOL AddSegment(CComplex p0, CComplex p1, cdrawdata::CSegment &segm, double tol=0); + BOOL AddArcSegment(CComplex p0, CComplex p1, cdrawdata::CArcSegment &asegm, double tol=0); + + BOOL AddBlockLabel(cdrawdata::CBlockLabel &blabel, double d); + int ClosestNode(double x, double y); + int ClosestBlockLabel(double x, double y); + int ClosestSegment(double x, double y); + BOOL GetIntersection(int n0, int n1, int segm, double *xi, double *yi); + int ClosestArcSegment(double x, double y); + void GetCircle(cdrawdata::CArcSegment &asegm,CComplex &c, double &R); + int GetLineArcIntersection(cdrawdata::CSegment &seg, cdrawdata::CArcSegment &arc, CComplex *p); + int GetArcArcIntersection(cdrawdata::CArcSegment &arc1, cdrawdata::CArcSegment &arc2, CComplex *p); + double ShortestDistanceFromArc(CComplex p, cdrawdata::CArcSegment &arc); + void RotateMove(CComplex c, double t, int EditAction); + void TranslateMove(double dx, double dy, int EditAction); + void ScaleMove(double bx, double by, double sf, int EditAction); + void MirrorSelected(double x0, double y0, double x1, double y1, int ea); + void RotateCopy(CComplex c, double t, int ncopies, int EditAction); + void TranslateCopy(double dx, double dy, int ncopies, int EditAction); + BOOL DeleteSelectedNodes(); + BOOL DeleteSelectedSegments(); + BOOL DeleteSelectedArcSegments(); + BOOL DeleteSelectedBlockLabels(); + BOOL OpBlkDlg(); + void OpNodeDlg(); + void OpSegDlg(); + void OpArcSegDlg(); + void OpGrpDlg(); + BOOL LoadMesh(); + BOOL OnWritePoly(); + BOOL FunnyOnWritePoly(); + BOOL ReadDXF(CString fname, double DefTol=-1.); + BOOL WriteDXF(CString fname); + BOOL HasPeriodicBC(); + BOOL CanCreateRadius(int n); + BOOL CreateRadius(int n, double r); + double LineLength(int i); + BOOL ScanPreferences(); + + void UpdateUndo(); + void Undo(); + void EnforcePSLG(); // makes sure that everything is kosher... + void EnforcePSLG(double tol); + void FancyEnforcePSLG(double tol); + BOOL SelectOrphans(); + BOOL dxf_line_hook(); +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CcdrawDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + void initalise_lua(); + static int lua_prob_def(lua_State *L); + static int luaSaveDocument(lua_State *L); + static int lua_create_mesh(lua_State *L); + static int lua_smartmesh(lua_State *L); + static int lua_purge_mesh(lua_State *L); + static int lua_show_mesh(lua_State *L); + static int lua_analyze(lua_State *L); + static int lua_runpost(lua_State *L); + static int lua_addnode(lua_State *L); + static int lua_addlabel(lua_State *L); + static int lua_addline(lua_State *L); + static int lua_addarc(lua_State *L); + static int lua_selectnode(lua_State *L); + static int lua_selectlabel(lua_State *L); + static int lua_selectsegment(lua_State *L); + static int lua_selectarcsegment(lua_State *L); + static int lua_clearselected(lua_State *L); + static int lua_setnodeprop(lua_State *L); + static int lua_setblockprop(lua_State *L); + static int lua_setsegmentprop(lua_State *L); + static int lua_setarcsegmentprop(lua_State *L); + static int lua_deleteselected(lua_State *L); + static int lua_deleteselectedsegments(lua_State *L); + static int lua_deleteselectednodes(lua_State *L); + static int lua_deleteselectedlabels(lua_State *L); + static int lua_deleteselectedarcsegments(lua_State *L); + static int lua_zoomout(lua_State *L); + static int lua_zoomnatural(lua_State *L); + static int lua_zoomin(lua_State *L); + static int lua_move_translate(lua_State *L); + static int lua_move_rotate(lua_State *L); + static int lua_copy_translate(lua_State *L); + static int lua_copy_rotate(lua_State *L); + static int lua_mirror(lua_State *L); + static int lua_scale(lua_State *L); + static int lua_addmatprop(lua_State *L); + static int lua_addpointprop(lua_State *L); + static int lua_addboundprop(lua_State *L); + static int lua_addcircuitprop(lua_State *L); + static int lua_delcircuitprop(lua_State *L); + static int lua_delpointprop(lua_State *L); + static int lua_delboundprop(lua_State *L); + static int lua_delmatprop(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_selectgroup(lua_State *L); + static int lua_zoom(lua_State *L); + static int lua_newdocument(lua_State *L); + static int lua_savebitmap(lua_State * L); + static int lua_modmatprop(lua_State *L); + static int lua_modboundprop(lua_State *L); + static int lua_modpointprop(lua_State *L); + static int lua_modcircprop(lua_State *L); + static int lua_exitpre(lua_State *L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC); + static int lua_saveWMF(lua_State *L); + static int lua_updatewindow(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_showgrid(lua_State *L); + static int lua_hidegrid(lua_State *L); + static int lua_gridsnap(lua_State *L); + static int lua_setgrid(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int lua_readdxf(lua_State *L); + static int lua_savedxf(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_defineouterspace(lua_State *L); + static int lua_attachouterspace(lua_State *L); + static int lua_detachouterspace(lua_State *L); + static int lua_attachdefault(lua_State *L); + static int lua_detachdefault(lua_State *L); + static int lua_createradius(lua_State *L); + static int lua_gettitle(lua_State *L); + static int lua_setgroup(lua_State *L); + static int lua_getmaterial(lua_State *L); + static int lua_getboundingbox(lua_State *L); + static int lua_getprobleminfo(lua_State *L); + static int lua_selectcircle(lua_State *L); + static int lua_selectrectangle(lua_State *L); + virtual ~CcdrawDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CcdrawDoc) + afx_msg void OnDefineProblem(); + afx_msg void OnEditMatprops(); + afx_msg void OnEditPtprops(); + afx_msg void OnEditSegprops(); + afx_msg void OnEditCircprops(); + afx_msg void OnEditExterior(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); +char *ParseDbl(char *t, double *f); +char *ParseInt(char *t, int *f); diff --git a/femm/CDRAWLUA.CPP b/femm/CDRAWLUA.CPP new file mode 100644 index 0000000..5a5071f --- /dev/null +++ b/femm/CDRAWLUA.CPP @@ -0,0 +1,2827 @@ +// cdrawDoc.cpp : implementation of the CcdrawDoc class +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cdrawView.h" +#include "promptbox.h" +#include "MainFrm.h" +#include "ChildFrm.h" + +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern void *pcdrawDoc; +extern lua_State * lua; +extern BOOL bLinehook; +extern int m_luaWindowStatus; + +#define CatchNullDocument(); if (pcdrawDoc==NULL)\ + { CString msg="No heat flow input in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//---------------------Lua Extensions------------------------ + +void CcdrawDoc::initalise_lua() +{ + + // register lua extensions + lua_register(lua,"ci_setfocus",lua_switchfocus); + lua_register(lua,"ci_saveas",luaSaveDocument); + lua_register(lua,"ci_createmesh",lua_create_mesh); + lua_register(lua,"ci_smartmesh",lua_smartmesh); + lua_register(lua,"ci_showmesh",lua_show_mesh); + lua_register(lua,"ci_purgemesh",lua_purge_mesh); + lua_register(lua,"ci_probdef",lua_prob_def); + lua_register(lua,"ci_analyse",lua_analyze); + lua_register(lua,"ci_loadsolution",lua_runpost); + lua_register(lua,"ci_addnode",lua_addnode); + lua_register(lua,"ci_addblocklabel",lua_addlabel); + lua_register(lua,"ci_addsegment",lua_addline); + lua_register(lua,"ci_addarc",lua_addarc); + lua_register(lua,"ci_selectnode",lua_selectnode); + lua_register(lua,"ci_selectlabel",lua_selectlabel); + lua_register(lua,"ci_selectsegment",lua_selectsegment); + lua_register(lua,"ci_selectarcsegment",lua_selectarcsegment); + lua_register(lua,"ci_clearselected",lua_clearselected); + lua_register(lua,"ci_setnodeprop",lua_setnodeprop); + lua_register(lua,"ci_setblockprop",lua_setblockprop); + lua_register(lua,"ci_setsegmentprop",lua_setsegmentprop); + lua_register(lua,"ci_setarcsegmentprop",lua_setarcsegmentprop); + lua_register(lua,"ci_deleteselected",lua_deleteselected); + lua_register(lua,"ci_deleteselectednodes",lua_deleteselectednodes); + lua_register(lua,"ci_deleteselectedlabels",lua_deleteselectedlabels); + lua_register(lua,"ci_deleteselectedsegments",lua_deleteselectedsegments); + lua_register(lua,"ci_deleteselectedarcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"ci_zoomnatural",lua_zoomnatural); + lua_register(lua,"ci_zoomout",lua_zoomout); + lua_register(lua,"ci_zoomin",lua_zoomin); + lua_register(lua,"ci_zoom",lua_zoom); + lua_register(lua,"ci_addmaterial",lua_addmatprop); + lua_register(lua,"ci_addpointprop",lua_addpointprop); + lua_register(lua,"ci_addconductorprop",lua_addcircuitprop); + lua_register(lua,"ci_addboundprop",lua_addboundprop); + lua_register(lua,"ci_modifymaterial",lua_modmatprop); + lua_register(lua,"ci_modifyboundprop",lua_modboundprop); + lua_register(lua,"ci_modifypointprop",lua_modpointprop); + lua_register(lua,"ci_modifyconductorprop",lua_modcircprop); + lua_register(lua,"ci_deletematerial",lua_delmatprop); + lua_register(lua,"ci_deleteboundprop",lua_delboundprop); + lua_register(lua,"ci_deleteconductor",lua_delcircuitprop); + lua_register(lua,"ci_deletepointprop",lua_delpointprop); + lua_register(lua,"ci_moverotate",lua_move_rotate); + lua_register(lua,"ci_movetranslate",lua_move_translate); + lua_register(lua,"ci_copyrotate",lua_copy_rotate); + lua_register(lua,"ci_copytranslate",lua_copy_translate); + lua_register(lua,"ci_mirror",lua_mirror); + lua_register(lua,"ci_scale",lua_scale); + lua_register(lua,"ci_seteditmode",lua_seteditmode); + lua_register(lua,"ci_selectgroup",lua_selectgroup); + lua_register(lua,"ci_newdocument",lua_newdocument); + lua_register(lua,"ci_savebitmap",lua_savebitmap); + lua_register(lua,"ci_savemetafile",lua_saveWMF); + lua_register(lua,"ci_close",lua_exitpre); + lua_register(lua,"ci_refrescview",lua_updatewindow); + lua_register(lua,"ci_shownames",lua_shownames); + lua_register(lua,"ci_showgrid",lua_showgrid); + lua_register(lua,"ci_hidegrid",lua_hidegrid); + lua_register(lua,"ci_gridsnap",lua_gridsnap); + lua_register(lua,"ci_setgrid",lua_setgrid); + lua_register(lua,"ci_readdxf",lua_readdxf); + lua_register(lua,"ci_savedxf",lua_savedxf); + lua_register(lua,"ci_defineouterspace",lua_defineouterspace); + lua_register(lua,"ci_attachouterspace",lua_attachouterspace); + lua_register(lua,"ci_detachouterspace",lua_detachouterspace); + lua_register(lua,"ci_resize",luaResize); + lua_register(lua,"ci_minimize",luaMinimize); + lua_register(lua,"ci_maximize",luaMaximize); + lua_register(lua,"ci_restore", luaRestore); + lua_register(lua,"ci_createradius",lua_createradius); + lua_register(lua,"ci_gettitle",lua_gettitle); + lua_register(lua,"ci_get_title",lua_gettitle); + lua_register(lua,"ci_setgroup",lua_setgroup); + lua_register(lua,"ci_set_group",lua_setgroup); + lua_register(lua,"ci_getmaterial",lua_getmaterial); + lua_register(lua,"ci_get_material",lua_getmaterial); + lua_register(lua,"ci_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"ci_getboundingbox",lua_getboundingbox); + lua_register(lua,"ci_selectcircle",lua_selectcircle); + lua_register(lua,"ci_selectrectangle",lua_selectrectangle); + + // compatibility lua function names + lua_register(lua,"ci_select_rectangle",lua_selectrectangle); + lua_register(lua,"ci_select_circle",lua_selectcircle); + lua_register(lua,"ci_define_outer_space",lua_defineouterspace); + lua_register(lua,"ci_attach_outer_space",lua_attachouterspace); + lua_register(lua,"ci_detach_outer_space",lua_detachouterspace); + lua_register(lua,"ci_attachdefault",lua_attachdefault); + lua_register(lua,"ci_detachdefault",lua_detachdefault); + lua_register(lua,"ci_attach_default",lua_attachdefault); + lua_register(lua,"ci_detach_default",lua_detachdefault); + lua_register(lua,"ci_set_focus",lua_switchfocus); + lua_register(lua,"ci_save_as",luaSaveDocument); + lua_register(lua,"ci_create_mesh",lua_create_mesh); + lua_register(lua,"ci_show_mesh",lua_show_mesh); + lua_register(lua,"ci_purge_mesh",lua_purge_mesh); + lua_register(lua,"ci_prob_def",lua_prob_def); + lua_register(lua,"ci_analyze",lua_analyze); + lua_register(lua,"ci_load_solution",lua_runpost); + lua_register(lua,"ci_add_node",lua_addnode); + lua_register(lua,"ci_add_block_label",lua_addlabel); + lua_register(lua,"ci_add_segment",lua_addline); + lua_register(lua,"ci_add_arc",lua_addarc); + lua_register(lua,"ci_select_node",lua_selectnode); + lua_register(lua,"ci_select_label",lua_selectlabel); + lua_register(lua,"ci_select_segment",lua_selectsegment); + lua_register(lua,"ci_select_arcsegment",lua_selectarcsegment); + lua_register(lua,"ci_clear_selected",lua_clearselected); + lua_register(lua,"ci_set_node_prop",lua_setnodeprop); + lua_register(lua,"ci_set_block_prop",lua_setblockprop); + lua_register(lua,"ci_set_segment_prop",lua_setsegmentprop); + lua_register(lua,"ci_set_arcsegment_prop",lua_setarcsegmentprop); + lua_register(lua,"ci_delete_selected",lua_deleteselected); + lua_register(lua,"ci_delete_selected_nodes",lua_deleteselectednodes); + lua_register(lua,"ci_delete_selected_labels",lua_deleteselectedlabels); + lua_register(lua,"ci_delete_selected_segments",lua_deleteselectedsegments); + lua_register(lua,"ci_delete_selected_arcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"ci_zoom_natural",lua_zoomnatural); + lua_register(lua,"ci_zoom_out",lua_zoomout); + lua_register(lua,"ci_zoom_in",lua_zoomin); + lua_register(lua,"ci_add_material",lua_addmatprop); + lua_register(lua,"ci_add_point_prop",lua_addpointprop); + lua_register(lua,"ci_add_conductor_prop",lua_addcircuitprop); + lua_register(lua,"ci_add_bound_prop",lua_addboundprop); + lua_register(lua,"ci_modify_material",lua_modmatprop); + lua_register(lua,"ci_modify_bound_prop",lua_modboundprop); + lua_register(lua,"ci_modify_point_prop",lua_modpointprop); + lua_register(lua,"ci_modify_conductor_prop",lua_modcircprop); + lua_register(lua,"ci_delete_material",lua_delmatprop); + lua_register(lua,"ci_delete_bound_prop",lua_delboundprop); + lua_register(lua,"ci_delete_conductor",lua_delcircuitprop); + lua_register(lua,"ci_delete_point_prop",lua_delpointprop); + lua_register(lua,"ci_move_rotate",lua_move_rotate); + lua_register(lua,"ci_move_translate",lua_move_translate); + lua_register(lua,"ci_copy_rotate",lua_copy_rotate); + lua_register(lua,"ci_copy_translate",lua_copy_translate); + lua_register(lua,"ci_set_edit_mode",lua_seteditmode); + lua_register(lua,"ci_select_group",lua_selectgroup); + lua_register(lua,"ci_new_document",lua_newdocument); + lua_register(lua,"ci_save_bitmap",lua_savebitmap); + lua_register(lua,"ci_save_metafile",lua_saveWMF); + lua_register(lua,"ci_refresh_view",lua_updatewindow); + lua_register(lua,"ci_show_grid",lua_showgrid); + lua_register(lua,"ci_hide_grid",lua_hidegrid); + lua_register(lua,"ci_grid_snap",lua_gridsnap); + lua_register(lua,"ci_set_grid",lua_setgrid); + lua_register(lua,"ci_show_names",lua_shownames); + lua_register(lua,"ci_read_dxf",lua_readdxf); + lua_register(lua,"ci_save_dxf",lua_savedxf); + lua_register(lua,"ci_create_radius",lua_createradius); + + pcdrawDoc=(CcdrawDoc *)this; +} + +int CcdrawDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CcdrawDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".feh") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<4;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CcdrawDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".feh") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pcdrawDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CcdrawDoc::lua_exitpre(lua_State *L) +{ + CatchNullDocument(); + ((CcdrawDoc *)pcdrawDoc)->OnCloseDocument( ); + + return 0; +} + +int CcdrawDoc::luaSaveDocument(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + int n; + n=lua_gettop(L); + + CString temp; + temp.Format("%s",lua_tostring(L,n)); + thisDoc->OnSaveDocument(temp); + thisDoc->SetPathName(temp); + + return 0; +} + +int CcdrawDoc::lua_readdxf(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + double DefTol; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + if (n==2) DefTol=lua_todouble(L,2); + else DefTol=0; + + result=thisDoc->ReadDXF(DocTitle,DefTol); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CcdrawDoc::lua_savedxf(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + + result=thisDoc->WriteDXF(DocTitle); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CcdrawDoc::lua_prob_def(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + CString units,type; + int n; + n=lua_gettop(L); + + // error traps + int LengthUnits=-1; + int ProblemType=-1; + double Precision; + double Frequency; + double MinAngle=-1; + + units.Format("%s",lua_tostring(L,1)); + type.Format("%s",lua_tostring(L,2)); + Frequency=lua_todouble(L,3); + Precision=lua_todouble(L,4); + if(n>4) thisDoc->Depth=lua_todouble(L,5); + if(n>5) MinAngle =lua_todouble(L,6); + if(units=="inches") LengthUnits=0; + if(units=="millimeters") LengthUnits=1; + if(units=="centimeters") LengthUnits=2; + if(units=="meters") LengthUnits=3; + if(units=="mills") LengthUnits=4; + if(units=="mils") LengthUnits=4; + if(units=="micrometers") LengthUnits=5; + if(type=="planar") ProblemType=0; + if(type=="axi") ProblemType=1; + + + // error detection and nice variable handling + + if (LengthUnits==-1) + { + CString msg; + msg.Format("Unknown length unit %s",units); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + thisDoc->LengthUnits=LengthUnits; + } + + if (ProblemType==-1) + { + CString msg; + msg.Format("Unknown problem type %s",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->ProblemType=ProblemType; + } + + + if (Precision < 1.e-16 || Precision >1.e-8) + { + CString msg; + msg.Format("Invalid Precision %lf",Precision); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->Precision=Precision; + } + + if ((MinAngle <=MINANGLE_MAX) && (MinAngle>=1.)) + { + thisDoc->MinAngle=MinAngle; + } + + if (thisDoc->Depth<=0) thisDoc->Depth=1; + + if (Frequency<0) Frequency=fabs(Frequency); + thisDoc->Frequency=Frequency; + +// CString temp; +// temp.Format("%s",lua_tostring(L,n)); + + + + + return 0; +} + +int CcdrawDoc::lua_create_mesh(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + theView->lnuMakeMesh(); + + return 1; +} + +int CcdrawDoc::lua_smartmesh(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + if (lua_gettop(L)!=0) + { + int k = (int)lua_todouble(L,1); + if (k!=0) k=1; + thisDoc->SmartMesh=k; + } + + return 0; +} + +int CcdrawDoc::lua_show_mesh(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + theView->lnu_show_mesh(); + + return 0; +} + +int CcdrawDoc::lua_purge_mesh(lua_State *L) +{ + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + theView->lnu_purge_mesh(); + + return 0; +} + +int CcdrawDoc::lua_analyze(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + int bHide=0; + if ((n==0) && (theApp.GetMainWnd()->GetStyle() & WS_MINIMIZE)) bHide=1; + if (n>0) bHide=(int)lua_todouble(L,1); + if (bHide!=0) bHide=1; + + theView->lnu_analyze(bHide); + + return 0; +} + +int CcdrawDoc::lua_runpost(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + CString pn = thisDoc->GetPathName(); + + if (pn.GetLength()==0){ + CString msg; + msg.Format("No results to display"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".anc\""; + if (((CFemmApp *) AfxGetApp())->COCheckIfAlreadyOpen(rootname)==FALSE) + AfxGetApp( )->OpenDocumentFile(rootname); + + return 0; +} + + +int CcdrawDoc::lua_addnode(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + double x,y,d; + + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddNode(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + +int CcdrawDoc::lua_addlabel(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + double x,y,d; + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddBlockLabel(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + + +int CcdrawDoc::lua_addline(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + CPoint mypntstart,mypntend; + + double sx,sy,ex,ey; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CcdrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + flag=thisDoc->AddSegment(thisDoc->ClosestNode(sx,sy),thisDoc->ClosestNode(ex,ey)); + + if(flag==TRUE) + { + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CcdrawDoc::lua_addarc(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + double sx,sy,ex,ey; + double angle,maxseg; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + angle=lua_todouble(L,5); + maxseg=lua_todouble(L,6); + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CcdrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + CArcSegment asegm; + asegm.n0=thisDoc->ClosestNode(sx,sy); + asegm.n1=thisDoc->ClosestNode(ex,ey); + thisDoc->nodelist[asegm.n1].ToggleSelect(); + theView->DrawPSLG(); + + asegm.MaxSideLength=maxseg; + asegm.ArcLength=angle; + asegm.BoundaryMarker=""; + + flag=thisDoc->AddArcSegment(asegm); + flag=FALSE; + thisDoc->UnselectAll(); + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CcdrawDoc::lua_selectnode(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->nodelist.GetSize()==0) return 0; + node=thisDoc->ClosestNode(mx,my); + thisDoc->nodelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[node].x); + lua_pushnumber(L,thisDoc->nodelist[node].y); + + return 2; +} + +int CcdrawDoc::lua_selectlabel(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->blocklist.GetSize()==0) return 0; + node=thisDoc->ClosestBlockLabel(mx,my); + thisDoc->blocklist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->blocklist[node].x); + lua_pushnumber(L,thisDoc->blocklist[node].y); + + return 2; +} + + +int CcdrawDoc::lua_selectsegment(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->linelist.GetSize()==0) return 0; + node=thisDoc->ClosestSegment(mx,my); + thisDoc->linelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].y); + + return 4; +} + + +int CcdrawDoc::lua_selectarcsegment(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->arclist.GetSize()==0) return 0; + node=thisDoc->ClosestArcSegment(mx,my); + thisDoc->arclist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].y); + + return 4; +} + +int CcdrawDoc::lua_clearselected(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + thisDoc->UnselectAll(); + return 0; +} + +int CcdrawDoc::lua_setnodeprop(lua_State *L) +{ + CatchNullDocument(); + CString nodeprop,inconductor; + int groupno; + + nodeprop.Format("%s",lua_tostring(L,1)); + groupno=(int) lua_todouble(L,2); + inconductor.Format("%s",lua_tostring(L,3)); + + if (groupno<0) + { + CString msg; + msg.Format("Invalid group no %d",groupno); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int i; + + // check to see how many (if any) nodes are selected. + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].IsSelected==TRUE) + { + thisDoc->nodelist[i].InGroup=groupno; + thisDoc->nodelist[i].BoundaryMarker=nodeprop; + thisDoc->nodelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CcdrawDoc::lua_setblockprop(lua_State *L) +{ + CatchNullDocument(); + CString blocktype; + BOOL automesh; + double meshsize; + int group; + + int n=lua_gettop(L); + + blocktype=""; + automesh=1; + meshsize=0; + group=0; + + if (n>0) blocktype.Format("%s",lua_tostring(L,1)); + if (n>1) automesh=(int) lua_todouble(L,2); + if (n>2) meshsize=lua_todouble(L,3); + if (n>3) group=(int) lua_todouble(L,4); + + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].MaxArea=PI*meshsize*meshsize/4.; + thisDoc->blocklist[i].BlockType=blocktype; + thisDoc->blocklist[i].InGroup=group; + if(automesh==1) thisDoc->blocklist[i].MaxArea=0; + } + } + + return 0; +} + +int CcdrawDoc::lua_setsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString prop,inconductor; + double elesize; + int automesh,hide,group; + + prop.Format("%s",lua_tostring(L,1)); + elesize=lua_todouble(L,2); + automesh=(int) lua_todouble(L,3); + hide=(int) lua_todouble(L,4); + group=(int) lua_todouble(L,5); + inconductor.Format("%s",lua_tostring(L,6)); + + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + for(int i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].IsSelected==TRUE){ + if (automesh==1) thisDoc->linelist[i].MaxSideLength=-1; + else{ + if (elesize>0) + thisDoc->linelist[i].MaxSideLength=elesize; + else elesize=-1; + } + thisDoc->linelist[i].BoundaryMarker=prop; + thisDoc->linelist[i].Hidden=hide; + thisDoc->linelist[i].InGroup=group; + thisDoc->linelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CcdrawDoc::lua_setarcsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString boundprop,inconductor; + double maxsegdeg; + int hide,group; + + maxsegdeg=lua_todouble(L,1); + if (maxsegdeg>10) maxsegdeg=10; + if (maxsegdeg<=0) maxsegdeg=1; + boundprop.Format("%s",lua_tostring(L,2)); + hide=(int) lua_todouble(L,3); + group=(int) lua_todouble(L,4); + inconductor.Format("%s",lua_tostring(L,5)); + + CcdrawDoc *thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].IsSelected==TRUE){ + thisDoc->arclist[i].BoundaryMarker=boundprop; + thisDoc->arclist[i].MaxSideLength=maxsegdeg; + thisDoc->arclist[i].Hidden=hide; + thisDoc->arclist[i].InGroup=group; + thisDoc->arclist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CcdrawDoc::lua_deleteselectednodes(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + thisDoc->DeleteSelectedNodes(); + return 0; +} + +int CcdrawDoc::lua_deleteselectedlabels(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + thisDoc->DeleteSelectedBlockLabels(); + return 0; + +} + +int CcdrawDoc::lua_deleteselectedsegments(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + thisDoc->DeleteSelectedSegments(); + return 0; +} + +int CcdrawDoc::lua_deleteselectedarcsegments(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + thisDoc->DeleteSelectedArcSegments(); + return 0; +} + +int CcdrawDoc::lua_deleteselected(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + thisDoc->DeleteSelectedSegments(); + thisDoc->DeleteSelectedArcSegments(); + thisDoc->DeleteSelectedNodes(); + thisDoc->DeleteSelectedBlockLabels(); + + return 0; +} + +int CcdrawDoc::lua_newdocument(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + thisDoc->OnNewDocument(); + thisDoc->SetPathName("Untitled",FALSE); + thisDoc->SetTitle("Untitled"); + return 0; +} + + +int CcdrawDoc::lua_zoomnatural(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomnatural(); + + return 0; +} + + +int CcdrawDoc::lua_zoomout(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + theView->lua_zoomout(); + + return 0; +} + +int CcdrawDoc::lua_zoomin(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomin(); + + return 0; +} + +int CcdrawDoc::lua_zoom(lua_State *L) +{ + CatchNullDocument(); + + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CRect r; + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CcdrawDoc::lua_copy_rotate(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + // IF N=5 WE Have an edit action, if n=4 we dont ! + + int EditAction,copies; + + double x,y,angle; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + angle=lua_todouble(L,3); + copies=(int) lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for copy rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + thisDoc->RotateCopy(CComplex(x,y),angle,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + +int CcdrawDoc::lua_copy_translate(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + int EditAction, copies; + double x,y; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + copies=(int) lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for copy translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->TranslateCopy(x,y,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + + +int CcdrawDoc::lua_move_translate(lua_State *L) +{ + CatchNullDocument(); + + double x,y; + int EditAction; + + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + if (n==3) EditAction=(int) lua_todouble(L,3); + if (n==2) EditAction=theView->EditAction; + + if(n!=3 && n!=2) + { + CString msg; + msg.Format("Invalid number of parameters for move translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->TranslateMove(x,y,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + +int CcdrawDoc::lua_move_rotate(lua_State *L) +{ + CatchNullDocument(); + + double x,y,shiftangle; + int EditAction; + + int n; + n=lua_gettop(L); + + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + shiftangle=lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for move rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->RotateMove(CComplex(x,y),shiftangle,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + + +int CcdrawDoc::lua_mirror(lua_State *L) +{ + CatchNullDocument(); + double m_pax,m_pay,m_pbx,m_pby; + int EditAction; + + CcdrawDoc *thisDoc; + CcdrawView *theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + m_pax=lua_todouble(L,1); + m_pay=lua_todouble(L,2); + m_pbx=lua_todouble(L,3); + m_pby=lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for mirror"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->MirrorSelected(m_pax,m_pay,m_pbx,m_pby,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int CcdrawDoc::lua_scale(lua_State *L) +{ + CatchNullDocument(); + int EditAction; + double x,y,scalefactor; + + int n; + n=lua_gettop(L); + + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + scalefactor=lua_todouble(L,3); + EditAction=(int) lua_todouble(L,4); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for scale"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->ScaleMove(x,y,scalefactor,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int CcdrawDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CcdrawDoc * thisDoc;CcdrawView * theView; + + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int iEditAction; + iEditAction=-1; + + if (EditAction=="nodes") iEditAction=0; + if (EditAction=="segments") iEditAction=1; + if (EditAction=="blocks") iEditAction=2; + if (EditAction=="arcsegments") iEditAction=3; + if (EditAction=="group") iEditAction=4; + + if(iEditAction==-1) + { + CString msg; + msg.Format("Invalid Edit Action %s",EditAction); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + theView->EditAction=iEditAction; + } + + + return 0; +} + +int CcdrawDoc::lua_selectgroup(lua_State *L) +{ + CatchNullDocument(); + int group,i; + group=(int) lua_todouble(L,1); + + if(group<0) + { + CString msg; + msg.Format("Invalid group %d",group); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + +// thisDoc->UnselectAll(); + + // select nodes + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].InGroup==group) + thisDoc->nodelist[i].IsSelected=TRUE; + } + + // select segments + for(i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].InGroup==group) + thisDoc->linelist[i].IsSelected=TRUE; + } + + // select arc segments + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].InGroup==group) + thisDoc->arclist[i].IsSelected=TRUE; + } + + // select blocks + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].InGroup==group) + thisDoc->blocklist[i].IsSelected=TRUE; + } + + + theView->EditAction=4; // set to group + + return 0; +} + + +int CcdrawDoc::lua_addmatprop(lua_State *L) +{ + CatchNullDocument(); + + CMaterialProp m; + int n=lua_gettop(L); + + if (n>0) m.BlockName.Format("%s",lua_tostring(L,1)); + if (n>1){ + m.ox=lua_todouble(L,2); + m.oy=m.ox; + } + if(n>2) m.oy=lua_todouble(L,3); + if(n>3){ + m.ex=lua_todouble(L,4); + m.ey=m.ex; + } + if(n>4) m.ey=lua_todouble(L,5); + if(n>5){ + m.ltx=lua_todouble(L,6); + m.lty=m.ltx; + } + if(n>6) m.lty=lua_todouble(L,7); + + ((CcdrawDoc *)pcdrawDoc)->blockproplist.Add(m); + + return 0; +} + + + +int CcdrawDoc::lua_modmatprop(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k,modprop; + + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->blockproplist[k].BlockName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->blockproplist[k].ox=lua_todouble(L,3); + break; + case 2: + thisDoc->blockproplist[k].oy=lua_todouble(L,3); + break; + case 3: + thisDoc->blockproplist[k].ex=lua_todouble(L,3); + break; + case 4: + thisDoc->blockproplist[k].ey=lua_todouble(L,3); + break; + case 5: + thisDoc->blockproplist[k].ltx=lua_todouble(L,3); + break; + case 6: + thisDoc->blockproplist[k].lty=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CcdrawDoc::lua_addboundprop(lua_State *L) +{ + CatchNullDocument(); + + CBoundaryProp m; + int n=lua_gettop(L); + + if(n>0) m.BdryName.Format("%s",lua_tostring(L,1)); + if(n>1) m.vs=lua_tonumber(L,2); + if(n>2) m.qs=lua_tonumber(L,3); + if(n>3) m.c0=lua_tonumber(L,4); + if(n>4) m.c1=lua_tonumber(L,5); + if(n>5) m.BdryFormat=(int) lua_todouble(L,6); + + ((CcdrawDoc *)pcdrawDoc)->lineproplist.Add(m); + + return 0; +} + +int CcdrawDoc::lua_modboundprop(lua_State *L) +{ + CatchNullDocument(); + CString BdryName; + int k,modprop; + + CcdrawDoc * thisDoc=(CcdrawDoc *)pcdrawDoc; + + // find the index of the boundary property to modify; + if (thisDoc->lineproplist.GetSize()==0) return TRUE; + BdryName.Format("%s",lua_tostring(L,1)); + for(k=0;klineproplist.GetSize();k++) + if(BdryName==thisDoc->lineproplist[k].BdryName) break; + + // get out of here if there's no matching material + if(k==thisDoc->lineproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->lineproplist[k].BdryName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->lineproplist[k].vs =lua_tonumber(L,3); + break; + case 2: + thisDoc->lineproplist[k].qs =lua_tonumber(L,3); + break; + case 3: + thisDoc->lineproplist[k].c0 =lua_tonumber(L,3); + break; + case 4: + thisDoc->lineproplist[k].c1 =lua_tonumber(L,3); + break; + case 5: + thisDoc->lineproplist[k].BdryFormat=(int)lua_todouble(L,3); + break; + + default: + break; + } + + return 0; +} + +int CcdrawDoc::lua_addpointprop(lua_State *L) +{ + CatchNullDocument(); + + CPointProp m; + int n=lua_gettop(L); + + if(n>0) m.PointName.Format("%s",lua_tostring(L,1)); + if(n>1) m.vp=lua_tonumber(L,2); + if(n>2) m.qp=lua_tonumber(L,3); + + ((CcdrawDoc *)pcdrawDoc)->nodeproplist.Add(m); + + return 0; +} + +int CcdrawDoc::lua_modpointprop(lua_State *L) +{ + CatchNullDocument(); + CString PointName; + int k,modprop; + + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + + // find the index of the material to modify; + if (thisDoc->nodeproplist.GetSize()==0) return TRUE; + PointName.Format("%s",lua_tostring(L,1)); + for(k=0;knodeproplist.GetSize();k++) + if(PointName==thisDoc->nodeproplist[k].PointName) break; + + // get out of here if there's no matching material + if(k==thisDoc->nodeproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->nodeproplist[k].PointName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->nodeproplist[k].vp=lua_tonumber(L,3); + break; + case 2: + thisDoc->nodeproplist[k].qp=lua_tonumber(L,3); + break; + default: + break; + } + + return 0; +} + +int CcdrawDoc::lua_addcircuitprop(lua_State *L) +{ + CatchNullDocument(); + + CCircuit m; + int n=lua_gettop(L); + + if(n>0) m.CircName=lua_tostring(L,1); + if(n>1) m.vc=lua_tonumber(L,2); + if(n>2) m.qc=lua_tonumber(L,3); + if(n>3) m.CircType=(int) lua_todouble(L,4); + + ((CcdrawDoc *)pcdrawDoc)->circproplist.Add(m); + + return 0; +} + +int CcdrawDoc::lua_modcircprop(lua_State *L) +{ + CatchNullDocument(); + CString CircName; + int k,modprop; + + CcdrawDoc * thisDoc=(CcdrawDoc *)pcdrawDoc; + + // find the index of the material to modify; + if (thisDoc->circproplist.GetSize()==0) return TRUE; + CircName.Format("%s",lua_tostring(L,1)); + for(k=0;kcircproplist.GetSize();k++) + if(CircName==thisDoc->circproplist[k].CircName) break; + + // get out of here if there's no matching circuit + if(k==thisDoc->circproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->circproplist[k].CircName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->circproplist[k].vc=lua_tonumber(L,3); + break; + case 2: + thisDoc->circproplist[k].qc=lua_tonumber(L,3); + break; + case 3: + thisDoc->circproplist[k].CircType=(int) lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CcdrawDoc::lua_delcircuitprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CcdrawDoc * thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;icircproplist.GetSize();i++) + { + if (thisDoc->circproplist[i].CircName==name) + thisDoc->circproplist.RemoveAt(i); + + } + + return 0; +} + +int CcdrawDoc::lua_delmatprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;iblockproplist.GetSize();i++) + { + if (thisDoc->blockproplist[i].BlockName==name) + thisDoc->blockproplist.RemoveAt(i); + + } + + return 0; +} + + +int CcdrawDoc::lua_delboundprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;ilineproplist.GetSize();i++) + { + if (thisDoc->lineproplist[i].BdryName==name) + thisDoc->lineproplist.RemoveAt(i); + } + + + return 0; +} + +int CcdrawDoc::lua_delpointprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CcdrawDoc *thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;inodeproplist.GetSize();i++) + { + if (thisDoc->nodeproplist[i].PointName==name) + thisDoc->nodeproplist.RemoveAt(i); + } + + return 0; +} + +int CcdrawDoc::lua_updatewindow(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CDC tempDC; + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // force redraw + theView->OnDraw(pDC); + + return 0; +} + + +int CcdrawDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + return 0; +} + + +PBITMAPINFO CcdrawDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy1"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits != 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CcdrawDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy2"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy3"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy4"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy5"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy6"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy7"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy8"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + + +int CcdrawDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CcdrawDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CcdrawDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CcdrawDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CcdrawDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->InvalidateRect(NULL); + + return 0; +} + +int CcdrawDoc::lua_shownames(lua_State * L) +{ + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +void CcdrawView::lnuMakeMesh() +{ + OnMakeMesh(); +} + +void CcdrawView::lnu_purge_mesh() +{ + OnPurgemesh(); +} + +void CcdrawView::lnu_show_mesh() +{ + OnShowMesh(); +} + +void CcdrawView::lnu_analyze(int bShow) +{ + if (bShow>0) bLinehook=HiddenLua; + else bLinehook=NormalLua; + OnMenuAnalyze(); +} + +void CcdrawView::lua_zoomnatural() +{ + OnZoomNatural(); +} + +void CcdrawView::lua_zoomout() +{ + OnZoomOut(); +} + +void CcdrawView::lua_zoomin() +{ + OnZoomIn(); +} + +int CcdrawDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CcdrawDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CcdrawDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CcdrawDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int CcdrawDoc::lua_defineouterspace(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + int n=lua_gettop(L); + if (n!=3) return 0; + + thisDoc->extZo = fabs(lua_todouble(L,1)); + thisDoc->extRo = fabs(lua_todouble(L,2)); + thisDoc->extRi = fabs(lua_todouble(L,3)); + + if((thisDoc->extRo==0) || (thisDoc->extRi==0)) + { + thisDoc->extZo = 0; + thisDoc->extRo = 0; + thisDoc->extRi = 0; + } + + return 0; +} + +int CcdrawDoc::lua_attachouterspace(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=TRUE; + + return 0; +} + +int CcdrawDoc::lua_detachouterspace(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=FALSE; + + return 0; +} + +int CcdrawDoc::lua_createradius(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + CcdrawView * theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n!=3) return 0; + + double x,y,r; + int k; + + x = lua_todouble(L,1); + y = lua_todouble(L,2); + r = fabs(lua_todouble(L,3)); + + if ((k=thisDoc->ClosestNode(x,y))<0) return 0; // catch case where no nodes have been drawn yet; + + if (thisDoc->CanCreateRadius(k)==FALSE) + { + CString msg; + msg.Format("The specified point is not suitable for conversion into a radius"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + if (thisDoc->CreateRadius(k,r)) + { + theView->InvalidateRect(NULL); + theView->MeshUpToDate=FALSE; + } + else{ + CString msg; + msg.Format("Could not make a radius of the prescribed dimension"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + return 0; +} + +int CcdrawDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + +int CcdrawDoc::lua_setgroup(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + int grp,i; + + int n=lua_gettop(L); + + if (n>0) grp =(int) lua_todouble(L,1); + else return 0; + + for(i=0;inodelist.GetSize();i++) + if(thisDoc->nodelist[i].IsSelected==TRUE) + thisDoc->nodelist[i].InGroup=grp; + + for(i=0;ilinelist.GetSize();i++) + if(thisDoc->linelist[i].IsSelected==TRUE) + thisDoc->linelist[i].InGroup=grp; + + for(i=0;iarclist.GetSize();i++) + if(thisDoc->arclist[i].IsSelected==TRUE) + thisDoc->arclist[i].InGroup=grp; + + for(i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].InGroup=grp; + + thisDoc->UnselectAll(); + + return 0; +} + +int CcdrawDoc::lua_getmaterial(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + CString matname; + int n=lua_gettop(L); + + if (n>0) matname=lua_tostring(L,1); + else return 0; + + CString LibName=thisDoc->BinDir+"condlib.dat"; + + FILE *fp; + int i,k; + char s[1024],q[1024]; + char *v; + + CMaterialProp MProp; + + if ((fp=fopen(LibName,"rt"))==NULL){ + CString msg; + msg.Format("Couldn't open %s",LibName); + lua_error(L,msg.GetBuffer(1)); + return FALSE; + } + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + if (sscanf(s,"%s",q)==EOF) q[0]=NULL; + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.ex=1.; + MProp.ey=1.; + MProp.ox=0.; + MProp.oy=0.; + MProp.ltx=0.; + MProp.lty=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.ox); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.oy); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ltx); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.lty); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + if (MProp.BlockName==matname){ + thisDoc->blockproplist.Add(MProp); + fclose(fp); + return 0; + } + q[0]=NULL; + } + } + + fclose(fp); + + CString msg; + msg.Format("Couldn't load \"%s\" from the materials library",matname); + lua_error(L,msg.GetBuffer(1)); + return FALSE; +} + +int CcdrawDoc::lua_attachdefault(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0,j=0;iblocklist.GetSize();i++) + { + if ((thisDoc->blocklist[i].IsSelected==TRUE) && (j==0)) + { + thisDoc->blocklist[i].IsDefault=2; + j++; + } + else thisDoc->blocklist[i].IsDefault=FALSE; + } + + return 0; +} + +int CcdrawDoc::lua_detachdefault(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsDefault=FALSE; + + return 0; +} + +int CcdrawDoc::lua_getprobleminfo(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Depth); + switch (thisDoc->LengthUnits) + { + case 1: // mm + lua_pushnumber(L,0.001); + break; + case 2: // cm + lua_pushnumber(L,0.01); + break; + case 3: // m + lua_pushnumber(L,1.0); + break; + case 4: // mils + lua_pushnumber(L,2.54e-05); + break; + case 5: // um + lua_pushnumber(L,1.0e-06); + break; + default:// inches + lua_pushnumber(L,0.0254); + break; + } + return 3; +} + +int CcdrawDoc::lua_getboundingbox(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc *thisDoc; + CcdrawView *theView; + thisDoc=(CcdrawDoc *)pcdrawDoc; + + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcdrawView *)thisDoc->GetNextView(pos); + + double x[2],y[2]; + if (theView->GetBoundingBox(x,y)) + { + lua_pushnumber(L,x[0]); + lua_pushnumber(L,x[1]); + lua_pushnumber(L,y[0]); + lua_pushnumber(L,y[1]); + return 4; + } + else return 0; +} + +int CcdrawDoc::lua_selectcircle(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * pDoc; + CcdrawView * theView; + + pDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CcdrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double R; + CComplex c,q; + + n=lua_gettop(L); + if (n<3) return 0; + c=lua_tonumber(L,1)+I*lua_tonumber(L,2); + R=lua_todouble(L,3); + if (n>3) EditAction=(int) lua_todouble(L,4); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} + +int CcdrawDoc::lua_selectrectangle(lua_State *L) +{ + CatchNullDocument(); + CcdrawDoc * pDoc; + CcdrawView * theView; + + pDoc=(CcdrawDoc *)pcdrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CcdrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double mx,my,wzx,wzy,x,y,z; + + n=lua_gettop(L); + if (n<4) return 0; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + wzx=lua_todouble(L,3); + wzy=lua_todouble(L,4); + if (n>4) EditAction=(int) lua_todouble(L,5); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} \ No newline at end of file diff --git a/femm/CD_PREF.CPP b/femm/CD_PREF.CPP new file mode 100644 index 0000000..284925b --- /dev/null +++ b/femm/CD_PREF.CPP @@ -0,0 +1,424 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "cd_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define SelColor clist[0] +#define MeshColor clist[1] +#define BlockColor clist[2] +#define LineColor clist[3] +#define GridColor clist[4] +#define NodeColor clist[5] +#define BackColor clist[6] +#define NameColor clist[7] + +///////////////////////////////////////////////////////////////////////////// +// cdCPref dialog + + +cdCPref::cdCPref(CWnd* pParent /*=NULL*/) + : CDialog(cdCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCPref) + m_d_gridsize = 0.25; + m_d_pixels = 100.0; + m_d_prec = 1.e-8; + m_d_minangle = DEFAULT_MINIMUM_ANGLE; + m_d_depth = 1.0; + m_d_frequency = 60; + m_d_showgrid = TRUE; + m_d_snapgrid = FALSE; + m_d_showorigin = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + s_action=0; + s_coord=0; + s_length=0; + s_type=0; + + clist=(COLORREF *)calloc(16,sizeof(COLORREF)); + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; +} + +cdCPref::~cdCPref() +{ + free(clist); +} + +void cdCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCPref) + DDX_Control(pDX, IDC_CD_DCOLOR, m_d_color); + DDX_Control(pDX, IDC_CD_DTYPE, m_d_type); + DDX_Control(pDX, IDC_CD_DLENGTH, m_d_length); + DDX_Control(pDX, IDC_CD_DCOORD, m_d_coord); + DDX_Control(pDX, IDC_CD_DACTION, m_d_action); + DDX_Text(pDX, IDC_CD_DGRIDSIZE, m_d_gridsize); + DDX_Text(pDX, IDC_CD_DDEPTH2, m_d_depth); + DDX_Text(pDX, IDC_CD_DFREQUENCY, m_d_frequency); + DDX_Text(pDX, IDC_CD_DPIXELS, m_d_pixels); + DDX_Text(pDX, IDC_CD_DPREC, m_d_prec); + DDV_MinMaxDouble(pDX, m_d_prec, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_CD_DMINANGLE, m_d_minangle); + DDV_MinMaxDouble(pDX, m_d_minangle, 1., MINANGLE_MAX); + DDX_Check(pDX, IDC_CD_DSHOWGRID, m_d_showgrid); + DDX_Check(pDX, IDC_CD_DSNAPGRID, m_d_snapgrid); + DDX_Check(pDX, IDC_CD_SHOW_ORIGIN, m_d_showorigin); + DDX_Check(pDX, IDC_CD_SHOW_NAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_DGRIDSIZE, m_IDC_d_gridsize); + DDX_Control(pDX, IDC_CD_DPIXELS, m_IDC_d_pixels); + DDX_Control(pDX, IDC_CD_DPREC, m_IDC_d_prec); + DDX_Control(pDX, IDC_CD_DFREQUENCY, m_IDC_d_frequency); + DDX_Control(pDX, IDC_CD_DDEPTH2, m_IDC_d_depth); +} + + +BEGIN_MESSAGE_MAP(cdCPref, CDialog) + //{{AFX_MSG_MAP(cdCPref) + ON_BN_CLICKED(IDC_CD_MODBTN, OnModifyButton) + ON_BN_CLICKED(IDC_CD_RESTORE, OnRestoreColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCPref message handlers + +void cdCPref::OnModifyButton() +{ + CColorDialog dlg; + int i; + + UpdateData(); + i=m_d_color.GetCurSel(); + + dlg.m_cc.lpCustColors=clist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + else{ + } + +} + +BOOL cdCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_action.SetCurSel(s_action); + m_d_coord.SetCurSel(s_coord); + m_d_length.SetCurSel(s_length); + m_d_type.SetCurSel(s_type); + m_d_color.SetCurSel(0); + + UpdateData(FALSE); + + return TRUE; +} + + +void cdCPref::OnOK() +{ + UpdateData(); + + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + CDialog::OnOK(); +} + +void cdCPref::OnRestoreColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; + } +} + +BOOL cdCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +char* StripKey(char *c); + +void cdCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "cdraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_prec); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_minangle); + q[0]=NULL; + } + + if( _strnicmp(q,"",7)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_depth); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_frequency); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_coord); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_length); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_type); + q[0]=NULL; + } + + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_pixels); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_shownames); + q[0]=NULL; + } + } + fclose(fp); + } +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void cdCPref::WritePrefs() +{ + FILE *fp; + CString fname; + + UpdateData(); + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + fname=((CFemmApp *)AfxGetApp())->GetExecutablePath()+"cdraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",s_action); + fprintf(fp," = %g\n",m_d_pixels); + fprintf(fp," = %g\n",m_d_gridsize); + fprintf(fp," = %i\n",m_d_showgrid); + fprintf(fp," = %i\n",m_d_snapgrid); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_showorigin); + fprintf(fp," = %i\n",s_type); + fprintf(fp," = %i\n",s_length); + fprintf(fp," = %g\n",m_d_prec); + fprintf(fp," = %g\n",m_d_minangle); + fprintf(fp," = %g\n",m_d_depth); + fprintf(fp," = %g\n",m_d_frequency); + fprintf(fp," = %i\n",s_coord); + + fclose(fp); + } +} diff --git a/femm/CD_PREF.H b/femm/CD_PREF.H new file mode 100644 index 0000000..bd92e0d --- /dev/null +++ b/femm/CD_PREF.H @@ -0,0 +1,69 @@ +// cd_Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cdCPref dialog + +class cdCPref : public CDialog +{ +// Construction +public: + + cdCPref(CWnd* pParent = NULL); // standard constructor + ~cdCPref(); + + COLORREF *clist; + int s_action; + int s_coord; + int s_length; + int s_type; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(cdCPref) + enum { IDD = IDD_CD_PREF }; + CComboBox m_d_color; + CComboBox m_d_type; + CComboBox m_d_length; + CComboBox m_d_coord; + CComboBox m_d_action; + double m_d_gridsize; + double m_d_pixels; + double m_d_prec; + double m_d_minangle; + double m_d_depth; + double m_d_frequency; + BOOL m_d_showgrid; + BOOL m_d_snapgrid; + BOOL m_d_showorigin; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCPref) + afx_msg void OnModifyButton(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnRestoreColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_d_gridsize, m_IDC_d_depth,m_IDC_d_frequency; + CLuaEdit m_IDC_d_pixels, m_IDC_d_prec, m_IDC_d_minangle; + +}; diff --git a/femm/COMPLEX.H b/femm/COMPLEX.H new file mode 100644 index 0000000..3bea33a --- /dev/null +++ b/femm/COMPLEX.H @@ -0,0 +1,140 @@ +#ifndef CCOMPLEX +#define CCOMPLEX + +#define PI 3.141592653589793238462643383 +#define SmallNo 1.e-14 +#define DEG 0.01745329251994329576923690768 + +class CComplex +{ + public: + // data members + double re,im; + + // member functions + CComplex(); + CComplex(double x); + CComplex(int x); + CComplex(double x, double y); + CComplex Sqrt(); + CComplex Conj(); + CComplex Inv(); + void Set(double x, double y); + double Abs(); + double Arg(); + double Re(); + double Im(); + char* ToString(char *s); + char* ToStringAlt(char *s); + + //operator redefinition + //Addition + CComplex operator+( const CComplex& z ); + CComplex operator+(double z); + CComplex operator+(int z); + friend CComplex operator+( int x, const CComplex& y ); + friend CComplex operator+( double x, const CComplex& y ); + friend CComplex operator+( const CComplex& x, const CComplex& y ); + void operator+=( const CComplex& z); + void operator+=(double z); + void operator+=(int z); + + //Subtraction + CComplex operator-(); + CComplex operator-( const CComplex& z ); + CComplex operator-(double z); + CComplex operator-(int z); + friend CComplex operator-( int x, const CComplex& y ); + friend CComplex operator-( double x, const CComplex& y ); + friend CComplex operator-( const CComplex& x, const CComplex& y ); + friend CComplex operator-( const CComplex& x ); + void operator-=( const CComplex& z); + void operator-=(double z); + void operator-=(int z); + + //Multiplication + CComplex operator*( const CComplex& z ); + CComplex operator*(double z); + CComplex operator*(int z); + friend CComplex operator*( int x, const CComplex& y ); + friend CComplex operator*( double x, const CComplex& y ); + friend CComplex operator*( const CComplex& x, const CComplex& y ); + void operator*=( const CComplex& z); + void operator*=(double z); + void operator*=(int z); + + //Division + CComplex operator/( const CComplex& z ); + CComplex operator/(double z); + CComplex operator/(int z); + friend CComplex operator/( int x, const CComplex& y ); + friend CComplex operator/( double x, const CComplex& y ); + friend CComplex operator/( const CComplex &x, const CComplex& y ); + void operator/=( const CComplex& z); + void operator/=(double z); + void operator/=(int z); + + //Equals + void operator=(double z); + void operator=(int z); + + //Tests + bool operator==( const CComplex& z); + bool operator==(double z); + bool operator==(int z); + + bool operator!=( const CComplex& z); + bool operator!=(double z); + bool operator!=(int z); + + bool operator<( const CComplex& z); + bool operator<( double z); + bool operator<( int z); + + bool operator<=( const CComplex& z); + bool operator<=( double z); + bool operator<=( int z); + + bool operator>( const CComplex& z); + bool operator>( double z); + bool operator>( int z); + + bool operator>=( const CComplex& z); + bool operator>=( double z); + bool operator>=( int z); + + + private: + +}; + +// useful functions... +#define I CComplex(0,1) +double Re( const CComplex& a); +double Im( const CComplex& a); +double abs( const CComplex& x ); +double absq( const CComplex& x ); +double arg( const CComplex& x ); +CComplex conj( const CComplex& x); +CComplex exp( const CComplex& x ); +CComplex sqrt( const CComplex& x ); +CComplex tanh( const CComplex& x ); +CComplex sinh( const CComplex& x ); +CComplex cosh( const CComplex& x ); +CComplex cos( const CComplex& x ); +CComplex acos( const CComplex& x ); +CComplex sin( const CComplex& x ); +CComplex asin( const CComplex& x ); +CComplex tan( const CComplex& x ); +CComplex atan( const CComplex& x ); +CComplex atan2( const CComplex& y, const CComplex& x); +CComplex log( const CComplex& x ); +CComplex pow( const CComplex& x, int y); +CComplex pow( const CComplex& x, double y); +CComplex pow( const CComplex& x, const CComplex& y); +CComplex Chop( const CComplex& a, double tol=1.e-12); + + + + +#endif // CCOMPLEX check \ No newline at end of file diff --git a/femm/CPlotDlg.cpp b/femm/CPlotDlg.cpp new file mode 100644 index 0000000..fef2ac3 --- /dev/null +++ b/femm/CPlotDlg.cpp @@ -0,0 +1,67 @@ +// CPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "CPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCPlotDlg dialog + + +CCPlotDlg::CCPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(CCPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCPlotDlg) + m_numcontours = 0; + m_showai = FALSE; + m_showar = FALSE; + m_ahigh = 0.0; + m_alow = 0.0; + m_showmask = FALSE; + //}}AFX_DATA_INIT +} + + +void CCPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCPlotDlg) + DDX_Text(pDX, IDC_NUMCONTOURS, m_numcontours); + DDV_MinMaxInt(pDX, m_numcontours, 4, 999); + DDX_Check(pDX, IDC_SHOW_A_IM, m_showai); + DDX_Check(pDX, IDC_SHOW_A_RE, m_showar); + DDX_Text(pDX, IDC_AHIGH, m_ahigh); + DDX_Text(pDX, IDC_ALOW, m_alow); + DDX_Check(pDX, IDC_SHOW_MASK1, m_showmask); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_NUMCONTOURS, m_IDC_numcontours); + DDX_Control(pDX, IDC_AHIGH, m_IDC_ahigh); + DDX_Control(pDX, IDC_ALOW, m_IDC_alow); +} + + +BEGIN_MESSAGE_MAP(CCPlotDlg, CDialog) + //{{AFX_MSG_MAP(CCPlotDlg) + ON_BN_CLICKED(IDC_DFLT1, OnDflt1) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCPlotDlg message handlers + +void CCPlotDlg::OnDflt1() +{ + // TODO: Add your control notification handler code here + UpdateData(TRUE); + m_alow=Alb; + m_ahigh=Aub; + m_numcontours=19; + UpdateData(FALSE); +} diff --git a/femm/CPlotDlg.h b/femm/CPlotDlg.h new file mode 100644 index 0000000..fa25574 --- /dev/null +++ b/femm/CPlotDlg.h @@ -0,0 +1,43 @@ +// CPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCPlotDlg dialog + +class CCPlotDlg : public CDialog +{ +// Construction +public: + CCPlotDlg(CWnd* pParent = NULL); // standard constructor + double Alb,Aub; + +// Dialog Data + //{{AFX_DATA(CCPlotDlg) + enum { IDD = IDD_CPLOTDLG }; + int m_numcontours; + BOOL m_showai; + BOOL m_showar; + double m_ahigh; + double m_alow; + BOOL m_showmask; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCPlotDlg) + afx_msg void OnDflt1(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_numcontours, m_IDC_ahigh, m_IDC_alow; +}; diff --git a/femm/CVIEWDOC.CPP b/femm/CVIEWDOC.CPP new file mode 100644 index 0000000..e696275 --- /dev/null +++ b/femm/CVIEWDOC.CPP @@ -0,0 +1,2478 @@ +// cviewDoc.cpp : implementation of the CcviewDoc class +// + + +#include "stdafx.h" +#include +#include +#include "cv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "cviewDoc.h" +#include "cviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#define AXISYMMETRIC 1 + +extern lua_State * lua; +extern void *pcviewDoc; +extern BOOL bLinehook; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CcviewDoc + +IMPLEMENT_DYNCREATE(CcviewDoc, CDocument) + +BEGIN_MESSAGE_MAP(CcviewDoc, CDocument) + //{{AFX_MSG_MAP(CcviewDoc) + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CcviewDoc construction/destruction + +double sqr(double x); + +CcviewDoc::CcviewDoc() +{ + // set some default values for problem definition + d_LineIntegralPoints=400; + Depth=1/0.0254; + Frequency=0; + LengthUnits=0; + ProblemType=FALSE; + ProblemNote="Add comments here."; + FirstDraw=-1; + A_High=0.; + A_Low=0.; + A_lb=0.; + A_ub=0.; + extRo=extRi=extZo=0; + Smooth=TRUE; + NumList=NULL; + ConList=NULL; + bHasMask=FALSE; + LengthConv=(double *)calloc(6,sizeof(double)); + LengthConv[0]=0.0254; //inches + LengthConv[1]=0.001; //millimeters + LengthConv[2]=0.01; //centimeters + LengthConv[3]=1.; //meters + LengthConv[4]=2.54e-05; //mils + LengthConv[5]=1.e-06; //micrometers + Coords=FALSE; + + for(int i=0;i<9;i++) + d_PlotBounds[i][0]=d_PlotBounds[i][1]= + PlotBounds[i][0]=PlotBounds[i][1]=0; + + // determine path to bin directory + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // lua initialization stuff + initalise_lua(); +} + +CcviewDoc::~CcviewDoc() +{ + int i; + free(LengthConv); + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + ProblemNote=v; + 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.V=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.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.qp.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.V; + BProp.c0=0; BProp.c1=0; + BProp.qs=0; + BProp.InConductor=""; + 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,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==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,"",9)==0){ + lineproplist.Add(BProp); + q[0]=NULL; + } + + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.Kx=0; MProp.Ky=0; + MProp.ex=0; MProp.ey=0; + MProp.ox=0; MProp.oy=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.ox); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.oy); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ex.re); + MProp.ex.im=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey.re); + MProp.ey.im=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + double lt; + sscanf(v,"%lf",<); + lt=-atan(lt); + MProp.ex=MProp.ex*exp(I*lt); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + double lt; + sscanf(v,"%lf",<); + lt=-atan(lt); + MProp.ey=MProp.ey*exp(I*lt); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + MProp.Kx=MProp.ox+I*2.*PI*Frequency*MProp.ex*eo; + MProp.Ky=MProp.oy+I*2.*PI*Frequency*MProp.ey*eo; + blockproplist.Add(MProp); + q[0]=NULL; + } + + // Circuit Properties + if( _strnicmp(q,"",16)==0){ + CProp.CircName="New Circuit"; + CProp.V=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,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V.im); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.q.re); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.q.im); + 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) asegm.MaxSideLength=b; + arclist.Add(asegm); + } + q[0]=NULL; + } + + + // read in list of holes; + if(_strnicmp(q,"[numholes]",13)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) + { + blk.BlockType=-1; + blk.MaxArea=0; + for(i=0;imeshelem[i].rsqr) meshelem[i].rsqr=b; + } + } + + // Find flux density in each element; + for(i=0;iA_High) A_High=abs(meshnode[i].v); + if (abs(meshnode[i].v)Re(A_ub)) A_ub.re=Re(meshnode[i].v); + if (Re(meshnode[i].v)Im(A_ub)) A_ub.im=Im(meshnode[i].v); + if (Im(meshnode[i].v)arg(u1)) + { + swa=ConList[i][k]; + ConList[i][k]=ConList[i][k+1]; + ConList[i][k+1]=swa; + flg=TRUE; + } + } + if(!flg) j=NumList[i]; + } + } + + // Postprocess to get smoothed nodal values of current + for(i=0;id_PlotBounds[3][1]) d_PlotBounds[3][1]=b; + if(bd_PlotBounds[4][1]) d_PlotBounds[4][1]=b; + if(bd_PlotBounds[5][1]) d_PlotBounds[5][1]=b; + if(bd_PlotBounds[6][1]) d_PlotBounds[6][1]=b; + if(bd_PlotBounds[7][1]) d_PlotBounds[7][1]=b; + if(bd_PlotBounds[8][1]) d_PlotBounds[8][1]=b; + if(b=0) + { + if(meshelem[i].lbl!=k) + { + blocklist[meshelem[i].lbl].IsSelected=TRUE; + if (!bMultiplyDefinedLabels) + { + CString msg; + msg ="Some regions in the problem have been defined\n"; + msg+="by more than one block label. These potentially\n"; + msg+="problematic regions will appear as selected in\n"; + msg+="the initial view."; + MsgBox(msg); + bMultiplyDefinedLabels=TRUE; + } + } + } + } + + + FirstDraw=TRUE; + + return TRUE; +} + +int CcviewDoc::InTriangle(double x, double y) +{ + static int k; + int j,hi,lo,sz; + double z; + + sz=(int) meshelem.GetSize(); + if((k<0) || (k>=sz)) k=0; + + // In most applications, the triangle we're looking + // for is nearby the last one we found. Since the elements + // are ordered in a banded structure, we want to check the + // elements nearby the last one selected first. + if (InTriangleTest(x,y,k)) return k; + + hi=k;lo=k; + + for(j=0;j=sz) hi=0; + lo--; if(lo<0) lo=sz-1; + + z=(meshelem[hi].ctr.re-x)*(meshelem[hi].ctr.re-x) + + (meshelem[hi].ctr.im-y)*(meshelem[hi].ctr.im-y); + if(z<=meshelem[hi].rsqr) + { + if(InTriangleTest(x,y,hi)) + { + k=hi; + return k; + } + } + + z=(meshelem[lo].ctr.re-x)*(meshelem[lo].ctr.re-x) + + (meshelem[lo].ctr.im-y)*(meshelem[lo].ctr.im-y); + if(z<=meshelem[lo].rsqr) + { + if(InTriangleTest(x,y,lo)) + { + k=lo; + return k; + } + } + + } + + return (-1); +} + +BOOL CcviewDoc::GetPointValues(double x, double y, CPointVals &u) +{ + int k; + k=InTriangle(x,y); + if (k<0) return FALSE; + GetPointValues(x,y,k,u); + return TRUE; +} + +BOOL CcviewDoc::GetPointValues(double x, double y, int k, CPointVals &u) +{ + int i,n[3]; + double a[3],b[3],c[3],da,ravg,aecf; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + ravg=LengthConv[LengthUnits]* + (meshnode[n[0]].x + meshnode[n[1]].x + meshnode[n[2]].x)/3.; + + GetPointJ(x,y,u.Jx,u.Jy,meshelem[k]); + + u.v=0; u.Jx=0; u.Jy=0; + for(i=0;i<3;i++){ + // voltage + u.v +=meshnode[n[i]].v*(a[i]+b[i]*x+c[i]*y)/(da); + + // total current density + if(Smooth==TRUE) + { + u.Jx +=meshelem[k].jx[i]*(a[i]+b[i]*x+c[i]*y)/(da); + u.Jy +=meshelem[k].jy[i]*(a[i]+b[i]*x+c[i]*y)/(da); + } + } + if (Smooth==FALSE){ + u.Jx=meshelem[k].Jx; + u.Jx=meshelem[k].Jx; + } + + // ac conductivity + aecf=AECF(k,x+I*y); + u.Kx=blockproplist[meshelem[k].blk].Kx/aecf; + u.Ky=blockproplist[meshelem[k].blk].Ky/aecf; + + // electric field intensity + u.Ex = u.Jx/(u.Kx); + u.Ey = u.Jy/(u.Ky); + + // electrical permittivity + u.ex = blockproplist[meshelem[k].blk].ex/aecf; + u.ey = blockproplist[meshelem[k].blk].ey/aecf; + + // electric flux density + u.Dx = u.Ex*u.ex*eo; + u.Dy = u.Ey*u.ey*eo; + + // displacement current density + u.Jdx = u.Dx*I*2.*PI*Frequency; + u.Jdy = u.Dy*I*2.*PI*Frequency; + + // conductivity + u.ox = blockproplist[meshelem[k].blk].ox/aecf; + u.oy = blockproplist[meshelem[k].blk].oy/aecf; + + // conduction current density + u.Jcx = u.Ex*u.ox; + u.Jcy = u.Ey*u.oy; + + return TRUE; +} + +void CcviewDoc::GetPointJ(double x, double y, CComplex &Jx, CComplex &Jy, CElement &elm) +{ + // elm is a reference to the element that contains the point of interest. + int i,n[3]; + double da,a[3],b[3],c[3]; + + if(Smooth==FALSE){ + Jx=elm.Jx; + Jy=elm.Jy; + return; + } + + for(i=0;i<3;i++) n[i]=elm.p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,Jx=0,Jy=0;i<3;i++){ + Jx+=(elm.jx[i]*(a[i]+b[i]*x+c[i]*y)/da); + Jy+=(elm.jy[i]*(a[i]+b[i]*x+c[i]*y)/da); + } +} + +BOOL CcviewDoc::IsSameMaterial(int e1, int e2) +{ + int b1,b2; + + b1=meshelem[e1].blk; + b2=meshelem[e2].blk; + + // Are the same material trivially if they are the same block type + if (b1==b2) return TRUE; + + // If the materials have the same Kx and Ky, we + // can say that they are the same material; + if ((blockproplist[b1].Kx==blockproplist[b2].Kx) && + (blockproplist[b1].Ky==blockproplist[b2].Ky)) return TRUE; + + return FALSE; +} + +void CcviewDoc::GetNodalJ(CComplex *xd, CComplex *yd, int N) +{ + int i,j,k,n,m,p,eos,nos,qn; + int lf,rt; + double xi,yi,ii,xx,xy,yy,dx,dy,det; + CComplex dv,iv,xv,yv,Ex,Ey; + static int q[21]; + CComplex kn; + BOOL flag; + + for(i=0;i<3;i++) + { + j=meshelem[N].p[i]; + lf=rt=-1; + flag=FALSE; + for(eos=0;eos2) nos=0; + p=meshelem[n].p[nos]; + + // add this node to the list. We can have a max of 20 nodes, + // which should never actually occur (usually about 6 to 8) + if (qn<20) q[qn++]=p; + + // if this node has a fixed definition, get out of the loop; + if((meshnode[j].Q!=-2) &&(meshnode[p].Q!=-2)){ + lf=p; + break; + } + + m--; if(m<0) m=NumList[j]-1; + } + + // catch some annoying special cases; + if ((lf==rt) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is at the end of a conductor; not much to + // do but punt; + xd[i]=meshelem[N].Jx; + yd[i]=meshelem[N].Jy; + flag=TRUE; + } + else if ((rt!=-1) && (meshnode[j].Q!=-2) && (lf==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + xd[i]=meshelem[N].Jx; + yd[i]=meshelem[N].Jy; + flag=TRUE; + } + else if ((lf!=-1) && (meshnode[j].Q!=-2) && (rt==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + xd[i]=meshelem[N].Jx; + yd[i]=meshelem[N].Jy; + flag=TRUE; + } + else if((lf==-1) && (rt==-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is an isolated charge. Again, not much to + // do but punt; + xd[i]=meshelem[N].Jx; + yd[i]=meshelem[N].Jy; + flag=TRUE; + } + else if((lf!=-1) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + + // The node of interest is on some boundary where the charge is fixed. + // if the angle is shallow enough, we can just do the regular thing; + // Otherwise, we punt. + CComplex x,y; + x=meshnode[lf].CC()-meshnode[j].CC(); x/=abs(x); + y=meshnode[j].CC()-meshnode[rt].CC(); y/=abs(y); + if(fabs(arg(x/y))>10.0001*PI/180.) + { + // if the angle is greater than 10 degrees, punt; + xd[i]=meshelem[N].Jx; + yd[i]=meshelem[N].Jy; + flag=TRUE; + } + } + + if(flag==FALSE) + { + // The nominal case. + // Fit a plane through the nodes in the list to solve for E. + // Then, multiply by permittivity to get D. + xi=yi=ii=xx=xy=yy=0; + iv=0; xv=0; yv=0; + + q[qn++]=j; + + for(k=0;k0) + { + OnNewDocument(); + SetPathName(pname,FALSE); + OnOpenDocument(pname); + } +} + +int CcviewDoc::ClosestNode(double x, double y) +{ + int i,j; + double d0,d1; + + if(nodelist.GetSize()==0) return -1; + + j=0; + d0=nodelist[0].GetDistance(x,y); + for(i=0;iq[k]) && (k<(contour.GetSize()-1))) k++; + u=(z-q[k-1])/(q[k]-q[k-1]); + pt=contour[k-1]+u*(contour[k]-contour[k-1]); + t=contour[k]-contour[k-1]; + t/=abs(t); + n = I*t; + pt+=(n*1.e-06); + + if (elm<0) elm=InTriangle(pt.re,pt.im); + else if (InTriangleTest(pt.re,pt.im,elm)==FALSE) + { + flag=FALSE; + for(j=0;j<3;j++) + for(m=0;m=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + p.M[i][0]=z; + if(flag!=FALSE) + { + switch (PlotType) + { + case 0: + p.M[i][1]=abs(v.v); + p.M[i][2]=Re(v.v); + p.M[i][3]=Im(v.v); + break; + case 1: + p.M[i][1]=abs(abs(v.Jx)+I*abs(v.Jy)); + break; + case 2: + yr=Re(v.Jx)+I*Re(v.Jy); + yi=Im(v.Jx)+I*Im(v.Jy); + p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); + p.M[i][2]=Re(yr/n); + p.M[i][3]=Re(yi/n); + break; + case 3: + yr=Re(v.Jx)+I*Re(v.Jy); + yi=Im(v.Jx)+I*Im(v.Jy); + p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); + p.M[i][2]=Re(yr/t); + p.M[i][3]=Re(yi/t); + break; + case 4: + p.M[i][1]=abs(abs(v.Jx/v.Kx)+I*abs(v.Jy/v.Ky)); + break; + case 5: + yr=Re(v.Jx/v.Kx)+I*Re(v.Jy/v.Ky); + yi=Im(v.Jx/v.Kx)+I*Im(v.Jy/v.Ky); + p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); + p.M[i][2]=Re(yr/n); + p.M[i][3]=Re(yi/n); + break; + case 6: + yr=Re(v.Jx/v.Kx)+I*Re(v.Jy/v.Ky); + yi=Im(v.Jx/v.Kx)+I*Im(v.Jy/v.Ky); + p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); + p.M[i][2]=Re(yr/t); + p.M[i][3]=Re(yi/t); + break; + case 7: + p.M[i][1]=abs(abs(v.Jcx)+I*abs(v.Jcy)); + break; + case 8: + yr=Re(v.Jcx)+I*Re(v.Jcy); + yi=Im(v.Jcx)+I*Im(v.Jcy); + p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); + p.M[i][2]=Re(yr/n); + p.M[i][3]=Re(yi/n); + break; + case 9: + yr=Re(v.Jcx)+I*Re(v.Jcy); + yi=Im(v.Jcx)+I*Im(v.Jcy); + p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); + p.M[i][2]=Re(yr/t); + p.M[i][3]=Re(yi/t); + break; + case 10: + p.M[i][1]=abs(abs(v.Jdx)+I*abs(v.Jdy)); + break; + case 11: + yr=Re(v.Jdx)+I*Re(v.Jdy); + yi=Im(v.Jdx)+I*Im(v.Jdy); + p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); + p.M[i][2]=Re(yr/n); + p.M[i][3]=Re(yi/n); + break; + case 12: + yr=Re(v.Jdx)+I*Re(v.Jdy); + yi=Im(v.Jdx)+I*Im(v.Jdy); + p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); + p.M[i][2]=Re(yr/t); + p.M[i][3]=Re(yi/t); + break; + default: + p.M[i][1]=0; + break; + } + } + } + + free(q); +} + +BOOL CcviewDoc::InTriangleTest(double x, double y, int i) +{ + if ((i<0) || (i>=meshelem.GetSize())) return FALSE; + + int j,k; + double z; + + for(j=0;j<3;j++) + { + k=j+1; if(k==3) k=0; + // Case 1: p[k]>p[j] + if (meshelem[i].p[k] > meshelem[i].p[j]) + { + z=(meshnode[meshelem[i].p[k]].x-meshnode[meshelem[i].p[j]].x)* + (y-meshnode[meshelem[i].p[j]].y) - + (meshnode[meshelem[i].p[k]].y-meshnode[meshelem[i].p[j]].y)* + (x-meshnode[meshelem[i].p[j]].x); + if(z<0) return FALSE; + } + //Case 2: p[k]0) return FALSE; + } + } + + return TRUE; +} + +CPointVals::CPointVals() +{ + v=0; // voltage + Ex=0; Ey=0; // electric field intensity + Dx=0; Dy=0; // electric flux density + Jcx=0; Jcy=0; // conduction current density + Jdx=0; Jdy=0; // displacement current density + Jx=0; Jy=0; // ac current density + Kx=0; Ky=0; // ac conductivity + ox=0; oy=0; // dc conductivity + ex=0; ey=0; // permittivity +} + +CComplex CcviewDoc::Ctr(int i) +{ + CComplex p,c; + int j; + + for(j=0,c=0;j<3;j++){ + p.Set(meshnode[meshelem[i].p[j]].x/3.,meshnode[meshelem[i].p[j]].y/3.); + c+=p; + } + + return c; +} + +double CcviewDoc::ElmArea(int i) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=meshelem[i].p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +double CcviewDoc::ElmArea(CElement *elm) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=elm->p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +CComplex CcviewDoc::HenrotteVector(int k) +{ + int i,n[3]; + double b[3],c[3],da; + CComplex v; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,v=0;i<3;i++) + v-=meshnode[n[i]].msk*(b[i]+I*c[i])/(da*LengthConv[LengthUnits]); // grad + + return v; +} + +CComplex CcviewDoc::BlockIntegral(int inttype) +{ + int i,k; + CComplex c,y,z,Ex,Ey,B1,B2,F1,F2; + double a,R,ex,ey,aecf; + double r[3]; + + for(i=0,z=0;i=6) + { + a=ElmArea(i)*pow(LengthConv[LengthUnits],2.); + if(ProblemType==1){ + for(k=0;k<3;k++) + r[k]=meshnode[meshelem[i].p[k]].x*LengthConv[LengthUnits]; + R=(r[0]+r[1]+r[2])/3.; + a*=(2.*PI*R); + } + else a*=Depth; + + B1=meshelem[i].Jx*eo/(blockproplist[meshelem[i].blk].Kx); + B2=meshelem[i].Jy*eo/(blockproplist[meshelem[i].blk].Ky); + c=HenrotteVector(i); + + switch(inttype){ + + case 6: // x (or r) direction Henrotte force, SS part. + if(ProblemType!=0) break; + + y=(((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + 2.*Re(B1*conj(B2))*Im(c))/(2.*eo); + if(Frequency!=0) y/=2.; + + y*=AECF(i); // correction for axisymmetric external region; + + z+=(a*y); + break; + + case 7: // y (or z) direction Henrotte force, SS part. + + y=(((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + 2.*Re(B1*conj(B2))*Re(c))/(2.*eo); + + y*=AECF(i); // correction for axisymmetric external region; + + if(Frequency!=0) y/=2.; + z+=(a*y); + + break; + + case 8: // x (or r) direction Henrotte force, 2x part. + + if(ProblemType!=0) break; + z+=a*((((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*eo)) * AECF(i); + + break; + + case 9: // y (or z) direction Henrotte force, 2x part. + z+= a*((((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*eo)) * AECF(i); + + break; + + case 10: // Henrotte torque, SS part. + if(ProblemType!=0) break; + + F1 = (((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + + 2.*Re(B1*conj(B2))*Im(c))/(2.*eo); + F2 = (((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + + 2.*Re(B1*conj(B2))*Re(c))/(2.*eo); + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3.; + + y=Re(c)*F2 -Im(c)*F1; + if(Frequency!=0) y/=2.; + y*=AECF(i); + z+=(a*y); + + break; + + case 11: // Henrotte torque, 2x part. + + if(ProblemType!=0) break; + F1 = (((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*eo); + F2 = (((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*eo); + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3; + + z+=a*(Re(c)*F2 -Im(c)*F1)*AECF(i); + + break; + + default: + break; + } + } + } + + return z; +} + +void CcviewDoc::LineIntegral(int inttype, CComplex *z) +{ +// inttype Integral +// 0 E.t +// 1 J.n +// 2 Contour length +// 3 Average Voltage + + z[0]=0; z[1]=0; + + // inttype==0 => E.t + if(inttype==0){ + CPointVals u; + int k; + + k=(int) contour.GetSize(); + GetPointValues(contour[0].re,contour[0].im, u); + z[0] = u.v; + GetPointValues(contour[k-1].re,contour[k-1].im,u); + z[0]-= u.v; + } + + // inttype==1 => J.n + if(inttype==1){ + CComplex n,t,pt,Fn; + CPointVals v; + double dz,u,d; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; z[1]=0; z[2]; z[3]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + Fn = (v.Jx.re+I*v.Jy.re)/n + I*(v.Jx.im+I*v.Jy.im)/n; + + if (ProblemType==AXISYMMETRIC) + d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); + else + d=Depth*LengthConv[LengthUnits]; + + z[0]+=(Fn*dz*d); + z[1]+=dz*d; + } + } + } + z[1]=z[0]/z[1]; // Average J.n over the surface; + } + + // inttype==2 => Contour Length + if(inttype==2){ + int i,k; + k=(int) contour.GetSize(); + for(i=0,z[0]=0;i Average Voltage + if(inttype==3){ + CComplex pt; + CPointVals v; + double dz,u,d; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + z[1]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + if (ProblemType==AXISYMMETRIC) + d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); + else + d=Depth*LengthConv[LengthUnits]; + + z[0]+=(v.v*dz*d); + z[1]+=dz*d; + } + } + } + z[0]=z[0]/z[1]; // Average voltage over the surface; + } + + // inttype==4 => Stress Tensor Force + if(inttype==4){ + CComplex n,t,pt,En,Dn,DE,dF1,dF2; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + for(i=0;i<4;i++) z[i]=0; + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + En=n.re*v.Ex + n.im*v.Ey; + Dn=n.re*v.Dx + n.im*v.Dy; + DE = v.Dx*v.Ex + v.Dy*v.Ey; + dF1 = v.Ex*Dn + v.Dx*En - n.re*DE; + dF2 = v.Ey*Dn + v.Dy*En - n.im*DE; + + dza=dz*LengthConv[LengthUnits]; + if(ProblemType==1){ + dza*=2.*PI*pt.re*LengthConv[LengthUnits]; + dF1=0; + } + else dza*=Depth; + + z[0]+=(dF1*dza/4.); + z[1]+=(dF2*dza/4.); + + DE = v.Dx*v.Ex.Conj() +v.Dy*v.Ey.Conj(); + + if (ProblemType!=1) + dF1 = v.Ex*Dn.Conj() + v.Dx*En.Conj() - n.re*DE; + dF2= v.Ey*Dn.Conj() + v.Dy*En.Conj() - n.im*DE; + + + z[2]+=(dF1*dza/4.); + z[3]+=(dF2*dza/4.); + } + } + + } + } + + + // inttype==5 => Stress Tensor Torque + if(inttype==5){ + CComplex n,t,pt,En,Dn,DE,dF1,dF2,dT; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + for(i=0;i<2;i++) z[i].Set(0,0); + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE) + { + En=n.re*v.Ex + n.im*v.Ey; + Dn=n.re*v.Dx + n.im*v.Dy; + DE = v.Dx*v.Ex + v.Dy*v.Ey; + dF1 = v.Ex*Dn + v.Dx*En - n.re*DE; + dF2 = v.Ey*Dn + v.Dy*En - n.im*DE; + dT=pt.re*dF2 - dF1*pt.im; + dza=dz*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + + z[0]+=(dT*dza*Depth/4.); + + DE = v.Dx*v.Ex.Conj() +v.Dy*v.Ey.Conj(); + dF1 = v.Ex*Dn.Conj() + v.Dx*En.Conj() - n.re*DE; + dF2= v.Ey*Dn.Conj() + v.Dy*En.Conj() - n.im*DE; + dT= pt.re*dF2 - dF1*pt.im ; + + z[1]+=(dT*dza*Depth/4.); + } + } + } + + } + + + return; +} + + +int CcviewDoc::ClosestArcSegment(double x, double y) +{ + double d0,d1; + int i,j; + + if(arclist.GetSize()==0) return -1; + + j=0; + d0=ShortestDistanceFromArc(CComplex(x,y),arclist[0]); + 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])); +} + +BOOL CcviewDoc::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"cview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LineIntegralPoints); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void CcviewDoc::BendContour(double angle, double anglestep) +{ + if (angle==0) return; + if (anglestep==0) anglestep=1; + + int k,n; + double d,tta,dtta,R; + CComplex c,a0,a1; + + // check to see if there are at least enough + // points to have made one line; + k=(int) contour.GetSize()-1; + if (k<1) return; + + // restrict the angle of the contour to 180 degrees; + if ((angle<-180.) || (angle>180.)) return; + n=(int) ceil(fabs(angle/anglestep)); + tta=angle*PI/180.; + dtta=tta/((double) n); + + // pop last point off of the contour; + a1=contour[k]; + contour.RemoveAt(k); + a0=contour[k-1]; + + // compute location of arc center; + // and radius of the circle that the + // arc lives on. + d=abs(a1-a0); + R=d/(2.*sin(fabs(tta/2.))); + if(tta>0) c=a0 + (R/d)*(a1-a0)*exp(I*(PI-tta)/2.); + else c=a0+(R/d)*(a1-a0)*exp(-I*(PI+tta)/2.); + + // add the points on the contour + for(k=1;k<=n;k++) contour.Add(c+(a0-c)*exp(k*I*dtta)); +} + + +double CcviewDoc::ShortestDistance(double p, double q, int segm) +{ + double t,x[3],y[3]; + + x[0]=nodelist[linelist[segm].n0].x; + y[0]=nodelist[linelist[segm].n0].y; + x[1]=nodelist[linelist[segm].n1].x; + y[1]=nodelist[linelist[segm].n1].y; + + t=((p-x[0])*(x[1]-x[0]) + (q-y[0])*(y[1]-y[0]))/ + ((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])); + + if (t>1.) 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 CcviewDoc::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 + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +class CcviewDoc : public CDocument +{ +protected: // create from serialization only + CcviewDoc(); + DECLARE_DYNCREATE(CcviewDoc) + +// Attributes +public: + + // General problem attributes + double Depth; + double Frequency; + int LengthUnits; + double *LengthConv; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL Smooth; + BOOL bMultiplyDefinedLabels; + double extRo, extRi, extZo; + + double A_High, A_Low; + CComplex A_lb, A_ub; + + double d_PlotBounds[9][2]; + double PlotBounds[9][2]; + + + // Some default behaviors + CString BinDir; + int d_LineIntegralPoints; + BOOL bHasMask; + + // lists of nodes, segments, and block labels + CArray< cviewtype::CNode, cviewtype::CNode&> nodelist; + CArray< cviewtype::CSegment, cviewtype::CSegment&> linelist; + CArray< cviewtype::CBlockLabel, cviewtype::CBlockLabel&> blocklist; + CArray< cviewtype::CArcSegment, cviewtype::CArcSegment&> arclist; + + // CArrays containing the mesh information + CArray< cviewtype::CMeshNode, cviewtype::CMeshNode&> meshnode; + CArray< cviewtype::CElement, cviewtype::CElement&> meshelem; + + // List of elements connected to each node; + int *NumList; + int **ConList; + + // lists of properties + CArray< cviewtype::CMaterialProp, cviewtype::CMaterialProp& > blockproplist; + CArray< cviewtype::CBoundaryProp, cviewtype::CBoundaryProp& > lineproplist; + CArray< cviewtype::CPointProp, cviewtype::CPointProp& > nodeproplist; + CArray< cviewtype::CCircuit, cviewtype::CCircuit& > circproplist; + + // list of points in a user-defined contour; + CArray< CComplex, CComplex& > contour; + + // member functions + int InTriangle(double x, double y); + BOOL InTriangleTest(double x, double y, int i); + BOOL GetPointValues(double x, double y, cviewtype::CPointVals &u); + BOOL GetPointValues(double x, double y, int k, cviewtype::CPointVals &u); + void GetLineValues(CXYPlot &p, int PlotType, int npoints); + void GetElementJ(int k); + void OnReload(); + int ClosestNode(double x, double y); + CComplex Ctr(int i); + double ElmArea(int i); + double ElmArea(cviewtype::CElement *elm); + void GetPointJ(double x, double y, CComplex &xZ, CComplex &yZ, cviewtype::CElement &elm); + void GetNodalJ(CComplex *xz, CComplex *yz, int i); + CComplex BlockIntegral(int inttype); + void LineIntegral(int inttype, CComplex *z); + int ClosestArcSegment(double x, double y); + void GetCircle(cviewtype::CArcSegment &asegm,CComplex &c, double &R); + double ShortestDistanceFromArc(CComplex p, cviewtype::CArcSegment &arc); + double ShortestDistanceFromSegment(double p, double q, int segm); + double ShortestDistance(double p, double q, int segm); + int ClosestSegment(double x, double y); + BOOL IsSameMaterial(int e1, int e2); + double AECF(int k); + double AECF(int k, CComplex p); + + BOOL ScanPreferences(); + void BendContour(double angle, double anglestep); + BOOL MakeMask(); + CComplex HenrotteVector(int k); + BOOL IsKosher(int k); + void FindBoundaryEdges(); + +// CComplex E(int k); +// CComplex D(int k); +// CComplex e(int k, int i); +// CComplex d(int k, int i); + +/* // Tests for whether or not one is inside a user-defined + // contour; this was really mostly used pre- v3.0, when + // the areas over which block integrals were taken were + // defined by a closed, user-generated contour. + BOOL ContourClosed(); + BOOL SlowInContour(double x, double y); + BOOL InContour(double x, double y); + BOOL InContour(CElement &elm); + BOOL InContour(CComplex p); + BOOL OnContour(CElement &elm); + void AvgMaxwell(double &fx, double &fy); + void AvgMaxwell(double &fx, double &fy, + CComplex &f2x, CComplex &f2y); +*/ + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CcviewDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + // lua extensions + bool luafired; + void initalise_lua(); + static int lua_dumpheader(lua_State * L); + static int lua_getpointvals(lua_State * L); + static int lua_exitpost(lua_State * L); + static int lua_addcontour(lua_State * L); + static int lua_clearcontour(lua_State * L); + static int lua_lineintegral(lua_State * L); + static int lua_selectblock(lua_State * L); + static int lua_groupselectblock(lua_State * L); + static int lua_blockintegral(lua_State * L); + static int lua_clearblock(lua_State * L); + static int lua_zoomout(lua_State * L); + static int lua_zoomin(lua_State * L); + static int lua_zoomnatural(lua_State * L); + static int lua_hidemesh(lua_State * L); + static int lua_showmesh(lua_State * L); + static int lua_showgrid(lua_State * L); + static int lua_hidegrid(lua_State * L); + static int lua_showdensity(lua_State * L); + static int lua_hidedensity(lua_State * L); + static int lua_hidecountour(lua_State * L); + static int lua_showcountour(lua_State * L); + static int lua_zoom(lua_State * L); + static int lua_smoothing(lua_State * L); + static int lua_hidepoints(lua_State * L); + static int lua_showpoints(lua_State * L); + static int lua_gridsnap(lua_State * L); + static int lua_setgrid(lua_State * L); + static int lua_getprobleminfo(lua_State * L); + static int lua_savebitmap(lua_State * L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC) ; + static int lua_getcircuitprops(lua_State *L); + static int lua_saveWMF(lua_State *L); + static int lua_refrescview(lua_State *L); + static int lua_selectline(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_bendcontour(lua_State *L); + static int lua_makeplot(lua_State *L); + static int lua_unselectall(lua_State *L); + static int lua_selectconductor(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_vectorplot(lua_State * L); + static int lua_reload(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_gettitle(lua_State *L); + + // commands to access low-level information through Lua + static int lua_numnodes(lua_State *L); + static int lua_numelements(lua_State *L); + static int lua_getnode(lua_State *L); + static int lua_getelement(lua_State *L); + + virtual ~CcviewDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CcviewDoc) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); diff --git a/femm/CVIEWLUA.CPP b/femm/CVIEWLUA.CPP new file mode 100644 index 0000000..05ca1a5 --- /dev/null +++ b/femm/CVIEWLUA.CPP @@ -0,0 +1,1917 @@ +#include "stdafx.h" +#include +#include +#include "cv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "cviewDoc.h" +#include "cviewview.h" +#include "MainFrm.h" +#include "windows.h" //necessary for bitmap saving +#include "lua.h" +#include "mycommandlineinfo.h" +#include "promptbox.h" +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern lua_State * lua; +extern BOOL bLinehook; +extern void *pcviewDoc; +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern CLuaConsoleDlg *LuaConsole; + +#define CatchNullDocument(); if (pcviewDoc==NULL)\ + { CString msg="No current heat flow output in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//-------------------Lua Extensions------------------------- + +void CcviewDoc::initalise_lua() +{ + // use a messagebox to display errors + lua_register(lua,"co_setfocus",lua_switchfocus); + lua_register(lua,"co_getpointvalues",lua_getpointvals); + lua_register(lua,"co_close",lua_exitpost); + lua_register(lua,"co_addcontour",lua_addcontour); + lua_register(lua,"co_clearcontour",lua_clearcontour); + lua_register(lua,"co_lineintegral",lua_lineintegral); + lua_register(lua,"co_selectblock",lua_selectblock); + lua_register(lua,"co_groupselectblock",lua_groupselectblock); + lua_register(lua,"co_clearblock",lua_clearblock); + lua_register(lua,"co_blockintegral",lua_blockintegral); + lua_register(lua,"co_zoomnatural",lua_zoomnatural); + lua_register(lua,"co_zoomin",lua_zoomin); + lua_register(lua,"co_zoomout",lua_zoomout); + lua_register(lua,"co_zoom",lua_zoom); + lua_register(lua,"co_showgrid",lua_showgrid); + lua_register(lua,"co_hidegrid",lua_hidegrid); + lua_register(lua,"co_gridsnap",lua_gridsnap); + lua_register(lua,"co_setgrid",lua_setgrid); + lua_register(lua,"co_showmesh",lua_showmesh); + lua_register(lua,"co_hidemesh",lua_hidemesh); + lua_register(lua,"co_hidedensityplot",lua_hidedensity); + lua_register(lua,"co_showdensityplot",lua_showdensity); + lua_register(lua,"co_hidecontourplot",lua_hidecountour); + lua_register(lua,"co_showcontourplot",lua_showcountour); + lua_register(lua,"co_showvectorplot" ,lua_vectorplot); + lua_register(lua,"co_smooth",lua_smoothing); + lua_register(lua,"co_showpoints",lua_showpoints); + lua_register(lua,"co_hidepoints",lua_hidepoints); + lua_register(lua,"co_shownames",lua_shownames); + lua_register(lua,"co_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"co_savebitmap",lua_savebitmap); + lua_register(lua,"co_getconductorproperties",lua_getcircuitprops); + lua_register(lua,"co_savemetafile",lua_saveWMF); + lua_register(lua,"co_refrescview",lua_refrescview); + lua_register(lua,"co_selectpoint",lua_selectline); + lua_register(lua,"co_seteditmode",lua_seteditmode); + lua_register(lua,"co_bendcontour",lua_bendcontour); + lua_register(lua,"co_makeplot",lua_makeplot); + lua_register(lua,"co_selectconductor",lua_selectconductor); + lua_register(lua,"co_reload",lua_reload); + lua_register(lua,"co_gettitle",lua_gettitle); + lua_register(lua,"co_get_title",lua_gettitle); + + lua_register(lua,"co_resize",luaResize); + lua_register(lua,"co_minimize",luaMinimize); + lua_register(lua,"co_maximize",luaMaximize); + lua_register(lua,"co_restore", luaRestore); + + // compatibility with alternate lua function naming convention + lua_register(lua,"co_set_focus",lua_switchfocus); + lua_register(lua,"co_get_point_values",lua_getpointvals); + lua_register(lua,"co_add_contour",lua_addcontour); + lua_register(lua,"co_clear_contour",lua_clearcontour); + lua_register(lua,"co_line_integral",lua_lineintegral); + lua_register(lua,"co_select_block",lua_selectblock); + lua_register(lua,"co_group_select_block",lua_groupselectblock); + lua_register(lua,"co_clear_block",lua_clearblock); + lua_register(lua,"co_block_integral",lua_blockintegral); + lua_register(lua,"co_zoom_natural",lua_zoomnatural); + lua_register(lua,"co_zoom_in",lua_zoomin); + lua_register(lua,"co_zoom_out",lua_zoomout); + lua_register(lua,"co_show_grid",lua_showgrid); + lua_register(lua,"co_hide_grid",lua_hidegrid); + lua_register(lua,"co_show_mesh",lua_showmesh); + lua_register(lua,"co_hide_mesh",lua_hidemesh); + lua_register(lua,"co_hide_density_plot",lua_hidedensity); + lua_register(lua,"co_show_density_plot",lua_showdensity); + lua_register(lua,"co_hide_contour_plot",lua_hidecountour); + lua_register(lua,"co_show_contour_plot",lua_showcountour); + lua_register(lua,"co_show_points",lua_showpoints); + lua_register(lua,"co_hide_points",lua_hidepoints); + lua_register(lua,"co_grid_snap",lua_gridsnap); + lua_register(lua,"co_set_grid",lua_setgrid); + lua_register(lua,"co_get_problem_info",lua_getprobleminfo); + lua_register(lua,"co_save_bitmap",lua_savebitmap); + lua_register(lua,"co_get_conductor_properties",lua_getcircuitprops); + lua_register(lua,"co_save_metafile",lua_saveWMF); + lua_register(lua,"co_refresh_view",lua_refrescview); + lua_register(lua,"co_select_point",lua_selectline); + lua_register(lua,"co_set_edit_mode",lua_seteditmode); + lua_register(lua,"co_bend_contour",lua_bendcontour); + lua_register(lua,"co_make_plot",lua_makeplot); + lua_register(lua,"co_select_conductor",lua_selectconductor); + lua_register(lua,"co_show_names",lua_shownames); + lua_register(lua,"co_show_vector_plot",lua_vectorplot); + + // functions to access low-level mesh info + lua_register(lua,"co_numnodes",lua_numnodes); + lua_register(lua,"co_numelements",lua_numelements); + lua_register(lua,"co_getnode",lua_getnode); + lua_register(lua,"co_getelement",lua_getelement); + + lua_register(lua,"co_num_nodes",lua_numnodes); + lua_register(lua,"co_num_elements",lua_numelements); + lua_register(lua,"co_get_node",lua_getnode); + lua_register(lua,"co_get_element",lua_getelement); + + pcviewDoc=this; + +} + +int CcviewDoc::lua_dumpheader(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + return 0; +} + +int CcviewDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CcviewDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".anh") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<8;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CcviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".anh") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pcviewDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CcviewDoc::lua_getpointvals(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CcviewDoc * thisDoc; + CcviewView * theView; + + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CPointVals u; + + if(thisDoc->GetPointValues(px, py, u)==TRUE) + { + lua_pushnumber(L,u.v); + lua_pushnumber(L,u.Jx); + lua_pushnumber(L,u.Jy); + lua_pushnumber(L,u.Kx); + lua_pushnumber(L,u.Ky); + lua_pushnumber(L,u.Ex); + lua_pushnumber(L,u.Ey); + lua_pushnumber(L,u.ex); + lua_pushnumber(L,u.ey); + lua_pushnumber(L,u.Jdx); + lua_pushnumber(L,u.Jdy); + lua_pushnumber(L,u.ox); + lua_pushnumber(L,u.oy); + lua_pushnumber(L,u.Jcx); + lua_pushnumber(L,u.Jcy); + return 15; + } + + return 0; +} + +int CcviewDoc::lua_exitpost(lua_State * L) +{ + CatchNullDocument(); + ((CcviewDoc *)pcviewDoc)->OnCloseDocument( ); + + return 0; +} + +int CcviewDoc::lua_reload(lua_State * L) +{ + CatchNullDocument(); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + // theView->BeginWaitCursor(); + thisDoc->OnReload(); + // theView->EndWaitCursor(); + if (theView->d_ResetOnReload==FALSE) thisDoc->FirstDraw=FALSE; + theView->RedrawView(); + theView->LuaViewInfo(); + return 0; +} + +void CcviewView::LuaViewInfo() +{ + OnViewInfo(); +} + +int CcviewDoc::lua_addcontour(lua_State * L) +{ + CatchNullDocument(); + CComplex z; + int i; + z.Set(lua_todouble(L,1),lua_todouble(L,2)); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + i=(int) thisDoc->contour.GetSize(); + + if(i>0){ + if (z!=thisDoc->contour[i-1]) + thisDoc->contour.Add(z); + } + else thisDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + + return 0; +} + +int CcviewDoc::lua_clearcontour(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + + return 0; +} + +int CcviewDoc::lua_lineintegral(lua_State * L) +{ + CatchNullDocument(); + int type; + CComplex z[4]; + int k; + + type=(int) lua_todouble(L,1); + // 0 - G.t + // 1 - F.n + // 2 - Contour length + // 3 - Average temperature + + if (type<0 || type >3) + { + CString msg; + msg.Format("Invalid line integral selected %d",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + z[0]=0; z[1]=0; + thisDoc->LineIntegral(type,z); + + for(k=0;k<4;k++) lua_pushnumber(lua,z[k]); + + return 4; +} + +int CcviewDoc::lua_selectblock(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int k; + + if (thisDoc->meshelem.GetSize()>0){ + k=thisDoc->InTriangle(px,py); + if(k>=0){ + thisDoc->bHasMask=FALSE; + thisDoc->blocklist[thisDoc->meshelem[k].lbl].ToggleSelect(); + // RedrawView(); + theView->DrawSelected=thisDoc->meshelem[k].lbl; + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + } + + return 0; +} + +int CcviewDoc::lua_groupselectblock(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int j,k,n; + + if (thisDoc->meshelem.GetSize()>0) + { + n=lua_gettop(L); + k=0; if (n>0) k=(int)lua_todouble(L,1); + + for(j=0;jblocklist.GetSize();j++) + { + if ((thisDoc->blocklist[j].InGroup==k) || (n==0)) + thisDoc->blocklist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } + + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + + return 0; +} + +int CcviewDoc::lua_clearblock(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + theView->UnselectAll(); + theView->EditAction=0; + theView->RedrawView(); + + return 0; +} + + +int CcviewDoc::lua_blockintegral(lua_State * L) +{ + // 0 Real Power + // 1 Reactive Power + // 2 Apparent Power + // 3 Time-Average Stored Energy + // 4 Block cross-section area + // 5 Block volume + // 6 x (or r) direction WST force, SS part. + // 7 y (or z) direction WST force, SS part. + // 8 x (or r) direction WST force, 2x part. + // 9 y (or z) direction WST force, 2x part. + // 10 WST torque, SS part. + // 11 WST torque, 2x part. + + CatchNullDocument(); + int type; + type=(int) lua_todouble(L,1); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CComplex z; + + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (thisDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + if(type>=6) + for(i=0;imeshnode.GetSize();i++) + if (thisDoc->meshnode[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE) + { + CString msg="Cannot integrate\nNo area has been selected"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + if(type>=6) thisDoc->MakeMask(); + z=thisDoc->BlockIntegral(type); + + lua_pushnumber(L,z); + + return 1; + +} + +int CcviewDoc::lua_zoomin(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + + theView->ox=theView->ox+0.25*x/theView->mag; + theView->oy=theView->oy+0.25*y/theView->mag; + theView->mag*=2.; + + theView->RedrawView(); + + + + + return 0; +} + +int CcviewDoc::lua_zoom(lua_State * L) +{ + CatchNullDocument(); + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CRect r; + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CcviewDoc::lua_zoomnatural(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + + CcviewDoc *pDoc=theView->GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return 0; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + theView->GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + if(pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else theView->RedrawView(); + + + + return 0; +} + +int CcviewDoc::lua_zoomout(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + theView->ox=theView->ox-0.5*x/theView->mag; + theView->oy=theView->oy-0.5*y/theView->mag; + theView->mag/=2.; + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_showmesh(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_hidemesh(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->RedrawView(); + + return 0; +} + + +int CcviewDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_showdensity(lua_State * L) +{ + CatchNullDocument(); + BOOL showlegend; + BOOL gscale; + int PlotType,n; + double m_ub1,m_lb1; + CString type; + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + n=lua_gettop(L); if(n<3) return 0; + + showlegend=(int) lua_todouble(L,1); + gscale=(int) lua_todouble(L,2); + PlotType=(int) lua_todouble(L,3); + + if(n>=5) + { + m_ub1=lua_todouble(L,4); + m_lb1=lua_todouble(L,5); + } + + if(m_lb1>m_ub1) + { + double temp=m_lb1; + m_lb1=m_ub1; + m_ub1=temp; + } + + if ((PlotType>8)|| (PlotType<0)) PlotType=0; + + if (showlegend==-1) + { + // load back the default plot range + m_lb1=thisDoc->d_PlotBounds[PlotType][0]; + m_ub1=thisDoc->d_PlotBounds[PlotType][1]; + showlegend=1; + gscale=0; + n=5; + } + + theView->DensityPlot=PlotType+1; + theView->LegendFlag=showlegend; + theView->GreyContours=gscale; + if(n>=5) + { + thisDoc->PlotBounds[PlotType][1]=m_ub1; + thisDoc->PlotBounds[PlotType][0]=m_lb1; + } + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_hidedensity(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + theView->DensityPlot=0; + + theView->RedrawView(); + + return 0; +} + + +int CcviewDoc::lua_showcountour(lua_State * L) +{ + CatchNullDocument(); + int m_numcontours,n; + double m_alow,m_ahigh; + CString type; + + // defaults; + type="real"; + m_numcontours=-1; + + n=lua_gettop(L); + if (n>0) m_numcontours=(int) lua_todouble(L,1); + if (n>1) m_alow=lua_todouble(L,2); + if (n>2) m_ahigh=lua_todouble(L,3); + if (n>3) type=lua_tostring(L,4); + type.MakeLower(); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + // default behavior + theView->ShowAr=true; + theView->ShowAi=false; + + if(type=="real") + { + theView->ShowAr=true; + theView->ShowAi=false; + } + if(type=="imag") + { + theView->ShowAi=true; + theView->ShowAr=false; + } + if(type=="both") + { + theView->ShowAi=theView->ShowAr=true; + } + + thisDoc->A_Low=m_alow; + thisDoc->A_High=m_ahigh; + theView->NumContours=m_numcontours; + + if(m_numcontours==-1) + { + thisDoc->A_Low= __min(thisDoc->A_lb.re,thisDoc->A_lb.im); + thisDoc->A_High=__max(thisDoc->A_ub.re,thisDoc->A_ub.im); + theView->NumContours=19; + } + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_hidecountour(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + theView->ShowAr=FALSE; + + theView->RedrawView(); + return 0; +} + +int CcviewDoc::lua_smoothing(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + + if (temp=="off") + { + thisDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + + } + if (temp=="on") + { + thisDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for smoothing"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + + theView->RedrawView(); + + return 0; +} + + +int CcviewDoc::lua_showpoints(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_hidepoints(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CcviewDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_getprobleminfo(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Frequency); + lua_pushnumber(L,thisDoc->Depth); + lua_pushnumber(L,thisDoc->LengthConv[thisDoc->LengthUnits]); + + return 4; +} + +int CcviewDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + // tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + // to save a bitmap file we need + // a bitmapheader lets use the v5 + + // OpenClipboard(); + // EmptyClipboard(); + // SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + // CloseClipboard(); +return 0; +} + + +PBITMAPINFO CcviewDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy9"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits >= 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CcviewDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy10"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy11"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy12"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy13"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy14"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy15"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy16"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + +int CcviewDoc::lua_getcircuitprops(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * TheDoc; // note normally thisdoc + CcviewView * theView; + TheDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=TheDoc->GetFirstViewPosition(); + theView=(CcviewView *)TheDoc->GetNextView(pos); + + int NumCircuits,i,k; + CString circuitname; + circuitname=lua_tostring(L,1); + k=-1; + + // ok we need to find the correct entry for the circuit name + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName==circuitname) + { + k=i; + i=NumCircuits; // that will break it + } + } + +// trap errors + + if(k==-1) + { + CString msg="Unknown conductor"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + lua_pushnumber(L,TheDoc->circproplist[k].V); + lua_pushnumber(L,TheDoc->circproplist[k].q); + return 2; +} + +int CcviewDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CcviewDoc::lua_refrescview(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // redraw the view + theView->OnDraw(pDC); + + return 0; +} + +int CcviewDoc::lua_selectline(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * pDoc; // note normally thisdoc + CcviewView * theView; + pDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CcviewView *)pDoc->GetNextView(pos); + + theView->EditAction=1; // make sure things update OK + + double mx,my; + int i,j,k,m; + + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + + +//*************** + { + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return 0; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + theView->DrawUserContour(FALSE); + return 0; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(y); + theView->DrawUserContour(FALSE); + } + } + } + } + + +//************* + return 0; +} + +int CcviewDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + if (EditAction=="point") + { + if (theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + if (theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) + { + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=0; + } + if (EditAction=="contour") + { + if(theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=1; + } + if (EditAction=="area") + { + if(theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + theView->EditAction=2; + } + + return 0; +} + +int CcviewDoc::lua_bendcontour(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + thisDoc->BendContour(lua_todouble(L,1),lua_todouble(L,2)); + theView->InvalidateRect(NULL); + + return 0; +} + +int CcviewDoc::lua_makeplot(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc *pDoc; + CcviewView *pView; + pDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + pView=(CcviewView *)pDoc->GetNextView(pos); + + int PlotType,npoints,FileFormat,n; + CString ToFile; + +// if ((pView->EditAction!=1) || (pDoc->contour.GetSize()==0)){ + if (pDoc->contour.GetSize()==0){ + CString outmsg; + outmsg.Format("*** Cannot create a plot;\r\n*** No contour has been defined\r\n"); + LuaConsole->ToOutput(outmsg); + return TRUE; + } + + n=lua_gettop(L); + + if(n>0) PlotType=(int) lua_todouble(L,1); + else return FALSE; + + if(n>1) npoints=(int) lua_todouble(L,2); + else npoints=pView->d_PlotPoints; + + CXYPlot xyplot; + pDoc->GetLineValues(xyplot,PlotType,npoints); + + if(n<3) + { + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (pView->OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else{ + ToFile.Format("%s",lua_tostring(L,3)); + + if(n>3){ + FileFormat=(int) lua_todouble(L,4); + if (xyplot.ToDisk(FileFormat,ToFile)==FALSE) + LuaConsole->ToOutput("*** Couldn't write data to disk\r\n"); + } + else{ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,ToFile)); + DeleteEnhMetaFile(hMeta); + } + } + + return TRUE; +} + +int CcviewDoc::lua_selectconductor(lua_State *L) +{ + CatchNullDocument(); + int n=lua_gettop(L); + if (n==0) return 0; + + int j,i; + CString name; + name=lua_tostring(L,1); + + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + for(i=0,j=-1;icircproplist.GetSize();i++) + { + + if (name==thisDoc->circproplist[i].CircName) + { + j=i; + break; + } + } + + if (j<0) return 0; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (thisDoc->nodelist[i].InConductor==j) thisDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (thisDoc->linelist[i].InConductor==j) thisDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (thisDoc->arclist[i].InConductor==j) thisDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (thisDoc->meshnode[i].Q==j) + { + thisDoc->meshnode[i].IsSelected=1-thisDoc->meshnode[i].IsSelected; + } + } + theView->RedrawView(); + + return 0; +} + +int CcviewDoc::lua_shownames(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +int CcviewDoc::lua_vectorplot(lua_State * L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n>0) theView->VectorPlot=(int)lua_todouble(L,1); + if (n>1) theView->VectorScaleFactor=lua_todouble(L,2); + + theView->InvalidateRect(NULL); + + return 0; +} + +int CcviewDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CcviewDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CcviewDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CcviewDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + CcviewView * theView; + thisDoc=(CcviewDoc *)pcviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CcviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int CcviewDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + thisDoc=(CcviewDoc *)pcviewDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + + + +/////////////////////////////////////////////////////// +// Functions that provide low-level access to the mesh +/////////////////////////////////////////////////////// + +int CcviewDoc::lua_numnodes(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + thisDoc=(CcviewDoc *)pcviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshnode.GetSize()); + + return 1; +} + +int CcviewDoc::lua_numelements(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + thisDoc=(CcviewDoc *)pcviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshelem.GetSize()); + + return 1; +} + +int CcviewDoc::lua_getnode(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + thisDoc=(CcviewDoc *)pcviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshnode.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshnode[k].x); + lua_pushnumber(L,thisDoc->meshnode[k].y); + + return 2; +} + +int CcviewDoc::lua_getelement(lua_State *L) +{ + CatchNullDocument(); + CcviewDoc * thisDoc; + thisDoc=(CcviewDoc *)pcviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshelem.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshelem[k].p[0]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[1]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[2]+1); + lua_pushnumber(L,Re(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,Im(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,thisDoc->ElmArea(k)); + lua_pushnumber(L,thisDoc->blocklist[thisDoc->meshelem[k].lbl].InGroup); + + return 7; +} + diff --git a/femm/CV_PREF.CPP b/femm/CV_PREF.CPP new file mode 100644 index 0000000..c39fee7 --- /dev/null +++ b/femm/CV_PREF.CPP @@ -0,0 +1,1016 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + #define SelColor clist[0] + #define BackColor clist[1] + #define MeshColor clist[2] + #define BlockColor clist[3] + #define LineColor clist[4] + #define GridColor clist[5] + #define NodeColor clist[6] + #define RegionColor clist[7] + #define TextColor clist[8] + #define RealFluxLineColor clist[9] + #define ImagFluxLineColor clist[10] + #define NameColor clist[11] + #define MaskLineColor clist[12] + #define RealVectorColor clist[13] + #define ImagVectorColor clist[14] + #define Color00 clist[15] + #define Color01 clist[16] + #define Color02 clist[17] + #define Color03 clist[18] + #define Color04 clist[19] + #define Color05 clist[20] + #define Color06 clist[21] + #define Color07 clist[22] + #define Color08 clist[23] + #define Color09 clist[24] + #define Color10 clist[25] + #define Color11 clist[26] + #define Color12 clist[27] + #define Color13 clist[28] + #define Color14 clist[29] + #define Color15 clist[30] + #define Color16 clist[31] + #define Color17 clist[32] + #define Color18 clist[33] + #define Color19 clist[34] + #define Grey00 clist[35] + #define Grey01 clist[36] + #define Grey02 clist[37] + #define Grey03 clist[38] + #define Grey04 clist[39] + #define Grey05 clist[40] + #define Grey06 clist[41] + #define Grey07 clist[42] + #define Grey08 clist[43] + #define Grey09 clist[44] + #define Grey10 clist[45] + #define Grey11 clist[46] + #define Grey12 clist[47] + #define Grey13 clist[48] + #define Grey14 clist[49] + #define Grey15 clist[50] + #define Grey16 clist[51] + #define Grey17 clist[52] + #define Grey18 clist[53] + #define Grey19 clist[54] + + + +///////////////////////////////////////////////////////////////////////////// +// cvCPref dialog + + +cvCPref::cvCPref(CWnd* pParent /*=NULL*/) + : CDialog(cvCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCPref) + m_d_GreyContours = FALSE; + m_d_LegendFlag = TRUE; + m_d_NumContours = 19; + m_d_ResetOnReload = FALSE; + m_d_GridFlag = FALSE; + m_d_ShowAr = FALSE; + m_d_ShowAi = FALSE; + m_d_PtsFlag = TRUE; + m_d_MeshFlag = FALSE; + m_d_SnapFlag = FALSE; + m_d_Smooth = TRUE; + m_d_LineIntegralPoints = 400; + m_d_PlotPoints = 1500; + m_d_ShowMask = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + m_d_DensityPlot=1; + m_d_EditAction=0; + m_d_VectorPlot=0; + + clist=(COLORREF *)calloc(64,sizeof(COLORREF)); + int i=0; + + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dImagFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dImagVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + +} + +cvCPref::~cvCPref() +{ + free(clist); +} + +void cvCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCPref) + DDX_Control(pDX, IDC_CV_VECTORPLOT, m_d_vplotlist); + DDX_Control(pDX, IDC_CV_DENSITYPLOT, m_d_dplotlist); + DDX_Control(pDX, IDC_CV_EDITACTION, m_d_editlist); + DDX_Control(pDX, IDC_CV_COLORS, m_d_color); + DDX_Check(pDX, IDC_CV_GREY, m_d_GreyContours); + DDX_Check(pDX, IDC_CV_LEGEND, m_d_LegendFlag); + DDX_Text(pDX, IDC_CV_NCONT, m_d_NumContours); + DDV_MinMaxInt(pDX, m_d_NumContours, 4, 999); + DDX_Check(pDX, IDC_CV_ONRELOAD, m_d_ResetOnReload); + DDX_Check(pDX, IDC_CV_SHOWGRID, m_d_GridFlag); + DDX_Check(pDX, IDC_CV_SHOWREAL, m_d_ShowAr); + DDX_Check(pDX, IDC_CV_SHOWIMAG, m_d_ShowAi); + DDX_Check(pDX, IDC_CV_SHOWPTS, m_d_PtsFlag); + DDX_Check(pDX, IDC_CV_SHOWMESH, m_d_MeshFlag); + DDX_Check(pDX, IDC_CV_SNAPGRID, m_d_SnapFlag); + DDX_Check(pDX, IDC_CV_SMOOTHING, m_d_Smooth); + DDX_Text(pDX, IDC_CV_LIPOINTS, m_d_LineIntegralPoints); + DDV_MinMaxInt(pDX, m_d_LineIntegralPoints, 10, 100000); + DDX_Text(pDX, IDC_CV_PLOTPOINTS, m_d_PlotPoints); + DDV_MinMaxInt(pDX, m_d_PlotPoints, 10, 100000); + DDX_Check(pDX, IDC_CV_SHOWMASK, m_d_ShowMask); + DDX_Check(pDX, IDC_CV_SHOWNAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CV_NCONT, m_IDC_d_NumContours); + DDX_Control(pDX, IDC_CV_LIPOINTS, m_IDC_d_LineIntegralPoints); + DDX_Control(pDX, IDC_CV_PLOTPOINTS, m_IDC_d_PlotPoints); + + +} + + +BEGIN_MESSAGE_MAP(cvCPref, CDialog) + //{{AFX_MSG_MAP(cvCPref) + ON_BN_CLICKED(IDC_CV_MODBTN, OnModBtn) + ON_BN_CLICKED(IDC_CV_RESET, OnResetColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCPref message handlers + +void cvCPref::OnModBtn() +{ + CColorDialog dlg; + COLORREF cclist[16]; + int i,k; + + UpdateData(); + i=m_d_color.GetCurSel(); + for(k=0;k<16;k++) cclist[k]=RGB(190,190,190); + + if(i<11) for(k=0;k<11;k++) cclist[k]=clist[k]; + if((i>10)&&(i<23)) for(k=11;k<23;k++) cclist[k-11]=clist[k]; + if(i>22) for(k=23;k<35;k++) cclist[k-23]=clist[k]; + + dlg.m_cc.lpCustColors=cclist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + +} + +BOOL cvCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_color.SetCurSel(0); + m_d_dplotlist.SetCurSel(m_d_DensityPlot); + m_d_editlist.SetCurSel(m_d_EditAction); + m_d_vplotlist.SetCurSel(m_d_VectorPlot); + + UpdateData(FALSE); + + return TRUE; +} + +void cvCPref::OnResetColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + int i=0; + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dImagFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dImagVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + } +} + +BOOL cvCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void cvCPref::WritePrefs() +{ + UpdateData(); + m_d_DensityPlot=m_d_dplotlist.GetCurSel(); + m_d_EditAction=m_d_editlist.GetCurSel(); + m_d_VectorPlot=m_d_vplotlist.GetCurSel(); + + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "cview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("FluxIColor",ImagFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorRColor", RealVectorColor,fp); + WriteColor("VectorIColor", ImagVectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",m_d_EditAction); + fprintf(fp," = %i\n",m_d_DensityPlot); + fprintf(fp," = %i\n",m_d_VectorPlot); + fprintf(fp," = %i\n",m_d_GridFlag); + fprintf(fp," = %i\n",m_d_SnapFlag); + fprintf(fp," = %i\n",m_d_MeshFlag); + fprintf(fp," = %i\n",m_d_LegendFlag); + fprintf(fp," = %i\n",m_d_NumContours); + fprintf(fp," = %i\n",m_d_ShowAr); + fprintf(fp," = %i\n",m_d_ShowAi); + fprintf(fp," = %i\n",m_d_ShowMask); + fprintf(fp," = %i\n",m_d_GreyContours); + fprintf(fp," = %i\n",m_d_PtsFlag); + fprintf(fp," = %i\n",m_d_ResetOnReload); + fprintf(fp," = %i\n",m_d_Smooth); + fprintf(fp," = %i\n",m_d_PlotPoints); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_LineIntegralPoints); + + fclose(fp); + } +} + +char* StripKey(char *c); + +void cvCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "cview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LineIntegralPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAi); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + +} \ No newline at end of file diff --git a/femm/CV_PREF.H b/femm/CV_PREF.H new file mode 100644 index 0000000..2befac7 --- /dev/null +++ b/femm/CV_PREF.H @@ -0,0 +1,69 @@ +// Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCPref dialog + +class cvCPref : public CDialog +{ +// Construction +public: + cvCPref(CWnd* pParent = NULL); // standard constructor + ~cvCPref(); + + COLORREF *clist; + int m_d_EditAction; + int m_d_DensityPlot; + int m_d_VectorPlot; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(cvCPref) + enum { IDD = IDD_CV_PREF }; + CComboBox m_d_vplotlist; + CComboBox m_d_dplotlist; + CComboBox m_d_editlist; + CComboBox m_d_color; + BOOL m_d_GreyContours; + BOOL m_d_LegendFlag; + int m_d_NumContours; + BOOL m_d_ResetOnReload; + BOOL m_d_GridFlag; + BOOL m_d_ShowAr; + BOOL m_d_ShowAi; + BOOL m_d_PtsFlag; + BOOL m_d_MeshFlag; + BOOL m_d_SnapFlag; + BOOL m_d_Smooth; + int m_d_LineIntegralPoints; + int m_d_PlotPoints; + BOOL m_d_ShowMask; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCPref) + afx_msg void OnModBtn(); + virtual BOOL OnInitDialog(); + afx_msg void OnResetColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_d_NumContours, m_IDC_d_LineIntegralPoints; + CLuaEdit m_IDC_d_PlotPoints; + +}; diff --git a/femm/ChildFrm.cpp b/femm/ChildFrm.cpp new file mode 100644 index 0000000..04ee286 --- /dev/null +++ b/femm/ChildFrm.cpp @@ -0,0 +1,113 @@ +// ChildFrm.cpp : implementation of the CChildFrame class +// + +#include "stdafx.h" +#include "femm.h" + +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern CFemmApp theApp; +extern BOOL bLinehook; +///////////////////////////////////////////////////////////////////////////// +// CChildFrame + +IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) + +BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) + //{{AFX_MSG_MAP(CChildFrame) + ON_WM_SIZE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame construction/destruction + +CChildFrame::CChildFrame() +{ + // TODO: add member initialization code here + +} + +CChildFrame::~CChildFrame() +{ +} + +BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + if( !CMDIChildWnd::PreCreateWindow(cs) ) + return FALSE; + + return TRUE; +} + +void CChildFrame::ActivateFrame(int nCmdShow) +{ + // Gets first window to open maximized. Originally cribbed from: + // Visual C++/MFC Frequently Asked Questions + // Scot Wingo + // Stingray Software + // Version 5.0, updated 5/15/97 + if (theApp.luaShowWindow != NULL) CMDIChildWnd::ActivateFrame(theApp.luaShowWindow); + else if(GetMDIFrame()->MDIGetActive()) CMDIChildWnd::ActivateFrame(nCmdShow); + else CMDIChildWnd::ActivateFrame(SW_SHOWMAXIMIZED); + theApp.luaShowWindow=NULL; +} + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame diagnostics + +#ifdef _DEBUG +void CChildFrame::AssertValid() const +{ + CMDIChildWnd::AssertValid(); +} + +void CChildFrame::Dump(CDumpContext& dc) const +{ + CMDIChildWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame message handlers + +BOOL CChildFrame::ResizeClient(int nWidth, int nHeight, BOOL bRedraw) +{ + RECT rcWnd; + GetClientRect (&rcWnd); + + if(nWidth != -1) rcWnd.right = nWidth; + if(nHeight != -1) rcWnd.bottom = nHeight; + if(!::AdjustWindowRectEx(&rcWnd,GetStyle(),(GetMenu()!=NULL), GetExStyle())) return FALSE; + + UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; + + if(!bRedraw) uFlags |= SWP_NOREDRAW; + + return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags); +} + +void CChildFrame::OnSize(UINT nType, int cx, int cy) +{ + CMDIChildWnd::OnSize(nType, cx, cy); + + // Idea here is to give the active view a message that says that the window has + // been minimized. If the active view is a postprocessor window, the output + // window may need to be hidden if the window is minimized but still active. + + if (nType==SIZE_MINIMIZED) + { + CView* theView=GetActiveView( ); + theView->PostMessage(WM_SIZE,SIZE_MINIMIZED); + } +} diff --git a/femm/ChildFrm.h b/femm/ChildFrm.h new file mode 100644 index 0000000..5e25800 --- /dev/null +++ b/femm/ChildFrm.h @@ -0,0 +1,54 @@ +// ChildFrm.h : interface of the CChildFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDFRM_H__5DA42274_DC99_4A3F_A918_C850B3925734__INCLUDED_) +#define AFX_CHILDFRM_H__5DA42274_DC99_4A3F_A918_C850B3925734__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class CChildFrame : public CMDIChildWnd +{ + DECLARE_DYNCREATE(CChildFrame) +public: + CChildFrame(); + BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw=FALSE); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void ActivateFrame(int nCmdShow); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CChildFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CChildFrame) + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDFRM_H__5DA42274_DC99_4A3F_A918_C850B3925734__INCLUDED_) diff --git a/femm/CircDlg.cpp b/femm/CircDlg.cpp new file mode 100644 index 0000000..bca0773 --- /dev/null +++ b/femm/CircDlg.cpp @@ -0,0 +1,115 @@ +// CircDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "problem.h" +#include "xyplot.h" +#include "femmviewdoc.h" +#include "CircDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCircDlg dialog + + +CCircDlg::CCircDlg(CWnd* pParent /*=NULL*/) + : CDialog(CCircDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCircDlg) + //}}AFX_DATA_INIT +} + + +void CCircDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCircDlg) + DDX_Control(pDX, IDC_FV_CIRCNAME, m_circname); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCircDlg, CDialog) + //{{AFX_MSG_MAP(CCircDlg) + ON_CBN_SELCHANGE(IDC_FV_CIRCNAME, OnSelchangeCircname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCircDlg message handlers + +void CCircDlg::OnSelchangeCircname() +{ + if(NumCircuits==0) return; + + int k; + CString crslt; + + k=m_circname.GetCurSel(); + + CString s; + char c[256]; + CComplex amps,flux,volts; + + amps=TheDoc->circproplist[k].Amps; + crslt.Format("Total current = %s Amps\r\n",amps.ToStringAlt(c)); + + volts=TheDoc->GetVoltageDrop(k); + s.Format("Voltage Drop = %s Volts\r\n",volts.ToStringAlt(c)); + crslt+=s; + + flux = TheDoc->GetFluxLinkage(k); + s.Format("Flux Linkage = %s Webers\r\n",flux.ToStringAlt(c)); + crslt+=s; + + if (amps!=0){ + s.Format("Flux/Current = %s Henries\r\n", + (flux/amps).ToStringAlt(c)); + crslt+=s; + s.Format("Voltage/Current = %s Ohms\r\n", + (volts/amps).ToStringAlt(c)); + crslt+=s; + } + + if (TheDoc->Frequency==0) + { + s.Format("Power = %g Watts\r\n",Re(amps*volts)); + crslt+=s; + } + else{ + s.Format("Real Power = %g Watts\r\n",Re(volts*conj(amps))/2.); + crslt+=s; + s.Format("Reactive Power = %g VAr\r\n",Im(volts*conj(amps))/2.); + crslt+=s; + s.Format("Apparent Power = %g VA\r\n",abs(volts)*abs(amps)/2.); + crslt+=s; + } + + SetDlgItemText(IDC_CIRCRESULT,crslt); +} + +BOOL CCircDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName); + + if(NumCircuits!=0){ + m_circname.SetCurSel(0); + OnSelchangeCircname(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/CircDlg.h b/femm/CircDlg.h new file mode 100644 index 0000000..8b2754c --- /dev/null +++ b/femm/CircDlg.h @@ -0,0 +1,39 @@ +// CircDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCircDlg dialog + +class CCircDlg : public CDialog +{ +// Construction +public: + CCircDlg(CWnd* pParent = NULL); // standard constructor + + CFemmviewDoc *TheDoc; + int NumCircuits; + +// Dialog Data + //{{AFX_DATA(CCircDlg) + enum { IDD = IDD_CIRCPROPS }; + CComboBox m_circname; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCircDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCircDlg) + afx_msg void OnSelchangeCircname(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/CircProp.cpp b/femm/CircProp.cpp new file mode 100644 index 0000000..30198a3 --- /dev/null +++ b/femm/CircProp.cpp @@ -0,0 +1,95 @@ +// CircProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCircProp dialog + + +CCircProp::CCircProp(CWnd* pParent /*=NULL*/) + : CDialog(CCircProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCircProp) + m_circname = _T(""); + m_totcurrent = 0; + //}}AFX_DATA_INIT +} + + +void CCircProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCircProp) + DDX_Text(pDX, IDC_CIRCNAME, m_circname); + DDX_Text(pDX, IDC_TOTCURRENT_RE, m_totcurrent); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CIRCNAME, m_idc_circname); + DDX_Control(pDX, IDC_TOTCURRENT_RE, m_idc_totcurrent_re); +} + + +BEGIN_MESSAGE_MAP(CCircProp, CDialog) + //{{AFX_MSG_MAP(CCircProp) + ON_BN_CLICKED(IDC_RADIOAMP, OnRadioamp) + ON_BN_CLICKED(IDC_RADIOVOLT, OnRadiovolt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCircProp message handlers + +void CCircProp::OnRadioamp() +{ + m_circtype=0; +} + +void CCircProp::OnRadiovolt() +{ + m_circtype=1; +} + +BOOL CCircProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + SetEm=IDC_RADIOAMP; + if(m_circtype==1){ + SetEm=IDC_RADIOVOLT; + OnRadiovolt(); + } + else OnRadioamp(); + + CheckRadioButton( + IDC_RADIOVOLT,// identifier of first radio button in group + IDC_RADIOAMP, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CCircProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(CCircProp) + enum { IDD = IDD_CIRCPROP }; + CString m_circname; + CComplex m_totcurrent; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCircProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCircProp) + afx_msg void OnRadioamp(); + afx_msg void OnRadiovolt(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_idc_circname, m_idc_totcurrent_re; +}; diff --git a/femm/CopyDlg.cpp b/femm/CopyDlg.cpp new file mode 100644 index 0000000..613c0b4 --- /dev/null +++ b/femm/CopyDlg.cpp @@ -0,0 +1,113 @@ +// CopyDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "CopyDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCopyDlg dialog + + +CCopyDlg::CCopyDlg(CWnd* pParent /*=NULL*/) + : CDialog(CCopyDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCopyDlg) + m_aboutx = 0.0; + m_abouty = 0.0; + m_deltax = 0.0; + m_deltay = 0.0; + m_shiftangle = 0.0; + m_ncopies = 0; + //}}AFX_DATA_INIT +} + + +void CCopyDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCopyDlg) + DDX_Text(pDX, IDC_ABOUTX, m_aboutx); + DDX_Text(pDX, IDC_ABOUTY, m_abouty); + DDX_Text(pDX, IDC_DELTAX, m_deltax); + DDX_Text(pDX, IDC_DELTAY, m_deltay); + DDX_Text(pDX, IDC_SHIFTANGLE, m_shiftangle); + DDX_Text(pDX, IDC_NCOPIES, m_ncopies); + DDV_MinMaxInt(pDX, m_ncopies, 0, 100); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_ABOUTX, m_IDC_aboutx); + DDX_Control(pDX, IDC_ABOUTY, m_IDC_abouty); + DDX_Control(pDX, IDC_DELTAX, m_IDC_deltax); + DDX_Control(pDX, IDC_DELTAY, m_IDC_deltay); + DDX_Control(pDX, IDC_SHIFTANGLE, m_IDC_shiftangle); + DDX_Control(pDX, IDC_NCOPIES, m_IDC_ncopies); +} + + +BEGIN_MESSAGE_MAP(CCopyDlg, CDialog) + //{{AFX_MSG_MAP(CCopyDlg) + ON_BN_CLICKED(IDC_ROTATE, OnRotate) + ON_BN_CLICKED(IDC_TRANSLATE, OnTranslate) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCopyDlg message handlers + +BOOL CCopyDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if (IsMove==TRUE){ + SetWindowText("Move"); + SendDlgItemMessage(IDC_NCOPIES,WM_ENABLE,FALSE,0); + } + else SetWindowText("Copy"); + + + CheckRadioButton( + IDC_ROTATE,// identifier of first radio button in group + IDC_TRANSLATE, // identifier of last radio button in group + IDC_TRANSLATE // identifier of radio button to select + ); + + OnTranslate(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CCopyDlg::OnOK() +{ + // TODO: Add extra validation here + + CDialog::OnOK(); +} + +void CCopyDlg::OnRotate() +{ + // TODO: Add your control notification handler code here + BtnState=0; + SendDlgItemMessage(IDC_SHIFTANGLE,WM_ENABLE,TRUE,0); + SendDlgItemMessage(IDC_ABOUTX,WM_ENABLE,TRUE,0); + SendDlgItemMessage(IDC_ABOUTY,WM_ENABLE,TRUE,0); + SendDlgItemMessage(IDC_DELTAX,WM_ENABLE,FALSE,0); + SendDlgItemMessage(IDC_DELTAY,WM_ENABLE,FALSE,0); +} + +void CCopyDlg::OnTranslate() +{ + // TODO: Add your control notification handler code here + BtnState=1; + SendDlgItemMessage(IDC_SHIFTANGLE,WM_ENABLE,FALSE,0); + SendDlgItemMessage(IDC_ABOUTX,WM_ENABLE,FALSE,0); + SendDlgItemMessage(IDC_ABOUTY,WM_ENABLE,FALSE,0); + SendDlgItemMessage(IDC_DELTAX,WM_ENABLE,TRUE,0); + SendDlgItemMessage(IDC_DELTAY,WM_ENABLE,TRUE,0); +} diff --git a/femm/CopyDlg.h b/femm/CopyDlg.h new file mode 100644 index 0000000..14be0ce --- /dev/null +++ b/femm/CopyDlg.h @@ -0,0 +1,48 @@ +// CopyDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCopyDlg dialog + +class CCopyDlg : public CDialog +{ +// Construction +public: + CCopyDlg(CWnd* pParent = NULL); // standard constructor + int BtnState; + BOOL IsMove; + +// Dialog Data + //{{AFX_DATA(CCopyDlg) + enum { IDD = IDD_COPYDLG }; + double m_aboutx; + double m_abouty; + double m_deltax; + double m_deltay; + double m_shiftangle; + int m_ncopies; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCopyDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCopyDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnRotate(); + afx_msg void OnTranslate(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_aboutx, m_IDC_abouty, m_IDC_deltax; + CLuaEdit m_IDC_deltay, m_IDC_shiftangle, m_IDC_ncopies; +}; diff --git a/femm/CplotDlg2.cpp b/femm/CplotDlg2.cpp new file mode 100644 index 0000000..7349821 --- /dev/null +++ b/femm/CplotDlg2.cpp @@ -0,0 +1,65 @@ +// CplotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "CplotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCplotDlg2 dialog + + +CCplotDlg2::CCplotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(CCplotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCplotDlg2) + m_numcontours = 0; + m_showa = FALSE; + m_ahigh = 0.0; + m_alow = 0.0; + m_showmask = FALSE; + //}}AFX_DATA_INIT +} + + +void CCplotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCplotDlg2) + DDX_Text(pDX, IDC_NUMCONTOURS, m_numcontours); + DDV_MinMaxInt(pDX, m_numcontours, 4, 999); + DDX_Check(pDX, IDC_SHOW_A, m_showa); + DDX_Text(pDX, IDC_AHIGH, m_ahigh); + DDX_Text(pDX, IDC_ALOW, m_alow); + DDX_Check(pDX, IDC_SHOW_MASK2, m_showmask); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_NUMCONTOURS, m_IDC_numcontours); + DDX_Control(pDX, IDC_AHIGH, m_IDC_ahigh); + DDX_Control(pDX, IDC_ALOW, m_IDC_alow); +} + + +BEGIN_MESSAGE_MAP(CCplotDlg2, CDialog) + //{{AFX_MSG_MAP(CCplotDlg2) + ON_BN_CLICKED(IDC_DFLT1, OnDflt1) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCplotDlg2 message handlers + +void CCplotDlg2::OnDflt1() +{ + // TODO: Add your control notification handler code here + UpdateData(TRUE); + m_alow=Alb; + m_ahigh=Aub; + m_numcontours=19; + UpdateData(FALSE); +} diff --git a/femm/CplotDlg2.h b/femm/CplotDlg2.h new file mode 100644 index 0000000..3208d70 --- /dev/null +++ b/femm/CplotDlg2.h @@ -0,0 +1,42 @@ +// CplotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCplotDlg2 dialog + +class CCplotDlg2 : public CDialog +{ +// Construction +public: + CCplotDlg2(CWnd* pParent = NULL); // standard constructor + double Alb,Aub; + +// Dialog Data + //{{AFX_DATA(CCplotDlg2) + enum { IDD = IDD_CPLOTDLG2 }; + int m_numcontours; + BOOL m_showa; + double m_ahigh; + double m_alow; + BOOL m_showmask; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCplotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCplotDlg2) + afx_msg void OnDflt1(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_numcontours, m_IDC_ahigh, m_IDC_alow; +}; diff --git a/femm/DXFImport.cpp b/femm/DXFImport.cpp new file mode 100644 index 0000000..42306e0 --- /dev/null +++ b/femm/DXFImport.cpp @@ -0,0 +1,44 @@ +// DXFImport.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "DXFImport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDXFImport dialog + + +CDXFImport::CDXFImport(CWnd* pParent /*=NULL*/) + : CDialog(CDXFImport::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDXFImport) + m_dxftol = 0.0; + //}}AFX_DATA_INIT +} + + +void CDXFImport::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDXFImport) + DDX_Text(pDX, IDC_DXFTOL, m_dxftol); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_DXFTOL, m_IDC_dxftol); +} + + +BEGIN_MESSAGE_MAP(CDXFImport, CDialog) + //{{AFX_MSG_MAP(CDXFImport) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDXFImport message handlers diff --git a/femm/DXFImport.h b/femm/DXFImport.h new file mode 100644 index 0000000..15c1f39 --- /dev/null +++ b/femm/DXFImport.h @@ -0,0 +1,39 @@ +// DXFImport.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDXFImport dialog + +class CDXFImport : public CDialog +{ +// Construction +public: + CDXFImport(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDXFImport) + enum { IDD = IDD_DXFIMPORT }; + double m_dxftol; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDXFImport) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDXFImport) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_dxftol; + +}; diff --git a/femm/EnterPt.cpp b/femm/EnterPt.cpp new file mode 100644 index 0000000..9a5261a --- /dev/null +++ b/femm/EnterPt.cpp @@ -0,0 +1,52 @@ +// EnterPt.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "EnterPt.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CEnterPt dialog + + +CEnterPt::CEnterPt(CWnd* pParent /*=NULL*/) + : CDialog(CEnterPt::IDD, pParent) +{ + //{{AFX_DATA_INIT(CEnterPt) + m_coord1 = 0.0; + m_coord2 = 0.0; + m_label1 = _T(""); + m_label2 = _T(""); + //}}AFX_DATA_INIT +} + +void CEnterPt::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CEnterPt) + DDX_Text(pDX, IDC_COORD1, m_coord1); + DDX_Text(pDX, IDC_COORD2, m_coord2); + DDX_Text(pDX, IDC_LABEL1, m_label1); + DDX_Text(pDX, IDC_LABEL2, m_label2); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_COORD1, m_IDC_coord1); + DDX_Control(pDX, IDC_COORD2, m_IDC_coord2); +} + + +BEGIN_MESSAGE_MAP(CEnterPt, CDialog) + //{{AFX_MSG_MAP(CEnterPt) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CEnterPt message handlers + diff --git a/femm/EnterPt.h b/femm/EnterPt.h new file mode 100644 index 0000000..d1a23a6 --- /dev/null +++ b/femm/EnterPt.h @@ -0,0 +1,40 @@ +// EnterPt.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CEnterPt dialog + +class CEnterPt : public CDialog +{ +// Construction +public: + CEnterPt(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CEnterPt) + enum { IDD = IDD_ENTERPT }; + double m_coord1; + double m_coord2; + CString m_label1; + CString m_label2; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEnterPt) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CEnterPt) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_coord1, m_IDC_coord2; +}; diff --git a/femm/ExteriorProps.cpp b/femm/ExteriorProps.cpp new file mode 100644 index 0000000..c5d8d63 --- /dev/null +++ b/femm/ExteriorProps.cpp @@ -0,0 +1,50 @@ +// ExteriorProps.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "ExteriorProps.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CExteriorProps dialog + + +CExteriorProps::CExteriorProps(CWnd* pParent /*=NULL*/) + : CDialog(CExteriorProps::IDD, pParent) +{ + //{{AFX_DATA_INIT(CExteriorProps) + m_Ri = 0.0; + m_Ro = 0.0; + m_Zo = 0.0; + //}}AFX_DATA_INIT +} + + +void CExteriorProps::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CExteriorProps) + DDX_Text(pDX, IDC_RI, m_Ri); + DDX_Text(pDX, IDC_RO, m_Ro); + DDX_Text(pDX, IDC_ZO, m_Zo); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_RO, m_IDC_RO); + DDX_Control(pDX, IDC_RI, m_IDC_RI); + DDX_Control(pDX, IDC_ZO, m_IDC_ZO); +} + + +BEGIN_MESSAGE_MAP(CExteriorProps, CDialog) + //{{AFX_MSG_MAP(CExteriorProps) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CExteriorProps message handlers diff --git a/femm/ExteriorProps.h b/femm/ExteriorProps.h new file mode 100644 index 0000000..b8be07c --- /dev/null +++ b/femm/ExteriorProps.h @@ -0,0 +1,51 @@ +#if !defined(AFX_EXTERIORPROPS_H__1854BB86_0B6A_4F9B_9407_F5D2B109EF17__INCLUDED_) +#define AFX_EXTERIORPROPS_H__1854BB86_0B6A_4F9B_9407_F5D2B109EF17__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ExteriorProps.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CExteriorProps dialog + +class CExteriorProps : public CDialog +{ +// Construction +public: + CExteriorProps(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CExteriorProps) + enum { IDD = IDD_EXTERIORPROPS }; + double m_Ri; + double m_Ro; + double m_Zo; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CExteriorProps) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CExteriorProps) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_RO, m_IDC_RI, m_IDC_ZO; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EXTERIORPROPS_H__1854BB86_0B6A_4F9B_9407_F5D2B109EF17__INCLUDED_) diff --git a/femm/FemmeDoc.cpp b/femm/FemmeDoc.cpp new file mode 100644 index 0000000..e9ec1a0 --- /dev/null +++ b/femm/FemmeDoc.cpp @@ -0,0 +1,3130 @@ +// 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) 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FemmeDoc.h : header file +// +#include "nosebl.h" + +#include "lua.h" +#include "luaconsoledlg.h" +#include "luadebug.h" + +extern CFemmApp theApp; // + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDoc document + +class CFemmeDoc : public CDocument +{ +protected: + CFemmeDoc(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CFemmeDoc) + +// Attributes +public: + + // General problem attributes + double Frequency; + double Precision; + double MinAngle; + int SmartMesh; + double Depth; + int LengthUnits; + int ACSolver; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL NoDraw; + CString PrevSoln; + int PrevType; + + // default behaviors + double d_prec; + double d_minangle; + double d_freq; + double d_depth; + int d_coord; + int d_length; + int d_type; + int d_solver; + + CString BinDir; + + // lists of nodes, segments, and block labels + CArray< CNode, CNode&> nodelist; + CArray< CSegment, CSegment&> linelist; + CArray< CArcSegment, CArcSegment&> arclist; + CArray< CBlockLabel, CBlockLabel&> blocklist; + + // lists of nodes, segments, and block labels for undo purposes... + CArray< CNode, CNode&> undonodelist; + CArray< CSegment, CSegment&> undolinelist; + CArray< CArcSegment, CArcSegment&> undoarclist; + CArray< CBlockLabel, CBlockLabel&> undoblocklist; + + // CArrays containing the mesh information + CArray< CPoint, CPoint&> meshline; + CArray< CPoint, CPoint&> greymeshline; + CArray< CNode, CNode&> meshnode; + + // lists of properties + CArray< CMaterialProp, CMaterialProp& > blockproplist; + CArray< CBoundaryProp, CBoundaryProp& > lineproplist; + CArray< CPointProp, CPointProp& > nodeproplist; + CArray< CCircuit, CCircuit& > circproplist; + double extRo,extRi,extZo; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmeDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmeDoc(); + + void UnselectAll(); + double ShortestDistance(double p, double q, int segm); + BOOL AddNode(double x, double y, double d); + BOOL AddSegment(int n0, int n1, double tol=0); + BOOL AddSegment(int n0, int n1, CSegment *parsegm, double tol=0); + BOOL AddArcSegment(CArcSegment &asegm, double tol=0); + BOOL AddBlockLabel(double x, double y, double d); + BOOL AddNode(CNode &node, double d); + BOOL AddSegment(CComplex p0, CComplex p1, CSegment &segm, double tol=0); + BOOL AddArcSegment(CComplex p0, CComplex p1, CArcSegment &asegm, double tol=0); + BOOL AddBlockLabel(CBlockLabel &blabel, double d); + int ClosestNode(double x, double y); + int ClosestBlockLabel(double x, double y); + int ClosestSegment(double x, double y); + BOOL GetIntersection(int n0, int n1, int segm, double *xi, double *yi); + int ClosestArcSegment(double x, double y); + void GetCircle(CArcSegment &asegm,CComplex &c, double &R); + int GetLineArcIntersection(CSegment &seg, CArcSegment &arc, CComplex *p); + int GetArcArcIntersection(CArcSegment &arc1, CArcSegment &arc2, CComplex *p); + double ShortestDistanceFromArc(CComplex p, CArcSegment &arc); + void RotateMove(CComplex c, double t, int EditAction); + void TranslateMove(double dx, double dy, int EditAction); + void ScaleMove(double bx, double by, double sf, int EditAction); + void MirrorSelected(double x0, double y0, double x1, double y1, int ea); + void RotateCopy(CComplex c, double t, int ncopies, int EditAction); + void TranslateCopy(double dx, double dy, int ncopies, int EditAction); + BOOL DeleteSelectedNodes(); + BOOL DeleteSelectedSegments(); + BOOL DeleteSelectedArcSegments(); + BOOL DeleteSelectedBlockLabels(); + BOOL OpBlkDlg(); + void OpNodeDlg(); + void OpSegDlg(); + void OpArcSegDlg(); + void OpGrpDlg(); + BOOL LoadMesh(); + BOOL OnWritePoly(); + BOOL FunnyOnWritePoly(); + BOOL ReadDXF(CString fname, double DefTol=-1.); + BOOL WriteDXF(CString fname); + BOOL OldOnOpenDocument(LPCTSTR lpszPathName); + BOOL HasPeriodicBC(); + BOOL CanCreateRadius(int n); + BOOL CreateRadius(int n, double r); + double LineLength(int i); + BOOL ScanPreferences(); + + void UpdateUndo(); + void Undo(); + void EnforcePSLG(); // makes sure that everything is kosher... + void EnforcePSLG(double tol); + void FancyEnforcePSLG(double tol); + BOOL SelectOrphans(); + BOOL dxf_line_hook(); + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions +protected: + //{{AFX_MSG(CFemmeDoc) + afx_msg void OnDefineProblem(); + afx_msg void OnEditMatprops(); + afx_msg void OnEditPtprops(); + afx_msg void OnEditSegprops(); + afx_msg void OnEditCircprops(); + afx_msg void OnEditExterior(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnViewLuaConsole(); + + void initalise_lua(); + static int lua_prob_def(lua_State *L); + static int luaSaveDocument(lua_State *L); + static int lua_create_mesh(lua_State *L); + static int lua_smartmesh(lua_State *L); + static int lua_purge_mesh(lua_State *L); + static int lua_show_mesh(lua_State *L); + static int lua_analyze(lua_State *L); + static int lua_runpost(lua_State *L); + static int lua_addnode(lua_State *L); + static int lua_addlabel(lua_State *L); + static int lua_addline(lua_State *L); + static int lua_addarc(lua_State *L); + static int lua_selectnode(lua_State *L); + static int lua_selectlabel(lua_State *L); + static int lua_selectsegment(lua_State *L); + static int lua_selectarcsegment(lua_State *L); + static int lua_clearselected(lua_State *L); + static int lua_setnodeprop(lua_State *L); + static int lua_setblockprop(lua_State *L); + static int lua_setsegmentprop(lua_State *L); + static int lua_setarcsegmentprop(lua_State *L); + static int lua_deleteselected(lua_State *L); + static int lua_deleteselectedsegments(lua_State *L); + static int lua_deleteselectednodes(lua_State *L); + static int lua_deleteselectedlabels(lua_State *L); + static int lua_deleteselectedarcsegments(lua_State *L); + static int lua_zoomout(lua_State *L); + static int lua_zoomnatural(lua_State *L); + static int lua_zoomin(lua_State *L); + static int lua_move_translate(lua_State *L); + static int lua_move_rotate(lua_State *L); + static int lua_copy_translate(lua_State *L); + static int lua_copy_rotate(lua_State *L); + static int lua_mirror(lua_State *L); + static int lua_scale(lua_State *L); + static int lua_addmatprop(lua_State *L); + static int lua_addpointprop(lua_State *L); + static int lua_addboundprop(lua_State *L); + static int lua_addcircuitprop(lua_State *L); + static int lua_delcircuitprop(lua_State *L); + static int lua_delpointprop(lua_State *L); + static int lua_delboundprop(lua_State *L); + static int lua_delmatprop(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_selectgroup(lua_State *L); + static int lua_zoom(lua_State *L); + static int lua_newdocument(lua_State *L); + static int lua_savebitmap(lua_State * L); + static int lua_modmatprop(lua_State *L); + static int lua_modboundprop(lua_State *L); + static int lua_modpointprop(lua_State *L); + static int lua_modcircprop(lua_State *L); + static int lua_exitpre(lua_State *L); + static int lua_addbhpoint(lua_State *L); + static int lua_clearbhpoints(lua_State *L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC); + static int lua_saveWMF(lua_State *L); + static int lua_updatewindow(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_showgrid(lua_State *L); + static int lua_hidegrid(lua_State *L); + static int lua_gridsnap(lua_State *L); + static int lua_setgrid(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int lua_readdxf(lua_State *L); + static int lua_savedxf(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_defineouterspace(lua_State *L); + static int lua_attachouterspace(lua_State *L); + static int lua_detachouterspace(lua_State *L); + static int lua_attachdefault(lua_State *L); + static int lua_detachdefault(lua_State *L); + static int lua_createradius(lua_State *L); + static int lua_gettitle(lua_State *L); + static int lua_setgroup(lua_State *L); + static int lua_getmaterial(lua_State *L); + static int lua_getprobleminfo(lua_State *L); + static int lua_getboundingbox(lua_State *L); + static int lua_selectcircle(lua_State *L); + static int lua_selectrectangle(lua_State *L); + static int lua_previous(lua_State *L); + static int old_lua_addmatprop(lua_State *L); + static int old_lua_modmatprop(lua_State *L); + static int old_lua_addpointprop(lua_State *L); + static int old_lua_modpointprop(lua_State *L); + static int old_lua_addcircuitprop(lua_State *L); + static int old_lua_modcircprop(lua_State *L); +}; + +char* StripKey(char *c); + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FEMMEDOC_H__C8BAD1A9_C080_4CB6_9B9D_1F22718D3551__INCLUDED_) diff --git a/femm/FemmeView.cpp b/femm/FemmeView.cpp new file mode 100644 index 0000000..8a629ea --- /dev/null +++ b/femm/FemmeView.cpp @@ -0,0 +1,3373 @@ +// FemmeView.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "FemmeDoc.h" +#include "FemmeView.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "GRIDDLG.h" +#include "EnterPt.h" +#include "KbdZoom.h" +#include "ArcDlg.h" +#include "CopyDlg.h" +#include "fe_libdlg.h" +#include "scaledlg.h" +#include "MirrorDlg.h" +#include "GroupNumber.h" +#include "PromptBox.h" +#include "MakeABCDlg.h" + +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +int Xm,Ym; + +extern lua_State * lua; +extern BOOL bLinehook; +extern HANDLE hProc; + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView + +IMPLEMENT_DYNCREATE(CFemmeView, CView) + +BEGIN_MESSAGE_MAP(CFemmeView, CView) + //{{AFX_MSG_MAP(CFemmeView) + ON_COMMAND(ID_NODE_OP, OnNodeOp) + ON_COMMAND(ID_SEGMENT_OP, OnSegmentOp) + ON_COMMAND(ID_BLOCK_OP, OnBlockOp) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_WM_KEYDOWN() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWnd) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_MAKE_MESH, OnMakeMesh) + ON_COMMAND(ID_MENU_ANALYZE, OnMenuAnalyze) + ON_COMMAND(ID_MENU_VIEWRES, OnMenuViewres) + ON_COMMAND(ID_ARCSEG_OP, OnArcsegOp) + ON_COMMAND(ID_UNDO, OnUndo) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_COMMAND(ID_MOVE_OBJECTS, OnMoveObjects) + ON_COMMAND(ID_COPY_OBJECTS, OnCopyObjects) + ON_COMMAND(ID_DXFIN, OnDxfin) + ON_COMMAND(ID_PURGEMESH, OnPurgemesh) + ON_COMMAND(ID_DXFWRITE, OnDxfwrite) + ON_COMMAND(ID_SELECTWND, OnSelectwnd) + ON_WM_ERASEBKGND() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_MENU_MATLIB, OnMenuMatlib) + ON_COMMAND(ID_GROUP_OP, OnGroupOp) + ON_COMMAND(ID_OPEN_SELECTED, OnOpenSelected) + ON_COMMAND(ID_EDIT_SCALE, OnEditScale) + ON_COMMAND(ID_EDIT_MIRROR, OnEditMirror) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames) + ON_COMMAND(ID_FD_SELECTCIRC, OnFDSelectCirc) + ON_COMMAND(ID_VIEW_SHOWORPHANS, OnViewShowOrphans) + ON_COMMAND(ID_CREATERADIUS, OnCreateRadius) + ON_UPDATE_COMMAND_UI(ID_EDIT_EXTERIOR, OnUpdateEditExterior) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_COMMAND(ID_EDIT_CREATEOPENBOUNDARY, &CFemmeView::OnMakeABC) +END_MESSAGE_MAP() + +CFemmeView::~CFemmeView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView construction/destruction + +CFemmeView::CFemmeView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // Default Colors + SelColor = dSelColor; + MeshColor = dMeshColor; + BlockColor = dBlockColor; + LineColor = dLineColor; + GridColor = dGridColor; + NodeColor = dNodeColor; + BackColor = dBackColor; + NameColor = dNameColor; + + // assume some default behaviors if they can't be + // loaded from disk + d_action=0; + d_mag=100.; + d_gridsize=0.25; + d_showgrid=TRUE; + d_snapgrid=FALSE; + d_showorigin=FALSE; + d_shownames=TRUE; + + // Load an updated color map, if it exists + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // now, set default look for the preprocessor; + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + CreateRadiusFlag=FALSE; + SelectCircFlag=FALSE; + MaxSeg = 1.0; + ArcAngle = 90.0; +} + +void CFemmeView::OnNewDocument() +{ + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + CreateRadiusFlag=FALSE; + SelectCircFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) return; + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + if (StatBar==NULL) return; + + // update check boxes in the main menu... + EditAction=d_action; + GridFlag=d_showgrid; + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(d_action==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(d_action==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(d_action==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(d_action==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(d_action==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(d_showgrid==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(d_snapgrid==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(d_shownames==TRUE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } + +} + +BOOL CFemmeView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView drawing + +void CFemmeView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +void CFemmeView::DrawPSLG() +{ + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen,penMesh; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penBlack.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + + CFemmeDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + + // make sure all the right boxes are checked. + { + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r); + if(d_showorigin==TRUE) + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penBlack ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlack ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw node block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + /* + // zoom-safe replacement + CComplex p; + int kmax; + MyMoveTo(pDC,xs+j,ys); + kmax=(int) (2.*PI*((double) j)/5.); + if (kmax>36) kmax=36; + if ((kmax<8) && (kmax>0)) kmax=8; + for(k=1;k<=kmax;k++) + { + p=exp(I*k*2.*PI/((double) kmax))*((double) j); + MyLineTo(pDC,xs+((int) Re(p)),ys+((int) Im(p))); + } + */ + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + // draw a line indicating the magnetization direction; + for(j=0,k=-1;jblockproplist.GetSize();j++) + if (pDoc->blocklist[i].BlockType==pDoc->blockproplist[j].BlockName) + k=j; + if (k>=0) + if ((pDoc->blockproplist[k].H_c!=0) && + (pDoc->blocklist[i].MagDirFctn.GetLength()==0)) + { + int vx,vy; + CComplex ar; + ar=(cos(pDoc->blocklist[i].MagDir*PI/180))+ + I*(sin(pDoc->blocklist[i].MagDir*PI/180)); + vx=xs - ((int) (10.*ar.re)); + vy=ys + ((int) (10.*ar.im)); + MyMoveTo(pDC,vx,vy); + vx=xs + ((int) (10.*ar.re)); + vy=ys - ((int) (10.*ar.im)); + MyLineTo(pDC,vx,vy); + ar/=(1.+I)/sqrt(2.); + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + MyMoveTo(pDC,vx,vy); + ar*=I; + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + } + + if(ShowNames){ + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + + pDC->SetTextAlign(TA_TOP); + for(k=0,lbl="";kcircproplist.GetSize();k++) + if (pDoc->circproplist[k].CircName==pDoc->blocklist[i].InCircuit) + { + if(pDoc->circproplist[k].CircType==1) + lbl.Format("[%s:%i]",pDoc->circproplist[k].CircName, + pDoc->blocklist[i].Turns); + else lbl="["+pDoc->blocklist[i].InCircuit+"]"; + } + pDC->TextOut(xs+5,ys,lbl); + } + + pDC->SelectObject( pOldPen ); + } + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + + ReleaseDC(pDC); +} + +BOOL CFemmeView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CFemmeView::OnDraw(CDC* pDC) +{ + CFemmeDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if(pDoc->NoDraw==TRUE) return; + + // TODO: add draw code for native data here + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + if (pDoc->FirstDraw==TRUE) OnZoomNatural(); + + CPen *pOldPen; + CPen penBlue,penRed,penNode,penGreen,penMesh,penGrey; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penGrey.CreatePen(PS_SOLID,1,RGB(220,220,220)); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=1.1; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + if(MeshFlag==TRUE) + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penNode ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + pOldPen = pDC->SelectObject( &penMesh); + for(i=0;imeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->meshline[i].x].xs, + pDoc->meshnode[pDoc->meshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->meshline[i].y].xs, + pDoc->meshnode[pDoc->meshline[i].y].ys); + + } + pDC->SelectObject( pOldPen ); + + pOldPen = pDC->SelectObject( &penGrey); + for(i=0;igreymeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].x].xs, + pDoc->meshnode[pDoc->greymeshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].y].xs, + pDoc->meshnode[pDoc->greymeshline[i].y].ys); + + } + pDC->SelectObject( pOldPen ); + + } + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + +/* + // zoom-safe replacement + CComplex p; + int kmax; + MyMoveTo(pDC,xs+j,ys); + kmax=(int) (2.*PI*((double) j)/5.); + if (kmax>36) kmax=36; + if ((kmax<8) && (kmax>0)) kmax=8; + for(k=1;k<=kmax;k++) + { + p=exp(I*k*2.*PI/((double) kmax))*((double) j); + MyLineTo(pDC,xs+((int) Re(p)),ys+((int) Im(p))); + } +*/ + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + // draw a line indicating the magnetization direction; + for(j=0,k=-1;jblockproplist.GetSize();j++) + if (pDoc->blocklist[i].BlockType==pDoc->blockproplist[j].BlockName) + k=j; + if (k>=0) + if ((pDoc->blockproplist[k].H_c!=0) && + (pDoc->blocklist[i].MagDirFctn.GetLength()==0)) + { + int vx,vy; + CComplex ar; + ar=(cos(pDoc->blocklist[i].MagDir*PI/180))+ + I*(sin(pDoc->blocklist[i].MagDir*PI/180)); + vx=xs - ((int) (10.*ar.re)); + vy=ys + ((int) (10.*ar.im)); + MyMoveTo(pDC,vx,vy); + vx=xs + ((int) (10.*ar.re)); + vy=ys - ((int) (10.*ar.im)); + MyLineTo(pDC,vx,vy); + ar/=(1.+I)/sqrt(2.); + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + MyMoveTo(pDC,vx,vy); + ar*=I; + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + + pDC->SetTextAlign(TA_TOP); + for(k=0,lbl="";kcircproplist.GetSize();k++) + if (pDoc->circproplist[k].CircName==pDoc->blocklist[i].InCircuit) + { + if(pDoc->circproplist[k].CircType==1) + lbl.Format("[%s:%i]",pDoc->circproplist[k].CircName, + pDoc->blocklist[i].Turns); + else lbl="["+pDoc->blocklist[i].InCircuit+"]"; + } + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); +} + +void CFemmeView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + EditAction=d_action; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + + CheckIt(); +} + +void CFemmeView::CheckIt() +{ + // once again, this is sort of a punt + // to make sure that the right buttons + // are checked. It can be relatively + // easy to change the internal flags + // associated with the buttons without + // taking the time to service the button + // state otherwise. + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + + // update check boxes in the main menu... + + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(EditAction==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(EditAction==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(EditAction==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(EditAction==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(EditAction==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(GridFlag==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(SnapFlag==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(ShowNames==TRUE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView printing + +BOOL CFemmeView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CFemmeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CFemmeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView diagnostics + +#ifdef _DEBUG +void CFemmeView::AssertValid() const +{ + CView::AssertValid(); +} + +void CFemmeView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CFemmeDoc* CFemmeView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFemmeDoc))); + return (CFemmeDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView message handlers + +void CFemmeView::OnNodeOp() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,TRUE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CFemmeView::OnSegmentOp() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=1; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,TRUE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CFemmeView::OnArcsegOp() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=3; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,TRUE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} +void CFemmeView::OnBlockOp() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,TRUE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + + +void CFemmeView::OnGroupOp() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=4; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,TRUE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CFemmeView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CFemmeDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ( (SnapFlag==TRUE) && ((EditAction==0) || (EditAction==2)) ) + { + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + if((ZoomWndFlag==2) || (SelectWndFlag==2)){ + + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + + } + + if(SelectCircFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + double R; + CComplex q; + + int xso,yso,xsi,ysi,xsn,ysn,i,k; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old circle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + R=abs((xso-xsn)+I*(yso-ysn)); + for(i=1;i<=(int)(2.*PI*R);i++){ + q=R*exp(I*((double) i)/R)+(xso+I*yso); + ocol=pDC->GetPixel((int) Re(q),(int) Im(q)); + p.c=ocol; p.x=(int) Re(q); p.y=(int) Im(q); + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel((int) Re(q),(int) Im(q),ocol); + } + + ReleaseDC(pDC); + + } + + + // update mouse location; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CFemmeView::OnZoomIn() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + InvalidateRect(NULL); +} + +void CFemmeView::OnZoomOut() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + InvalidateRect(NULL); +} + +BOOL CFemmeView::GetBoundingBox(double *x, double *y) +{ + // look at points, block labels, and arcs to get bounding box. + CFemmeDoc *pDoc=GetDocument(); + int i,j,k; + double R,dt; + CComplex p,s,c; + + if (pDoc->nodelist.GetSize()<2) return FALSE; + + x[0]=pDoc->nodelist[0].x; x[1]=pDoc->nodelist[0].x; + y[0]=pDoc->nodelist[0].y; y[1]=pDoc->nodelist[0].y; + for(i=1;inodelist.GetSize();i++) + { + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + { + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;iarclist.GetSize();i++) + { + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + return TRUE; +} + +void CFemmeView::OnZoomNatural() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + + if (GetBoundingBox(x,y)==FALSE) return; + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0]) > (y[1]-y[0])) w=(x[1]-x[0]); + else w=(y[1]-y[0]); + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-0.5)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) + pDoc->FirstDraw=FALSE; + else InvalidateRect(NULL); +} + +void CFemmeView::OnZoomWnd() +{ + // TODO: Add your command handler code here + ZoomWndFlag=TRUE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; +} + +void CFemmeView::OnSelectwnd() +{ + SelectWndFlag=TRUE; + ZoomWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,TRUE); +} + +void CFemmeView::OnFDSelectCirc() +{ + SelectCircFlag=TRUE; + SelectWndFlag=FALSE; + CreateRadiusFlag=FALSE; + ZoomWndFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_FD_SELECTCIRC,TRUE); +} + + +void CFemmeView::OnShowGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + + InvalidateRect(NULL); +} + +void CFemmeView::OnSetGrid() +{ + // TODO: Add your command handler code here + GRIDDLG pDlg; + CFemmeDoc *pDoc=GetDocument(); + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + InvalidateRect(NULL); + } +} + +void CFemmeView::OnSnapGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CFemmeView::OnShowMesh() +{ + // TODO: Add your command handler code here + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + } + else if(MeshUpToDate==TRUE){ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + } + InvalidateRect(NULL); +} + +void CFemmeView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CFemmeView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void CFemmeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Add your message handler code here and/or call default + // VK_TAB, VK_DELETE -- ones that we want to catch + CFemmeDoc *pDoc=GetDocument(); + + if (((nChar=='z') || (nChar=='Z')) && (GetKeyState(VK_CONTROL))) OnUndo(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if (nChar==VK_TAB) + { + if ((EditAction==0) || (EditAction==2)) EnterPoint(); + if (EditAction==4) + { + CGroupNumber dlg; + dlg.m_groupnumber=0; + if(dlg.DoModal()==IDOK) + { + int i,j; + j=dlg.m_groupnumber; + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + } + + if (nChar==VK_DELETE) OnEditCut(); + + if (nChar==VK_SPACE) OnOpenSelected(); + + if (nChar==VK_ESCAPE){ + pDoc->UnselectAll(); + FirstPoint=-1; + ZoomWndFlag=0; + SelectWndFlag=0; + CreateRadiusFlag=0; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + DrawPSLG(); + } + + if (nChar==VK_F3) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if (GetBoundingBox(x,y)!=FALSE) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + for (i=0;iblocklist.GetSize();i++) + { + if (pDoc->blocklist[i].MaxArea>0) pDoc->blocklist[i].MaxArea/=4.; + else if (pDoc->SmartMesh) pDoc->blocklist[i].MaxArea=DefaultMeshSize/4.; + } + InvalidateRect(NULL); + } + + if (nChar==VK_F4) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if ((GetBoundingBox(x,y)!=FALSE) && (pDoc->SmartMesh)) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + + for (i=0;iblocklist.GetSize();i++) + { + pDoc->blocklist[i].MaxArea*=4.; + if ((pDoc->blocklist[i].MaxArea>DefaultMeshSize) && (DefaultMeshSize>0)) + pDoc->blocklist[i].MaxArea=DefaultMeshSize; + } + InvalidateRect(NULL); + } + + // Call to base class... + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CFemmeView::EnterPoint() +{ + // TODO: Add your command handler code here + CEnterPt pDlg; + double x,y,t,d; + int i; + CFemmeDoc* pDoc = GetDocument(); + BOOL flag; + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + pDoc->UpdateUndo(); + + if (pDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=pDoc->nodelist[0].CC(); + p1=p0; + for(i=1;inodelist.GetSize();i++) + { + p2=pDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(x,y,d); + } + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(x,y,d); + } + + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } +} + +void CFemmeView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonDown(nFlags, point); + return; + } + + BOOL flag; + CFemmeDoc* pDoc = GetDocument(); + + if (CreateRadiusFlag==TRUE) + { + int k; + double r; + + CreateRadiusFlag=FALSE; + if ((k=pDoc->ClosestNode(mx,my))<0) return; // catch case where no nodes have been drawn yet; + if (pDoc->CanCreateRadius(k)==FALSE) + { + MsgBox("The specified point is not suitable for\nconversion into a radius"); + return; + } + + CPromptBox dlg; + dlg.mytitle = "Enter desired radius dimension:"; + if (dlg.DoModal()==IDOK) + { + r=dlg.ParseDouble(); + if (r>0){ + if (pDoc->CreateRadius(k,r)) + { + InvalidateRect(NULL); + MeshUpToDate=FALSE; + } + else MsgBox("Could not make a radius of the prescribed dimension"); + } + } + + return; + } + + if (SelectWndFlag==1) + { + ZoomPix.RemoveAll(); + SelectWndFlag++; + wzx=mx;wzy=my; + return; + } + if (SelectWndFlag==2) return; + + if (SelectCircFlag==1) + { + ZoomPix.RemoveAll(); + SelectCircFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectCircFlag==2) return; + + + if (ZoomWndFlag==1) + { + ZoomPix.RemoveAll(); + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(mx,my,1./mag); + if (flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==1){ + if (FirstPoint<0){ + if(pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + pDoc->nodelist[FirstPoint].ToggleSelect(); + pDoc->UpdateUndo(); + flag=pDoc->AddSegment(FirstPoint,pDoc->ClosestNode(mx,my)); + FirstPoint=-1; + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(mx,my,1./mag); + if(flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==3){ + if (FirstPoint<0){ + if (pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + CArcSegment asegm; + CArcDlg dlg; + asegm.n0=FirstPoint; + asegm.n1=pDoc->ClosestNode(mx,my); + pDoc->nodelist[asegm.n1].ToggleSelect(); + DrawPSLG(); + + for(int k=0;klineproplist.GetSize();k++) + dlg.namelist.Add(pDoc->lineproplist[k].BdryName); + + dlg.cursel=0; + dlg.m_MaxSeg=MaxSeg; + dlg.m_ArcAngle=ArcAngle; + if (dlg.DoModal()==IDCANCEL){ + FirstPoint=-1; + pDoc->UnselectAll(); + DrawPSLG(); + return; + } + MaxSeg = asegm.MaxSideLength = dlg.m_MaxSeg; + ArcAngle = asegm.ArcLength = dlg.m_ArcAngle; + if (dlg.cursel==0) asegm.BoundaryMarker=""; + else asegm.BoundaryMarker=pDoc->lineproplist[dlg.cursel-1].BdryName; + + pDoc->UpdateUndo(); + flag=pDoc->AddArcSegment(asegm); + flag=FALSE; + FirstPoint=-1; + pDoc->UnselectAll(); + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + CView::OnLButtonDown(nFlags, point); +} + +void CFemmeView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag==2){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + RECT r; + double z,m[2]; + if (mxGetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + int i,k; + double x,y,z; + CFemmeDoc *pDoc=GetDocument(); + SelectWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + if (SelectCircFlag==2){ + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_FD_SELECTCIRC,FALSE); + + int i,k; + double R; + CComplex c,q; + CFemmeDoc *pDoc=GetDocument(); + SelectCircFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + + R=abs((mx-wzx)+I*(my-wzy)); + c=wzx+I*wzy; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + + CView::OnLButtonUp(nFlags, point); +} + +void CFemmeView::OnRButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnRButtonDown(nFlags, point); + return; + } + + CFemmeDoc* pDoc = GetDocument(); + int i,j; + + //toggle select of nearest point + if(EditAction==0){ + j=pDoc->ClosestNode(mx,my); + if(j>=0) pDoc->nodelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest segment + if(EditAction==1){ + j=pDoc->ClosestSegment(mx,my); + if(j>=0) pDoc->linelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest arc segment + if(EditAction==3){ + j=pDoc->ClosestArcSegment(mx,my); + if(j>=0) pDoc->arclist[j].ToggleSelect(); + DrawPSLG(); + } + //toggle select of nearest blocklabel + if(EditAction==2){ + j=pDoc->ClosestBlockLabel(mx,my); + if(j>=0) pDoc->blocklist[j].ToggleSelect(); + DrawPSLG(); + } + + if(EditAction==4){ + int clnode,clseg,claseg,cllbl; + double dnode,dseg,daseg,dlbl,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // find distance to closest block label; + cllbl=pDoc->ClosestBlockLabel(mx,my); + if(cllbl>=0) dlbl=pDoc->blocklist[cllbl].GetDistance(mx,my); + else dlbl=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InGroup; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InGroup; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InGroup; + } + if ((dlbl=0)){ + d=dlbl; + j=pDoc->blocklist[cllbl].InGroup; + } + + if (j<1) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CFemmeView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CView::OnLButtonDblClk(nFlags, point); +} + +void CFemmeView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + CFemmeDoc *pDoc=GetDocument(); + if (EditAction==0) + { + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + int j; + CString ss; + + sprintf(s,"Closest node: (%g,%g)\n",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + ss+=s; + ss+="Nodal Property: "; + sprintf(s,"\n"); + for(j=0;jnodeproplist.GetSize();j++) + { + if(pDoc->nodeproplist[j].PointName== + pDoc->nodelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->nodelist[i].BoundaryMarker); + } + } + ss+=s; + sprintf(s,"In Group: %i",pDoc->nodelist[i].InGroup); + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->nodelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==1) + { + int i=pDoc->ClosestSegment(mx,my); + int j; + CString ss; + + if(i>=0){ + char s[256]; + sprintf(s,"Length of closest segment: %g\n", + pDoc->LineLength(i)); + + ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->linelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->linelist[i].BoundaryMarker); + } + } + ss+=s; + + ss+="Grid spacing: "; + if (pDoc->linelist[i].MaxSideLength<=0) + sprintf(s,"\n"); + else sprintf(s,"%g\n",pDoc->linelist[i].MaxSideLength); + ss+=s; + sprintf(s,"In Group: %i",pDoc->linelist[i].InGroup); + ss+=s; + + if(pDoc->linelist[i].Hidden==TRUE) + ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->linelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==2) + { + int i=pDoc->ClosestBlockLabel(mx,my); + int j,k; + if(i>=0){ + char s[256]; + sprintf(s,"Closest block label: (%g,%g)\n",pDoc->blocklist[i].x, + pDoc->blocklist[i].y); + CString ss=s; + ss+="Block Material: "; + k=-1; + sprintf(s,"\n"); + if (pDoc->blocklist[i].BlockType=="") + { + sprintf(s,"\n"); + } + else for(j=0;jblockproplist.GetSize();j++) + { + if(pDoc->blockproplist[j].BlockName== + pDoc->blocklist[i].BlockType) + { + sprintf(s,"%s\n", (const char *) pDoc->blocklist[i].BlockType); + k=j; + } + } + ss+=s; + + ss+="In Circuit: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->blocklist[i].InCircuit) + { + sprintf(s,"%s\n", (const char *) pDoc->blocklist[i].InCircuit); + } + } + ss+=s; + + ss+="Mesh size: "; + if (pDoc->blocklist[i].MaxArea==0) + sprintf(s,"\n"); + else sprintf(s,"%g\n", + floor(2.e07*sqrt(pDoc->blocklist[i].MaxArea/PI) + +0.5)/1.e07 ); + ss+=s; + + sprintf(s,"In Group: %i",pDoc->blocklist[i].InGroup); + ss+=s; + + // if it has magnetized material.... + if(k>=0) + { + if(pDoc->blockproplist[k].H_c>0) + { + sprintf(s,"\nMag Direction: %g deg", + pDoc->blocklist[i].MagDir); + ss+=s; + } + } + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==3) + { + int i=pDoc->ClosestArcSegment(mx,my); + if(i>=0){ + char s[256]; + CString ss; + int j; + double R; + CComplex c; + + sprintf(s,"Angle spanned by closest arc: %g deg\n", + pDoc->arclist[i].ArcLength); ss+=s; + pDoc->GetCircle(pDoc->arclist[i],c,R); + c=Chop(c); + sprintf(s,"Radius of associated circle: %g\n",R); ss+=s; + sprintf(s,"Center of associated circle: (%g,%g)\n",Re(c),Im(c)); ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->arclist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->arclist[i].BoundaryMarker); + } + } + ss+=s; + sprintf(s,"Grid spacing: %g deg\n",pDoc->arclist[i].MaxSideLength); ss+=s; + sprintf(s,"In Group: %i",pDoc->arclist[i].InGroup); ss+=s; + if(pDoc->arclist[i].Hidden==TRUE) ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->arclist[i].ToggleSelect(); + DrawPSLG(); + } + } + CView::OnRButtonDblClk(nFlags, point); +} + +void CFemmeView::OnMakeMesh() +{ + CFemmeDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved."); + return; + } + + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + BOOL LoadMesh=TheDoc->LoadMesh(); + if (bLinehook==FALSE) EndWaitCursor(); + + if(LoadMesh==TRUE){ + MeshUpToDate=TRUE; + if(MeshFlag==FALSE) OnShowMesh(); + else InvalidateRect(NULL); + CString s; + s.Format("Created mesh with %i nodes",TheDoc->meshnode.GetSize()); + if (TheDoc->greymeshline.GetSize()!=0) + s+="\nGrey mesh lines denote regions\nthat have no block label."; + if(bLinehook==FALSE) AfxMessageBox(s,MB_ICONINFORMATION); + else lua_pushnumber(lua,(int) TheDoc->meshnode.GetSize()); + } + +} + +void CFemmeView::OnMenuAnalyze() +{ + int i,j,k; + CFemmeDoc *TheDoc = GetDocument(); + BOOL bFlag=FALSE; + BOOL bExteriorDefined=TRUE; + + ASSERT_VALID(TheDoc); + + // check to see if all blocklabels are kosher... + if (TheDoc->blocklist.GetSize()==0){ + MsgBox("No block information has been defined\nCannot analyze the problem"); + return; + } + + for(i=0,bFlag=FALSE;iblocklist.GetSize();i++) + { + for(k=0,j=0;kblockproplist.GetSize();k++) + if (TheDoc->blocklist[i].BlockType!=TheDoc->blockproplist[k].BlockName) j++; + if((j==TheDoc->blockproplist.GetSize()) && (TheDoc->blocklist[i].BlockType!="")) + { + if(bFlag==FALSE) OnBlockOp(); + bFlag=TRUE; + TheDoc->blocklist[i].IsSelected=TRUE; + } + } + + if(bFlag==TRUE){ + InvalidateRect(NULL); + CString ermsg="Material properties have not\n"; + ermsg+= "been defined for all block labels.\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + + if(TheDoc->ProblemType==1) + { + // check to see if all of the input points are on r>=0 for axisymmetric problems. + for(k=0;knodelist.GetSize();k++) + if(TheDoc->nodelist[k].x<-(1.e-6)) + { + InvalidateRect(NULL); + CString ermsg="The problem domain must lie in\n"; + ermsg+= "r>=0 for axisymmetric problems.\n"; + ermsg+= "Cannot analyze the problem."; + MsgBox(ermsg); + return; + } + + // check to see if all block defined to be in an axisymmetric external region are linear. + for(k=0;kblocklist.GetSize();k++) + { + if(TheDoc->blocklist[k].IsExternal){ + + if((TheDoc->extRo==0) || (TheDoc->extRi==0)) bExteriorDefined=FALSE; + + for(i=0;iblockproplist.GetSize();i++) + if(TheDoc->blocklist[k].BlockType==TheDoc->blockproplist[i].BlockName) + { + if(TheDoc->blockproplist[i].BHpoints!=0) bFlag=TRUE; + else if(TheDoc->blockproplist[i].mu_x!=TheDoc->blockproplist[i].mu_y) bFlag=TRUE; + } + } + } + if(bFlag) + { + InvalidateRect(NULL); + CString ermsg="Only linear istropic materials are\n"; + ermsg+= "allowed in axisymmetric external regions.\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + if(!bExteriorDefined) + { + InvalidateRect(NULL); + CString ermsg="Some block labels have been specific as placed in\n"; + ermsg+= "an axisymmetric exterior region, but no properties\n"; + ermsg+= "have been adequately defined for the exterior region\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + } + + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved."); + return; + } + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + if (bLinehook==FALSE) EndWaitCursor(); + + char CommandLine[512]; + CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; + + if(bLinehook==FALSE) + sprintf(CommandLine,"\"%sfkn.exe\" %s", (const char *) BinDir, (const char *) rootname); + else + sprintf(CommandLine,"\"%sfkn.exe\" %s bLinehook", (const char *) BinDir, (const char *) rootname); + + CString MyPath=pn.Left(pn.ReverseFind('\\')); + + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + StartupInfo2.dwFlags = STARTF_FORCEOFFFEEDBACK; + if(bLinehook==HiddenLua){ + StartupInfo2.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK; + // SHOWNOACTIVATE doesn't steal focus to others + StartupInfo2.wShowWindow = SW_SHOWMINNOACTIVE; + } + if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, + 0, NULL, MyPath, &StartupInfo2, &ProcessInfo2)) + { + if(bLinehook!=FALSE) + { + DWORD ExitCode; + hProc=ProcessInfo2.hProcess; + do{ + GetExitCodeProcess(ProcessInfo2.hProcess,&ExitCode); + ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); + Sleep(1); + } while(ExitCode==STILL_ACTIVE); + hProc=NULL; + + if (ExitCode==1) + MsgBox("Material properties have not been defined for all regions"); + if (ExitCode==2) + MsgBox("problem loading mesh"); + if (ExitCode==3) + MsgBox("problem renumbering node points"); + if (ExitCode==4) + MsgBox("couldn't allocate enough space for matrices"); + if (ExitCode==5) + MsgBox("Couldn't solve the problem"); + if (ExitCode==6) + MsgBox("couldn't write results to disk"); + if (ExitCode==7) + MsgBox("problem loading input file"); + } + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } + else + { + MsgBox("Problem executing the solver"); + return; + } + +} + +void CFemmeView::OnMenuViewres() +{ + CFemmeDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("No results to display"); + return; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".ans\""; + ((CFemmApp *) AfxGetApp())->MOCheckIfAlreadyOpen(rootname); + AfxGetApp( )->OpenDocumentFile(rootname); + +} + +void CFemmeView::OnUndo() +{ + CFemmeDoc *TheDoc = GetDocument(); + TheDoc->Undo(); + TheDoc->UnselectAll(); + InvalidateRect(NULL); +} + +void CFemmeView::OnKbdZoom() +{ + // TODO: Add your command handler code here + CFemmeDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]UpdateUndo(); + pDoc->RotateMove(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateMove(dlg.m_deltax,dlg.m_deltay,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CFemmeView::OnCopyObjects() +{ + CCopyDlg dlg; + CFemmeDoc *pDoc=GetDocument(); + + dlg.m_aboutx=0; + dlg.m_abouty=0; + dlg.m_shiftangle=0; + dlg.m_deltax=0; + dlg.m_deltay=0; + dlg.IsMove=FALSE; + dlg.m_ncopies=1; + + if(dlg.DoModal()==IDOK) + { + if(dlg.BtnState==0) // Rotate + { + pDoc->UpdateUndo(); + pDoc->RotateCopy(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateCopy(dlg.m_deltax,dlg.m_deltay,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CFemmeView::OnDxfin() +{ + CString dxffile; + CFileDialog *fname_dia; + CFemmeDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + TRUE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if(pDoc->ReadDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't read specified DXF file\nMake sure the the specified file\nis in ASCII DXF r12 format"); + pDoc->NoDraw=FALSE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } +} + +void CFemmeView::OnPurgemesh() +{ + + CFemmeDoc *pDoc=GetDocument(); + pDoc->meshnode.RemoveAll(); + pDoc->meshnode.FreeExtra(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + pDoc->meshline.FreeExtra(); + pDoc->greymeshline.FreeExtra(); + MeshUpToDate=FALSE; + if (MeshFlag==TRUE){ + MeshFlag=FALSE; + InvalidateRect(NULL); + } + +} + +void CFemmeView::OnDxfwrite() +{ + + CString dxffile; + CFileDialog *fname_dia; + CFemmeDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + FALSE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if (bLinehook==FALSE) BeginWaitCursor(); + if(pDoc->WriteDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + pDoc->FirstDraw=TRUE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't write specified DXF file"); + if (bLinehook==FALSE) EndWaitCursor(); + } +} + + +BOOL CFemmeView::OnEraseBkgnd(CDC* pDC) +{ + + // idea is to always make the background white. + // source code copied from: + // Frequently Asked Questions About Foundation Classes + + // Set brush to desired background color + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + return TRUE; + +} + +void CFemmeView::OnPanDown() +{ + + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox=ox-0.25*x/mag; + oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CFemmeView::OnPanLeft() +{ + + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CFemmeView::OnPanRight() +{ + + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CFemmeView::OnPanUp() +{ + + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox+=0.25*x/mag; + oy+=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CFemmeView::OnMenuMatlib() +{ + fe_CLibDlg dlg; + + dlg.pDoc=GetDocument(); + dlg.BinDir=BinDir; + + dlg.DoModal(); +} + +void CFemmeView::OnOpenSelected() +{ + + CFemmeDoc *pDoc=GetDocument(); + + if(EditAction==1) pDoc->OpSegDlg(); + if(EditAction==2){ + if (pDoc->OpBlkDlg()==TRUE) + InvalidateRect(NULL); + } + if(EditAction==3){ + pDoc->OpArcSegDlg(); + InvalidateRect(NULL); + } + if(EditAction==0) pDoc->OpNodeDlg(); + + if(EditAction==4) pDoc->OpGrpDlg(); + + pDoc->UnselectAll(); + DrawPSLG(); +} + +void CFemmeView::OnEditScale() +{ + + CScaleDlg dlg; + CFemmeDoc *pDoc=GetDocument(); + double x[2],y[2],R,dt; + int i,j,k; + CComplex p,s,c; + BOOL bFlag=FALSE; + + // look at points, block labels, and arcs to get bounding box. + for(i=0;inodelist.GetSize();i++) + if(pDoc->nodelist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[i].x; x[1]=x[0]; + y[0]=pDoc->nodelist[i].y; y[1]=y[0]; + } + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + if(pDoc->blocklist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->blocklist[i].x; x[1]=x[0]; + y[0]=pDoc->blocklist[i].y; y[1]=y[0]; + } + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;ilinelist.GetSize();i++) + if(pDoc->linelist[i].IsSelected==TRUE){ + for(j=0;j<2;j++){ + if(j==0) k=pDoc->linelist[i].n0; + else k=pDoc->linelist[i].n1; + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[k].x; x[1]=x[0]; + y[0]=pDoc->nodelist[k].y; y[1]=y[0]; + } + if(pDoc->nodelist[k].xnodelist[k].x; + if(pDoc->nodelist[k].x>x[1]) x[1]=pDoc->nodelist[k].x; + if(pDoc->nodelist[k].ynodelist[k].y; + if(pDoc->nodelist[k].y>y[1]) y[1]=pDoc->nodelist[k].y; + } + } + + + for(i=0;iarclist.GetSize();i++) + if(pDoc->arclist[i].IsSelected==TRUE){ + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + if(bFlag==FALSE) return; + + dlg.m_scalefactor=1.; + dlg.m_basex=(x[1]+x[0])/2.; + dlg.m_basey=(y[1]+y[0])/2.; + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->ScaleMove(dlg.m_basex,dlg.m_basey,dlg.m_scalefactor,EditAction); + InvalidateRect(NULL); + } +} + +void CFemmeView::OnEditMirror() +{ + + CMirrorDlg dlg; + CFemmeDoc *pDoc=GetDocument(); + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->MirrorSelected(dlg.m_pax,dlg.m_pay, + dlg.m_pbx,dlg.m_pby,EditAction); + InvalidateRect(NULL); + } +} + +void CFemmeView::OnEditCut() +{ + + CFemmeDoc *pDoc=GetDocument(); + BOOL flag; + + pDoc->UpdateUndo(); + if(EditAction==0) flag=pDoc->DeleteSelectedNodes(); + if(EditAction==1) flag=pDoc->DeleteSelectedSegments(); + if(EditAction==2) flag=pDoc->DeleteSelectedBlockLabels(); + if(EditAction==3) flag=pDoc->DeleteSelectedArcSegments(); + if(EditAction==4){ + flag=FALSE; + if (pDoc->DeleteSelectedSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedArcSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedNodes()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedBlockLabels()==TRUE) flag=TRUE; + } + if (flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else InvalidateRect(NULL); + } + +} + + +BOOL CFemmeView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"femme.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_mag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_shownames); + q[0]=NULL; + } + } + fclose(fp); + return TRUE; + } + + return FALSE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp) +{ + fprintf(fp,"<%s> = %i %i %i\n",cname, + GetRValue(c),GetGValue(c),GetBValue(c)); +} + +BOOL CFemmeView::WritePreferences() +{ + FILE *fp; + CString fname; + CFemmeDoc *pDoc=GetDocument(); + + fname=BinDir+"femme.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",d_action); + fprintf(fp," = %g\n",d_mag); + fprintf(fp," = %g\n",d_gridsize); + fprintf(fp," = %i\n",d_showgrid); + fprintf(fp," = %i\n",d_snapgrid); + fprintf(fp," = %i\n",d_shownames); + fprintf(fp," = %i\n",d_showorigin); + fprintf(fp," = %i\n",pDoc->d_type); + fprintf(fp," = %i\n",pDoc->d_length); + fprintf(fp," = %g\n",pDoc->d_freq); + fprintf(fp," = %g\n",pDoc->d_prec); + fprintf(fp," = %g\n",pDoc->d_minangle); + fprintf(fp," = %g\n",pDoc->d_depth); + fprintf(fp," = %i\n",pDoc->d_coord); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void CFemmeView::OnViewShownames() +{ + + ShowNames=1-ShowNames; + InvalidateRect(NULL); +} + +void CFemmeView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CFemmeView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm)MoveTo(Xm,Ym); + pDC->LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC->MoveTo((int) Re(pc), (int) Im(pc)); + pDC->LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +void CFemmeView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if (bActivate && pActivateView==this) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(1); + + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + CheckIt(); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CFemmeView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CFemmeView::OnViewShowOrphans() +{ + CFemmeDoc *pDoc=GetDocument(); + + OnGroupOp(); + pDoc->SelectOrphans(); + InvalidateRect(NULL); +} + +void CFemmeView::OnUpdateEditExterior(CCmdUI* pCmdUI) +{ + if(GetDocument()->ProblemType) pCmdUI->Enable ( TRUE); + else pCmdUI->Enable ( FALSE ); +} + +void CFemmeView::OnCreateRadius() +{ + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=TRUE; + + StatBar->SetPaneText(0,"SELECT POINT AT WHICH A RADIUS IS DESIRED",TRUE); +} +void CFemmeView::OnMakeABC() +{ + CMakeABCDlg dlg; + CFemmeDoc *pDoc=GetDocument(); + + dlg.n=0; + + double xx[2],yy[2]; + if (GetBoundingBox(xx,yy)==0) return; + + if(pDoc->ProblemType == 0) // 2D planar case + { + dlg.abcr=0.75*abs((xx[0]+I*yy[0])-(xx[1]+I*yy[1])); + dlg.abcx=(xx[0]+xx[1])/2.0; + dlg.abcy=(yy[0]+yy[1])/2.0; + } + else{ //Axi case + dlg.abcx=0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.abcr=1.5*abs(xx[1]+I*(yy[1]-yy[0])/2.0); + } + + dlg.abcn=7; // suggested default number of layers + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + CString LuaCmd; + LuaCmd.Format("mi_makeABC(%i,%g,%g,%g,%i)",dlg.abcn,dlg.abcr,dlg.abcx,dlg.abcy,dlg.n); + lua_dostring(lua,LuaCmd); + } +} diff --git a/femm/FemmeView.h b/femm/FemmeView.h new file mode 100644 index 0000000..ff2a9f9 --- /dev/null +++ b/femm/FemmeView.h @@ -0,0 +1,181 @@ +#if !defined(AFX_FEMMEVIEW_H__9D980E92_AF25_49AD_94B8_5FC96599FC59__INCLUDED_) +#define AFX_FEMMEVIEW_H__9D980E92_AF25_49AD_94B8_5FC96599FC59__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FemmeView.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CFemmeView view + +class CFemmeView : public CView +{ +protected: + CFemmeView(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CFemmeView) + +// Attributes +public: + + CFemmeDoc* GetDocument(); + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void DrawPSLG(); + void EnterPoint(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void OnNewDocument(); + void CheckIt(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL ShowNames; + BOOL MeshUpToDate; + int FirstPoint; + int ZoomWndFlag; + int SelectWndFlag; + int SelectCircFlag; + int CreateRadiusFlag; + double wzx,wzy; + double MaxSeg,ArcAngle; + + // Colors used to render the view + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF NodeColor; + COLORREF NameColor; + + // default view properties + int d_action; //=0; + double d_mag; //=100.; + double d_gridsize; //=0.25; + BOOL d_showgrid; //=TRUE; + BOOL d_snapgrid; //=FALSE; + BOOL d_showorigin; + BOOL d_shownames; + + CString BinDir; // pathname for other FEMM executables + CArray ZoomPix; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmeView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual void OnInitialUpdate(); // called first time after construct + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + void lua_zoomin(); + void lua_zoomout(); + void lua_zoomnatural(); + void lnu_show_mesh(); + void lnu_purge_mesh(); + void lnuMakeMesh(); + void lnu_analyze(int bShow); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL GetBoundingBox(double *x, double *y); + + virtual ~CFemmeView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmeView) + afx_msg void OnNodeOp(); + afx_msg void OnSegmentOp(); + afx_msg void OnBlockOp(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnZoomIn(); + afx_msg void OnZoomOut(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnEditCopy(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomWnd(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMakeMesh(); + afx_msg void OnMenuAnalyze(); + afx_msg void OnMenuViewres(); + afx_msg void OnArcsegOp(); + afx_msg void OnUndo(); + afx_msg void OnKbdZoom(); + afx_msg void OnMoveObjects(); + afx_msg void OnCopyObjects(); + afx_msg void OnDxfin(); + afx_msg void OnPurgemesh(); + afx_msg void OnDxfwrite(); + afx_msg void OnSelectwnd(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnMenuMatlib(); + afx_msg void OnGroupOp(); + afx_msg void OnOpenSelected(); + afx_msg void OnEditScale(); + afx_msg void OnEditMirror(); + afx_msg void OnEditCut(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnViewShownames(); + afx_msg void OnFDSelectCirc(); + afx_msg void OnViewShowOrphans(); + afx_msg void OnCreateRadius(); + afx_msg void OnUpdateEditExterior(CCmdUI* pCmdUI); + afx_msg void OnMakeABC(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +#ifndef _DEBUG // debug version in femmeView.cpp +inline CFemmeDoc* CFemmeView::GetDocument() + { return (CFemmeDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FEMMEVIEW_H__9D980E92_AF25_49AD_94B8_5FC96599FC59__INCLUDED_) diff --git a/femm/FemmviewDoc.cpp b/femm/FemmviewDoc.cpp new file mode 100644 index 0000000..b315b3d --- /dev/null +++ b/femm/FemmviewDoc.cpp @@ -0,0 +1,4955 @@ +// femmviewDoc.cpp : implementation of the CFemmviewDoc class +// + +#include "stdafx.h" +#include +#include +#include "problem.h" +#include "femm.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewView.h" +#include "lua.h" + +extern lua_State * lua; +extern void *pFemmviewdoc; +extern CLuaConsoleDlg *LuaConsole; +extern BOOL bLinehook; + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +char *ParseDbl(char *t, double *f); +char *ParseString(char *t, CString *s); +char *ParseInt(char *t, int *f); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewDoc + +IMPLEMENT_DYNCREATE(CFemmviewDoc, CDocument) + +BEGIN_MESSAGE_MAP(CFemmviewDoc, CDocument) + //{{AFX_MSG_MAP(CFemmviewDoc) + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewDoc construction/destruction + +double sqr(double x) +{ + return x*x; +} + +CFemmviewDoc::CFemmviewDoc() +{ + // set some default values for problem definition + d_LineIntegralPoints=400; + d_ShiftH=TRUE; + d_WeightingScheme=0; + Frequency=0.; + Depth=1/0.0254; + LengthUnits=0; + ProblemType=FALSE; + ProblemNote="Add comments here."; + PrevSoln=""; + PrevType = 0; + bIncremental=FALSE; + FirstDraw=-1; + A_High=0.; + A_Low=0.; + A_lb=0.; + A_ub=0.; + extRo=extRi=extZo=0; + Smooth=TRUE; + NumList=NULL; + ConList=NULL; + WeightingScheme=0; + bHasMask=FALSE; + LengthConv=(double *)calloc(6,sizeof(double)); + LengthConv[0]=0.0254; //inches + LengthConv[1]=0.001; //millimeters + LengthConv[2]=0.01; //centimeters + LengthConv[3]=1.; //meters + LengthConv[4]=2.54e-05; //mils + LengthConv[5]=1.e-06; //micrometers + Coords=FALSE; + + for(int i=0;i<9;i++) + d_PlotBounds[i][0]=d_PlotBounds[i][1]= + PlotBounds[i][0]=PlotBounds[i][1]=0; + + // determine path to bin directory + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + WeightingScheme = d_WeightingScheme; + + // lua initialization stuff + initalise_lua(); +} + +CFemmviewDoc::~CFemmviewDoc() +{ + int i; + free(LengthConv); + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + ProblemNote=v; + 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; + } + + // 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) bIncremental=PrevType; + else bIncremental=FALSE; + q[0]=NULL; + } + + if (_strnicmp(q, "[prevtype]", 10) == 0) { + v = StripKey(s); + sscanf(v, "%i", &PrevType); + q[0] = NULL; + // 0 == None + // 1 == Incremental + // 2 == Frozen + } + + // Point Properties + if( _strnicmp(q,"",11)==0){ + PProp.PointName="New Point Property"; + PProp.Jr=0.; + PProp.Ji=0.; + PProp.Ar=0.; + PProp.Ai=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.Ar); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Ai); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Jr); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Ji); + 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.; + 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,"",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.Jr=0.; + MProp.Ji=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.; // hysteresis angle, degrees + MProp.Theta_hy=0.; // hysteresis angle, degrees + MProp.NStrands=0; + MProp.WireD=0; + MProp.LamFill=1.; // lamination fill factor; + MProp.LamType=0; // type of lamination; + MProp.BHpoints=0; + MProp.MuMax=0; + MProp.Frequency=Frequency; + 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.Jr); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + if (Frequency!=0) sscanf(v,"%lf",&MProp.Ji); + 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); + 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.Hdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); + MProp.Bdata=(double *)calloc(MProp.BHpoints,sizeof(double)); + for(j=0;j",9)==0){ + if (MProp.BHpoints>0) + { + if (bIncremental!=0){ + // first time through was just to get MuMax from AC curve... + CComplex *tmpHdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); + double *tmpBdata=(double *)calloc(MProp.BHpoints,sizeof(double)); + for(i=0;i",14)==0){ + CProp.CircName="New Circuit"; + CProp.CircType=0; + CProp.Amps=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); + if (Frequency!=0) 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) asegm.MaxSideLength=b; // use as-meshed max side length for display purposes + arclist.Add(asegm); + } + q[0]=NULL; + } + + + // read in list of holes; + if(_strnicmp(q,"[numholes]",13)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) + { + blk.BlockType=-1; + blk.MaxArea=0; + for(i=0;i0) + { + j=age.totalArcElements+1; + age.qp=(CQuadPoint *)calloc(j,sizeof(CQuadPoint)); // list of nodes on inner radius + } + + for(j=0;j<=age.totalArcElements;j++){ + CQuadPoint q; + + fgets(s,1024,fp); + sscanf(s,"%i %lf %i %lf %i %lf %i %lf", + &q.n0, &q.w0, + &q.n1, &q.w1, + &q.n2, &q.w2, + &q.n3, &q.w3); + age.qp[j]=q; + } + if (age.totalArcElements>0) agelist.Add(age); + } + + fclose(fp); + + // figure out amplitudes of harmonics for AGE boundary conditions + for (i=0;iagelist[i].totalArcElements){ + nn[4]=agelist[i].qp[1].n1; + ww[4]=agelist[i].qp[1].w1; + } + else{ + nn[4]=agelist[i].qp[k+2].n1; + ww[4]=agelist[i].qp[k+2].w1; + } + + // outer nodes + if ((k-1)<0){ + nn[5]=agelist[i].qp[agelist[i].totalArcElements-1].n2; + ww[5]=agelist[i].qp[agelist[i].totalArcElements-1].w2; + } + else{ + nn[5]=agelist[i].qp[k-1].n2; + ww[5]=agelist[i].qp[k-1].w2; + } + + nn[6]=agelist[i].qp[k].n2; + nn[7]=agelist[i].qp[k].n3; + nn[8]=agelist[i].qp[k+1].n3; + ww[6]=agelist[i].qp[k].w2; + ww[7]=agelist[i].qp[k].w3; + ww[8]=agelist[i].qp[k+1].w3; + + if((k+2)>agelist[i].totalArcElements){ + nn[9]=agelist[i].qp[1].n3; + ww[9]=agelist[i].qp[1].w3; + } + else{ + nn[9]=agelist[i].qp[k+2].n3; + ww[9]=agelist[i].qp[k+2].w3; + } + + // fix antiperiodic weights... + if ((k==0) && (agelist[i].BdryFormat==1)) + { + ww[0]=-ww[0]; + ww[5]=-ww[5]; + } + if (((k+1)==agelist[i].totalArcElements) && (agelist[i].BdryFormat==1)) + { + ww[4]=-ww[4]; + ww[9]=-ww[9]; + } + + for(kk=0;kk<10;kk++) + a[kk]=meshnode[nn[kk]].A*ww[kk]; + + // A at the center of the element + if (agelist[i].BdryFormat==0) + { + ac = (2*a[2]+2*a[3]+2*a[7]+2*a[8]+a[1]*ci+(a[2]-a[3]-a[4])*ci-(a[0]-3*a[1]+a[2]+3*a[3]-2*a[4])*pow(ci,2)+(a[0]-2*a[1]+2*a[3]-a[4])*pow(ci,3)+(a[6]+a[7]-a[8]-a[9])*co- + (a[5]-3*a[6]+a[7]+3*a[8]-2*a[9])*pow(co,2)+(a[5]-2*a[6]+2*a[8]-a[9])*pow(co,3))/8.; + agelist[i].aco += ac /((double) agelist[i].totalArcElements); + } + + // flux density for this element + agelist[i].br[k]=(-(ci*a[1])-2*a[2]+2*a[3]+ci*(a[2]+a[3]-a[4])-ci*ci*ci*(a[0]-4*a[1]+6*a[2]-4*a[3]+a[4])+ci*ci*(a[0]-5*a[1]+9*a[2]-7*a[3]+2*a[4])-2*a[7]+ + 2*a[8]+co*(-a[6]+a[7]+a[8]-a[9])-co*co*co*(a[5]-4*a[6]+6*a[7]-4*a[8]+a[9])+co*co*(a[5]-5*a[6]+9*a[7]-7*a[8]+2*a[9]))/(4*dt*R); + agelist[i].bt[k]=(ci*a[1]+2*a[2]+2*a[3]-ci*ci*(a[0]-3*a[1]+a[2]+3*a[3]-2*a[4])+ci*(a[2]-a[3]-a[4])+ci*ci*ci*(a[0]-2*a[1]+2*a[3]-a[4])-co*a[6]+ + (-2+co)*(1+co)*a[7]-2*a[8]+co*(a[8]+co*(a[5]-3*a[6]+3*a[8]-2*a[9])+a[9]+co*co*(-a[5]+2*a[6]-2*a[8]+a[9])))/(4*dr); + if (bIncremental) + { + for(kk=0;kk<10;kk++) + a[kk]=meshnode[nn[kk]].Aprev*ww[kk]; + agelist[i].brPrev[k]=Re((-(ci*a[1])-2*a[2]+2*a[3]+ci*(a[2]+a[3]-a[4])-ci*ci*ci*(a[0]-4*a[1]+6*a[2]-4*a[3]+a[4])+ci*ci*(a[0]-5*a[1]+9*a[2]-7*a[3]+2*a[4])-2*a[7]+ + 2*a[8]+co*(-a[6]+a[7]+a[8]-a[9])-co*co*co*(a[5]-4*a[6]+6*a[7]-4*a[8]+a[9])+co*co*(a[5]-5*a[6]+9*a[7]-7*a[8]+2*a[9]))/(4*dt*R)); + agelist[i].btPrev[k]=Re((ci*a[1]+2*a[2]+2*a[3]-ci*ci*(a[0]-3*a[1]+a[2]+3*a[3]-2*a[4])+ci*(a[2]-a[3]-a[4])+ci*ci*ci*(a[0]-2*a[1]+2*a[3]-a[4])-co*a[6]+ + (-2+co)*(1+co)*a[7]-2*a[8]+co*(a[8]+co*(a[5]-3*a[6]+3*a[8]-2*a[9])+a[9]+co*co*(-a[5]+2*a[6]-2*a[8]+a[9])))/(4*dr)); + } + } + + // Convolve with sines and cosines to get amplitudes of each harmonic + for(j=0;jmeshelem[i].rsqr) meshelem[i].rsqr=b; + } + } + + // Compute magnetization direction in each element + lua_State *LocalLua = lua_open(4096); + lua_baselibopen(LocalLua); + lua_strlibopen(LocalLua); + lua_mathlibopen(LocalLua); + for(i=0;iA_High) A_High=meshnode[i].A.re; + if (meshnode[i].A.reA_High) A_High=meshnode[i].A.im; + } + } + // save default values for extremes of A + A_lb=A_Low; + A_ub=A_High; + + if(Frequency!=0){ // compute frequency-dependent permeabilities for linear blocks; + + CComplex deg45; deg45=1+I; + CComplex K,halflag; + double ds; + double w=2.*PI*Frequency; + + for(k=0;kJ_High) J_High=b; if(bJr_High) Jr_High=br; if(brJi_High) Ji_High=bi; if(bi1)) + { + for(k=1;k<10;k++) + { + if (myBlockName[1]==('0'+k)){ + isExt[i]=TRUE; + break; + } + } + } + + } + + for(i=0;iB_High) B_High=b; + // new form is a heuristic that discounts really small elements + // with really high flux density, which sometimes happens in corners. + a1=sqrt(meshelem[i].rsqr)*b*b; + if ((a1>a0) && (!isExt[i])) + { + B_High=b; + a0=a1; + } + + if (!isExt[i]){ + if(bBr_High) Br_High=br; if(brBi_High) Bi_High=bi; if(biH_High) H_High=b; if(bHr_High) Hr_High=br; if(brHi_High) Hi_High=bi; if(biDensityPlot==2) theView->DensityPlot=1; + if (theView->DensityPlot>1) theView->DensityPlot=0; + } + + // compute total resulting current for circuits with an a priori defined + // voltage gradient; Need this to display circuit results & impedance. + for(i=0;i1) + for(j=0,circproplist[i].Amps=0.;j=0) + { + if(meshelem[i].lbl!=k) + { + blocklist[meshelem[i].lbl].IsSelected=TRUE; + if (!bMultiplyDefinedLabels) + { + CString msg; + msg ="Some regions in the problem have been defined\n"; + msg+="by more than one block label. These potentially\n"; + msg+="problematic regions will appear as selected in\n"; + msg+="the initial view."; + MsgBox(msg); + bMultiplyDefinedLabels=TRUE; + } + } + } + } + + + // Get some information needed to compute energy stored in + // permanent magnets with a nonlinear demagnetization curve + if (Frequency==0) + { + for(k=0;k0) && (blockproplist[k].BHpoints>0)) + { + blockproplist[k].Nrg = blockproplist[k].GetCoEnergy(blockproplist[k].GetB(blockproplist[k].H_c)); + } + } + } + + FirstDraw=TRUE; + return TRUE; +} + + +int CFemmviewDoc::InTriangle(double x, double y) +{ + static int k; + int j,hi,lo,sz; + double z; + + sz=(int) meshelem.GetSize(); + if((k<0) || (k>=sz)) k=0; + + // In most applications, the triangle we're looking + // for is nearby the last one we found. Since the elements + // are ordered in a banded structure, we want to check the + // elements nearby the last one selected first. + if (InTriangleTest(x,y,k)) return k; + + hi=k;lo=k; + + for(j=0;j=sz) hi=0; + lo--; if(lo<0) lo=sz-1; + + z=(meshelem[hi].ctr.re-x)*(meshelem[hi].ctr.re-x) + + (meshelem[hi].ctr.im-y)*(meshelem[hi].ctr.im-y); + if(z<=meshelem[hi].rsqr) + { + if(InTriangleTest(x,y,hi)) + { + k=hi; + return k; + } + } + + z=(meshelem[lo].ctr.re-x)*(meshelem[lo].ctr.re-x) + + (meshelem[lo].ctr.im-y)*(meshelem[lo].ctr.im-y); + if(z<=meshelem[lo].rsqr) + { + if(InTriangleTest(x,y,lo)) + { + k=lo; + return k; + } + } + + } + + return (-1); +} + +BOOL CFemmviewDoc::GetPointValues(double x, double y, CPointVals &u) +{ + int k; + k=InTriangle(x,y); + if (k<0) return FALSE; + GetPointValues(x,y,k,u); + return TRUE; +} + +BOOL CFemmviewDoc::GetPointValues(double x, double y, int k, CPointVals &u) +{ + int i,j,n[3],lbl; + double a[3],b[3],c[3],da,ravg; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + ravg=LengthConv[LengthUnits]* + (meshnode[n[0]].x + meshnode[n[1]].x + meshnode[n[2]].x)/3.; + + GetPointB(x,y,u.B1,u.B2,meshelem[k]); + + u.Hc=0; + u.mu12=0; + +// if(blockproplist[meshelem[k].blk].LamType>2) + u.ff=blocklist[meshelem[k].lbl].FillFactor; +// else u.ff=-1; + + if (Frequency==0){ + u.A=0; + if(ProblemType==0){ + for(i=0;i<3;i++) + u.A.re+=meshnode[n[i]].A.re*(a[i]+b[i]*x+c[i]*y)/(da); + } + else{ + /* Old way that I interpolated potential in axi case: + // interpolation from A from nodal points. + // note that the potential that's actually stored + // for axisymmetric problems is 2*Pi*r*A, so divide + // by nodal r to get 2*Pi*A at the nodes. Linearly + // interpolate this, then multiply by r at the point + // of interest to get back to 2*Pi*r*A. + for(i=0,rp=0;i<3;i++){ + r=meshnode[n[i]].x; + rp+=meshnode[n[i]].x*(a[i]+b[i]*x+c[i]*y)/da; + if (r>1.e-6) u.A.re+=meshnode[n[i]].A.re* + (a[i]+b[i]*x+c[i]*y)/(r*da); + } + u.A.re*=rp; + */ + + + // a ``smarter'' interpolation. One based on A can't + // represent constant flux density very well. + // This works, but I should re-write it in a more + // efficient form--it's doing a lot of the work + // twice, because the a-b-c stuff that's already + // been computed is ignored. + double v[6]; + double R[3]; + double Z[3]; + double p,q; + + for(i=0;i<3;i++){ + R[i]=meshnode[n[i]].x; + Z[i]=meshnode[n[i]].y; + } + + // corner nodes + v[0]=meshnode[n[0]].A.re; + v[2]=meshnode[n[1]].A.re; + v[4]=meshnode[n[2]].A.re; + + // construct values for mid-side nodes; + if ((R[0]<1.e-06) && (R[1]<1.e-06)) + v[1]=(v[0]+v[2])/2.; + else + v[1]=(R[1]*(3.*v[0] + v[2]) + R[0]*(v[0] + 3.*v[2]))/ + (4.*(R[0] + R[1])); + + if ((R[1]<1.e-06) && (R[2]<1.e-06)) + v[3]=(v[2]+v[4])/2.; + else + v[3]=(R[2]*(3.*v[2] + v[4]) + R[1]*(v[2] + 3.*v[4]))/ + (4.*(R[1] + R[2])); + + if ((R[2]<1.e-06) && (R[0]<1.e-06)) + v[5]=(v[4]+v[0])/2.; + else + v[5]=(R[0]*(3.*v[4] + v[0]) + R[2]*(v[4] + 3.*v[0]))/ + (4.*(R[2] + R[0])); + + // compute location in element transformed onto + // a unit triangle; + p=(b[1]*x+c[1]*y + a[1])/da; + q=(b[2]*x+c[2]*y + a[2])/da; + + // now, interpolate to get potential... + u.A.re = v[0] - p*(3.*v[0] - 4.*v[1] + v[2]) + + 2.*p*p*(v[0] - 2.*v[1] + v[2]) - + q*(3.*v[0] + v[4] - 4.*v[5]) + + 2.*q*q*(v[0] + v[4] - 2.*v[5]) + + 4.*p*q*(v[0] - v[1] + v[3] - v[5]); + + /* // "simple" way to do it... + // problem is that this mucks up things + // near the centerline, where things ought + // to look pretty quadratic. + for(i=0;i<3;i++) + u.A.re+=meshnode[n[i]].A.re*(a[i]+b[i]*x+c[i]*y)/(da); + */ + } + + // Need to catch bIncremental case here... + u.mu1.im = 0; u.mu2.im = 0; u.mu12 = 0; + if (!bIncremental) { + GetMu(u.B1.re, u.B2.re, u.mu1.re, u.mu2.re, k); + u.H1 = u.B1 / (Re(u.mu1)*muo); + u.H2 = u.B2 / (Re(u.mu2)*muo); + } + else { + double muinc, murel; + double B, B1p, B2p; + + B1p = meshelem[k].B1p; + B2p = meshelem[k].B2p; + B = sqrt(B1p*B1p + B2p*B2p); + + GetMu(B1p, B2p, muinc, murel, k); + if (B == 0) + { + // Catch the special case where B=0 to avoid a possible divide by zero + u.mu1 = muinc; + u.mu2 = muinc; + u.mu12 = 0; + } + else if(bIncremental==1) + { + // For "incremental" problem, permeability is linearized about the prevous soluiton. + u.mu1 = (B1p*B1p*muinc + B2p*B2p*murel) / (B*B); + u.mu12 = (B1p*B2p*(muinc - murel)) / (B*B); + u.mu2 = (B2p*B2p*muinc + B1p*B1p*murel) / (B*B); + } + else { //bIncremental==2 + // For "frozen" permeability, same permeability as previous problem + u.mu1 = murel; + u.mu2 = murel; + u.mu12 = 0; + } + + u.H1 = (u.B2*u.mu12 - u.B1*u.mu2) / (u.mu12*u.mu12 - u.mu1*u.mu2); + u.H2 = (u.B2*u.mu1 - u.B1*u.mu12) / (u.mu1*u.mu2 - u.mu12*u.mu12); + } + + + + + + + + + u.Je=0; + u.Js=blockproplist[meshelem[k].blk].Jr; + lbl=meshelem[k].lbl; + j=blocklist[lbl].InCircuit; + if(j>=0){ + if(blocklist[lbl].Case==0){ + if (ProblemType==0) + u.Js-=Re(blocklist[meshelem[k].lbl].o)* + blocklist[lbl].dVolts; + else{ + + int tn; + double R[3]; + for(tn=0;tn<3;tn++) + { + R[tn]=meshnode[n[tn]].x; + if (R[tn]<1.e-6) R[tn]=ravg; + else R[tn]*=LengthConv[LengthUnits]; + } + for(ravg=0.,tn=0;tn<3;tn++) + ravg+=(1./R[tn])*(a[tn]+b[tn]*x+c[tn]*y)/(da); + u.Js-=Re(blocklist[meshelem[k].lbl].o)* + blocklist[lbl].dVolts*ravg; + } + } + else u.Js+=blocklist[lbl].J; + } + u.c=Re(blocklist[meshelem[k].lbl].o); + u.E=blockproplist[meshelem[k].blk].DoEnergy(u.B1.re,u.B2.re); + + // correct H and energy stored in magnet for second-quadrant + // representation of a PM. + if (blockproplist[meshelem[k].blk].H_c!=0) + { + int bk=meshelem[k].blk; + + u.Hc = blockproplist[bk].H_c*exp(I*PI*meshelem[k].magdir/180.); + u.H1=u.H1-Re(u.Hc); + u.H2=u.H2-Im(u.Hc); + + // in the linear case: + if (blockproplist[bk].BHpoints==0) + u.E = 0.5*muo*(u.mu1.re*u.H1.re*u.H1.re + u.mu2.re*u.H2.re*u.H2.re); + else{ + u.E = u.E + blockproplist[bk].Nrg + - blockproplist[bk].H_c*Re((u.B1.re+I*u.B2.re)/exp(I*PI*meshelem[k].magdir/180.)); + } + + // If considering the magnet as an equivalent coil, add Hc to the demagnetizing field + if (!d_ShiftH) + { + u.H1=u.H1+Re(u.Hc); + u.H2=u.H2+Im(u.Hc); + u.Hc=0; + } + } + + // add in "local" stored energy for wound that would be subject to + // prox and skin effect for nonzero frequency cases. + if (blockproplist[meshelem[k].blk].LamType>2) + { + CComplex J; + J=u.Js*1.e6; + + u.E+=Re(J*J)*blocklist[meshelem[i].lbl].LocalEnergy/2.; + } + + u.Ph=0; + u.Pe=0; + return TRUE; + } + + if(Frequency!=0){ + u.A=0; + if(ProblemType==0) + { + for(i=0;i<3;i++) + u.A+=meshnode[n[i]].A*(a[i]+b[i]*x+c[i]*y)/(da); + } + else{ + CComplex v[6]; + double R[3]; + double Z[3]; + double p,q; + + for(i=0;i<3;i++){ + R[i]=meshnode[n[i]].x; + Z[i]=meshnode[n[i]].y; + } + + // corner nodes + v[0]=meshnode[n[0]].A; + v[2]=meshnode[n[1]].A; + v[4]=meshnode[n[2]].A; + + // construct values for mid-side nodes; + if ((R[0]<1.e-06) && (R[1]<1.e-06)) + v[1]=(v[0]+v[2])/2.; + else + v[1]=(R[1]*(3.*v[0] + v[2]) + R[0]*(v[0] + 3.*v[2]))/ + (4.*(R[0] + R[1])); + + if ((R[1]<1.e-06) && (R[2]<1.e-06)) + v[3]=(v[2]+v[4])/2.; + else + v[3]=(R[2]*(3.*v[2] + v[4]) + R[1]*(v[2] + 3.*v[4]))/ + (4.*(R[1] + R[2])); + + if ((R[2]<1.e-06) && (R[0]<1.e-06)) + v[5]=(v[4]+v[0])/2.; + else + v[5]=(R[0]*(3.*v[4] + v[0]) + R[2]*(v[4] + 3.*v[0]))/ + (4.*(R[2] + R[0])); + + // compute location in element transformed onto + // a unit triangle; + p=(b[1]*x+c[1]*y + a[1])/da; + q=(b[2]*x+c[2]*y + a[2])/da; + + // now, interpolate to get potential... + u.A = v[0] - p*(3.*v[0] - 4.*v[1] + v[2]) + + 2.*p*p*(v[0] - 2.*v[1] + v[2]) - + q*(3.*v[0] + v[4] - 4.*v[5]) + + 2.*q*q*(v[0] + v[4] - 2.*v[5]) + + 4.*p*q*(v[0] - v[1] + v[3] - v[5]); + } + + // if bIncremental, need to get permeability about the DC + // operating point, rather than usual DC permeability. + if (!bIncremental){ + GetMu(u.B1,u.B2,u.mu1,u.mu2,k); + u.mu12=0; + u.H1 = u.B1/(u.mu1*muo); + u.H2 = u.B2/(u.mu2*muo); + } + else{ + CComplex muinc,murel; + double B,B1p,B2p; + + B1p=meshelem[k].B1p; + B2p=meshelem[k].B2p; + B=sqrt(B1p*B1p + B2p*B2p); + + GetMu(B1p,B2p,muinc,murel,k); + if (B==0) + { + u.mu1=murel; + u.mu2=murel; + u.mu12 = 0; + } + else{ + u.mu1 = (B1p*B1p*muinc + B2p*B2p*murel)/(B*B); + u.mu12 = (B1p*B2p*(muinc - murel))/(B*B); + u.mu2 = (B2p*B2p*muinc + B1p*B1p*murel)/(B*B); + } + + u.H1 = (u.B2*u.mu12 - u.B1*u.mu2)/(u.mu12*u.mu12 - u.mu1*u.mu2); + u.H2 = (u.B2*u.mu1 - u.B1*u.mu12)/(u.mu1*u.mu2 - u.mu12*u.mu12); + } + + u.Js=blockproplist[meshelem[k].blk].Jr + + I*blockproplist[meshelem[k].blk].Ji; + lbl=meshelem[k].lbl; + j=blocklist[lbl].InCircuit; + if(j>=0){ + if(blocklist[lbl].Case==0){ + if (ProblemType==0) + u.Js-=blocklist[meshelem[k].lbl].o*blocklist[lbl].dVolts; + else + { + + int tn; + double R[3]; + for(tn=0;tn<3;tn++) + { + R[tn]=meshnode[n[tn]].x; + if (R[tn]<1.e-6) R[tn]=ravg; + else R[tn]*=LengthConv[LengthUnits]; + } + for(ravg=0.,tn=0;tn<3;tn++) + ravg+=(1./R[tn])*(a[tn]+b[tn]*x+c[tn]*y)/(da); + u.Js-=blocklist[meshelem[k].lbl].o* + blocklist[lbl].dVolts*ravg; + } + } + else u.Js+=blocklist[lbl].J; + } + + // report just loss-related part of conductivity. + if (blockproplist[meshelem[k].blk].Cduct!=0) + u.c=1./Re(1./(blocklist[meshelem[k].lbl].o)); + else u.c=0; + + if (blockproplist[meshelem[k].blk].Lam_d!=0) u.c=0; + + // only add in eddy currents if the region is solid + if (blocklist[meshelem[k].lbl].FillFactor<0) + u.Je=-I*Frequency*2.*PI*u.c*u.A; + + if(ProblemType!=0){ + if(x!=0) + u.Je/=(2.*PI*x*LengthConv[LengthUnits]); + else u.Je=0; + } + + CComplex z; + z=(u.H1*u.B1.Conj()) + (u.H2*u.B2.Conj()); + u.E=0.25*z.re; + + // add in "local" stored energy for wound that would be subject to + // prox and skin effect for nonzero frequency cases. + if (blockproplist[meshelem[k].blk].LamType>2) + { + CComplex J; + J=u.Js*1.e6; + u.E += Re(J*conj(J))*blocklist[meshelem[k].lbl].LocalEnergy/4.; + } + + u.Ph=Frequency*PI*z.im; + u.Pe=0; + if (u.c!=0) + { + z=u.Js + u.Je; + u.Pe=1.e06*(z.re*z.re + z.im*z.im)/(u.c*2.); + } + + return TRUE; + } + + return FALSE; +} + +void CFemmviewDoc::GetPointB(double x, double y, CComplex &B1, CComplex &B2, + CElement &elm) +{ + // elm is a reference to the element that contains the point of interest. + int i,n[3]; + double da,a[3],b[3],c[3]; + + if(Smooth==FALSE){ + B1=elm.B1; + B2=elm.B2; + return; + } + + for(i=0;i<3;i++) n[i]=elm.p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + B1.Set(0,0); + B2.Set(0,0); + for(i=0;i<3;i++){ + B1+=(elm.b1[i]*(a[i]+b[i]*x+c[i]*y)/da); + B2+=(elm.b2[i]*(a[i]+b[i]*x+c[i]*y)/da); + } +} + +void CFemmviewDoc::GetNodalB(CComplex *b1, CComplex *b2,CElement &elm) +{ + // elm is a reference to the element that contains the point of interest. + CComplex p; + CComplex tn,bn,bt,btu,btv,u1,u2,v1,v2; + int i,j,k,l,q,m,pt,nxt; + double r,R,z; + CElement *e; + int flag; + + // find nodal values of flux density via a patch method. + for(i=0;i<3;i++){ + + k=elm.p[i]; + p.Set(meshnode[k].x,meshnode[k].y); + b1[i].Set(0,0); + b2[i].Set(0,0); + for(j=0,m=0;jp[j]==k) pt=j; + pt--; + if(pt<0) pt=2; + pt=e->p[pt]; + + //scan to find element adjacent to this side; + for(j=0,nxt=-1;jB1); + b2[i]=(e->B2); + v1=1;v2=1; + } + else if(elm.lbl!=meshelem[nxt].lbl){ + // we have found two elements on either side of the interface + // now, we take contribution from B at the center of the + // interface side + tn.Set(meshnode[pt].x-meshnode[k].x, + meshnode[pt].y-meshnode[k].y); + r=(meshnode[pt].x+meshnode[k].x)*LengthConv[LengthUnits]/2.; + bn=(meshnode[pt].A-meshnode[k].A)/ + (abs(tn)*LengthConv[LengthUnits]); + if(ProblemType==1){ + bn/=(-2.*PI*r); + } + z=0.5/abs(tn); + tn/=abs(tn); + + // for the moment, kludge with bt... + bt=e->B1*tn.re + e->B2*tn.im; + + R+=z; + b1[i]+=(z*tn.re*bt); + b2[i]+=(z*tn.im*bt); + b1[i]+=(z*tn.im*bn); + b2[i]+=(-z*tn.re*bn); + v1=tn; + q=NumList[k]; + } + else e=&meshelem[nxt]; + } + + //scan cw for an interface... + if(v2==0) // catches the "special-case punt" where we have + { // already set nodal B values.... + e=&elm; + for(q=0;qp[j]==k) pt=j; + pt++; + if(pt>2) pt=0; + pt=e->p[pt]; + + //scan to find element adjacent to this side; + for(j=0,nxt=-1;jB1); + b2[i]=(e->B2); + v1=1;v2=1; + } + else if(elm.lbl!=meshelem[nxt].lbl){ + // we have found two elements on either side of the interface + // now, we take contribution from B at the center of the + // interface side + tn.Set(meshnode[pt].x-meshnode[k].x, + meshnode[pt].y-meshnode[k].y); + r=(meshnode[pt].x+meshnode[k].x)*LengthConv[LengthUnits]/2.; + bn=(meshnode[pt].A-meshnode[k].A)/ + (abs(tn)*LengthConv[LengthUnits]); + if(ProblemType==1){ + bn/=(-2.*PI*r); + } + z=0.5/abs(tn); + tn/=abs(tn); + + // for the moment, kludge with bt... + bt=e->B1*tn.re + e->B2*tn.im; + + R+=z; + b1[i]+=(z*tn.re*bt); + b2[i]+=(z*tn.im*bt); + b1[i]+=(z*tn.im*bn); + b2[i]+=(-z*tn.re*bn); + v2=tn; + q=NumList[k]; + } + else e=&meshelem[nxt]; + } + b1[i]/=R; + b2[i]/=R; + } + + // check to see if angle of corner is too sharp to apply + // this rule; really only does right if the interface is flat; + flag=FALSE; + // if there is only one edge, approx is ok; + if ((abs(v1)<0.9) || (abs(v2)<0.9)) flag=TRUE; + // if the interfaces make less than a 10 degree angle, things are ok; + if ( (-v1.re*v2.re-v1.im*v2.im) > 0.985) flag=TRUE; + + // Otherwise, punt... + if(flag==FALSE){ + bn=0; + k=elm.p[i]; + for(j=0;jbn.re) bn.re=bt.re; + if(bt.im>bn.im) bn.im=bt.im; + } + } + + R=sqrt(elm.B1.re*elm.B1.re + elm.B2.re*elm.B2.re); + if(R!=0) + { + b1[i].re=bn.re/R * elm.B1.re; + b2[i].re=bn.re/R * elm.B2.re; + } + else{ + b1[i].re=0; + b2[i].re=0; + } + + R=sqrt(elm.B1.im*elm.B1.im + elm.B2.im*elm.B2.im); + if(R!=0) + { + b1[i].im=bn.im/R * elm.B1.im; + b2[i].im=bn.im/R * elm.B2.im; + } + else{ + b1[i].im=0; + b2[i].im=0; + } + } + } + + // check to see if the point has a point current; if so, just + // use element average values; + if (nodeproplist.GetSize()!=0) + for(j=0;j=0) + { + if ((nodeproplist[nodelist[j].BoundaryMarker].Jr!=0) || + (nodeproplist[nodelist[j].BoundaryMarker].Ji!=0)) + { + b1[i]=elm.B1; + b2[i]=elm.B2; + } + } + } + + + //check for special case of node on r=0 axisymmetric; set Br=0; + if ((fabs(p.re)<1.e-06) && (ProblemType==1)) b1[i].Set(0.,0); + } +} + +void CFemmviewDoc::GetElementB(CElement &elm) +{ + int i,n[3]; + double b[3],c[3],da; + + for(i=0;i<3;i++) n[i]=elm.p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + if (ProblemType==0){ + elm.B1=0; + elm.B2=0; + elm.B1p=0; + elm.B2p=0; + for(i=0;i<3;i++) + { + elm.B1+=meshnode[n[i]].A*c[i]/(da*LengthConv[LengthUnits]); + elm.B2-=meshnode[n[i]].A*b[i]/(da*LengthConv[LengthUnits]); + } + + if (bIncremental) + { + for(i=0;i<3;i++) + { + elm.B1p+=meshnode[n[i]].Aprev*c[i]/(da*LengthConv[LengthUnits]); + elm.B2p-=meshnode[n[i]].Aprev*b[i]/(da*LengthConv[LengthUnits]); + } + } + + return; + } + else{ + CComplex v[6],dp,dq; + double R[3],Z[3],r; + + for(i=0,r=0;i<3;i++){ + R[i]=meshnode[n[i]].x; + Z[i]=meshnode[n[i]].y; + r+=R[i]/3.; + } + + // corner nodes + v[0]=meshnode[n[0]].A; + v[2]=meshnode[n[1]].A; + v[4]=meshnode[n[2]].A; + + // construct values for mid-side nodes; + if ((R[0]<1.e-06) && (R[1]<1.e-06)) v[1]=(v[0]+v[2])/2.; + else v[1]=(R[1]*(3.*v[0] + v[2]) + R[0]*(v[0] + 3.*v[2]))/ + (4.*(R[0] + R[1])); + + if ((R[1]<1.e-06) && (R[2]<1.e-06)) v[3]=(v[2]+v[4])/2.; + else v[3]=(R[2]*(3.*v[2] + v[4]) + R[1]*(v[2] + 3.*v[4]))/ + (4.*(R[1] + R[2])); + + if ((R[2]<1.e-06) && (R[0]<1.e-06)) v[5]=(v[4]+v[0])/2.; + else v[5]=(R[0]*(3.*v[4] + v[0]) + R[2]*(v[4] + 3.*v[0]))/ + (4.*(R[2] + R[0])); + + // derivatives w.r.t. p and q: + dp=(-v[0] + v[2] + 4.*v[3] - 4.*v[5])/3.; + dq=(-v[0] - 4.*v[1] + 4.*v[3] + v[4])/3.; + + // now, compute flux. + da*=2.*PI*r*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + elm.B1=-(c[1]*dp+c[2]*dq)/da; + elm.B2= (b[1]*dp+b[2]*dq)/da; + + if (bIncremental) + { + // corner nodes + v[0]=meshnode[n[0]].Aprev; + v[2]=meshnode[n[1]].Aprev; + v[4]=meshnode[n[2]].Aprev; + + // construct values for mid-side nodes; + if ((R[0]<1.e-06) && (R[1]<1.e-06)) v[1]=(v[0]+v[2])/2.; + else v[1]=(R[1]*(3.*v[0] + v[2]) + R[0]*(v[0] + 3.*v[2]))/ + (4.*(R[0] + R[1])); + + if ((R[1]<1.e-06) && (R[2]<1.e-06)) v[3]=(v[2]+v[4])/2.; + else v[3]=(R[2]*(3.*v[2] + v[4]) + R[1]*(v[2] + 3.*v[4]))/ + (4.*(R[1] + R[2])); + + if ((R[2]<1.e-06) && (R[0]<1.e-06)) v[5]=(v[4]+v[0])/2.; + else v[5]=(R[0]*(3.*v[4] + v[0]) + R[2]*(v[4] + 3.*v[0]))/ + (4.*(R[2] + R[0])); + + // derivatives w.r.t. p and q: + dp=(-v[0] + v[2] + 4.*v[3] - 4.*v[5])/3.; + dq=(-v[0] - 4.*v[1] + 4.*v[3] + v[4])/3.; + + // now, compute flux. + da=(b[0]*c[1]-b[1]*c[0]); + da*=2.*PI*r*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + elm.B1p=Re(-(c[1]*dp+c[2]*dq)/da); + elm.B2p=Re( (b[1]*dp+b[2]*dq)/da); + } + else{ + elm.B1p=0; + elm.B2p=0; + } + return; + } +} + + +void CFemmviewDoc::OnReload() +{ + // TODO: Add your command handler code here + CString pname = GetPathName(); + if(pname.GetLength()>0) + { + OnNewDocument(); + SetPathName(pname,FALSE); + OnOpenDocument(pname); + } +} + +int CFemmviewDoc::ClosestNode(double x, double y) +{ + int i,j; + double d0,d1; + + if(nodelist.GetSize()==0) return -1; + + j=0; + d0=nodelist[0].GetDistance(x,y); + for(i=0;iq[k]) && (k<(contour.GetSize()-1))) k++; + u=(z-q[k-1])/(q[k]-q[k-1]); + pt=contour[k-1]+u*(contour[k]-contour[k-1]); + t=contour[k]-contour[k-1]; + t/=abs(t); + n = I*t; + pt+=(n*1.e-06); + + if (elm<0) elm=InTriangle(pt.re,pt.im); + else if (InTriangleTest(pt.re,pt.im,elm)==FALSE) + { + flag=FALSE; + for(j=0;j<3;j++) + for(m=0;m=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + p.M[i][0]=z; + if ((Frequency==0) && (flag!=FALSE)){ + switch (PlotType){ + case 0: + p.M[i][1]=v.A.re; + break; + case 1: + p.M[i][1]=sqrt(v.B1.Abs()*v.B1.Abs() + v.B2.Abs()*v.B2.Abs()); + break; + case 2: + p.M[i][1]= n.re*v.B1.re + n.im*v.B2.re; + break; + case 3: + p.M[i][1]= t.re*v.B1.re + t.im*v.B2.re; + break; + case 4: + p.M[i][1]=sqrt(v.H1.Abs()*v.H1.Abs() + v.H2.Abs()*v.H2.Abs()); + break; + case 5: + p.M[i][1]= n.re*v.H1.re + n.im*v.H2.re; + break; + case 6: + p.M[i][1]= t.re*v.H1.re + t.im*v.H2.re; + break; + default: + p.M[i][1]=0; + break; + } + } + else if (flag!=FALSE){ + switch (PlotType){ + case 0: + p.M[i][1]=v.A.Abs(); + p.M[i][2]=v.A.re; + p.M[i][3]=v.A.im; + break; + case 1: + p.M[i][1]=sqrt(v.B1.Abs()*v.B1.Abs() + v.B2.Abs()*v.B2.Abs()); + break; + case 2: + p.M[i][2]= n.re*v.B1.re + n.im*v.B2.re; + p.M[i][3]= n.re*v.B1.im + n.im*v.B2.im; + p.M[i][1]=sqrt(p.M[i][2]*p.M[i][2] + + p.M[i][3]*p.M[i][3]); + break; + case 3: + p.M[i][2]= t.re*v.B1.re + t.im*v.B2.re; + p.M[i][3]= t.re*v.B1.im + t.im*v.B2.im; + p.M[i][1]=sqrt(p.M[i][2]*p.M[i][2] + + p.M[i][3]*p.M[i][3]); + break; + case 4: + p.M[i][1]=sqrt(v.H1.Abs()*v.H1.Abs() + v.H2.Abs()*v.H2.Abs()); + break; + case 5: + p.M[i][2]= n.re*v.H1.re + n.im*v.H2.re; + p.M[i][3]= n.re*v.H1.im + n.im*v.H2.im; + p.M[i][1]=sqrt(p.M[i][2]*p.M[i][2] + + p.M[i][3]*p.M[i][3]); + break; + case 6: + p.M[i][2]= t.re*v.H1.re + t.im*v.H2.re; + p.M[i][3]= t.re*v.H1.im + t.im*v.H2.im; + p.M[i][1]=sqrt(p.M[i][2]*p.M[i][2] + + p.M[i][3]*p.M[i][3]); + break; + case 7: + p.M[i][2]= v.Je.re; + p.M[i][3]= v.Je.im; + p.M[i][1]= abs(v.Je); + break; + case 8: + p.M[i][2]= v.Je.re+v.Js.re; + p.M[i][3]= v.Je.im+v.Js.im; + p.M[i][1]= abs(v.Je+v.Js); + break; + default: + p.M[i][1]=0; + break; + } + } + } + + free(q); +} + +BOOL CFemmviewDoc::InTriangleTest(double x, double y, int i) +{ + if ((i<0) || (i>=meshelem.GetSize())) return FALSE; + + int j,k; + double z; + + for(j=0;j<3;j++) + { + k=j+1; if(k==3) k=0; + // Case 1: p[k]>p[j] + if (meshelem[i].p[k] > meshelem[i].p[j]) + { + z=(meshnode[meshelem[i].p[k]].x-meshnode[meshelem[i].p[j]].x)* + (y-meshnode[meshelem[i].p[j]].y) - + (meshnode[meshelem[i].p[k]].y-meshnode[meshelem[i].p[j]].y)* + (x-meshnode[meshelem[i].p[j]].x); + if(z<0) return FALSE; + } + //Case 2: p[k]0) return FALSE; + } + } + + return TRUE; +} + +CPointVals::CPointVals() +{ + A=0; // vector potential + B1=0; B2=0; // flux density + mu1=1; mu2=1; // permeability + H1=0; H2=0; // field intensity + Je=0; Js=0; // eddy current and source current densities + c=0; // conductivity + E=0; // energy stored in the magnetic field + Ph=0; // power dissipated by hysteresis + Pe=0; + ff=1; +} + +CComplex CFemmviewDoc::Ctr(int i) +{ + CComplex p,c; + int j; + + for(j=0,c=0;j<3;j++){ + p.Set(meshnode[meshelem[i].p[j]].x/3.,meshnode[meshelem[i].p[j]].y/3.); + c+=p; + } + + return c; +} + +double CFemmviewDoc::ElmArea(int i) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=meshelem[i].p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +double CFemmviewDoc::ElmArea(CElement *elm) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=elm->p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +CComplex CFemmviewDoc::GetJA(int k,CComplex *J,CComplex *A) +{ + // returns current density with contribution from all sources in + // units of MA/m^2 + + int i,blk,lbl,crc; + double r,c,rn; + CComplex Javg; + + blk=meshelem[k].blk; + lbl=meshelem[k].lbl; + crc=blocklist[lbl].InCircuit; + + // first, get A + for(i=0;i<3;i++){ + if(ProblemType==0) A[i]=(meshnode[meshelem[k].p[i]].A); + else{ + rn=meshnode[meshelem[k].p[i]].x*LengthConv[LengthUnits]; + if(fabs(rn/LengthConv[LengthUnits])<1.e-06) A[i]=0; + else A[i]=(meshnode[meshelem[k].p[i]].A)/(2.*PI*rn); + } + } + + if(ProblemType==1) r = Re(Ctr(k))*LengthConv[LengthUnits]; + + // contribution from explicitly specified J + for(i=0;i<3;i++) J[i]=blockproplist[blk].Jr+I*blockproplist[blk].Ji; + Javg=blockproplist[blk].Jr+I*blockproplist[blk].Ji; + + c=blockproplist[blk].Cduct; + if ((blockproplist[blk].Lam_d!=0) && (blockproplist[blk].LamType==0)) c=0; + if (blocklist[lbl].FillFactor>0) c=0; + + + // contribution from eddy currents; + if(Frequency!=0) + for(i=0;i<3;i++) + { + J[i]-=I*Frequency*2.*PI*c*A[i]; + Javg-=I*Frequency*2.*PI*c*A[i]/3.; + } + + + // contribution from circuit currents // + if(crc>=0) + { + if(blocklist[lbl].Case==0){ // specified voltage + if(ProblemType==0){ + for(i=0;i<3;i++) + J[i]-=c*blocklist[lbl].dVolts; + Javg-=c*blocklist[lbl].dVolts; + } + else{ + for(i=0;i<3;i++){ + rn=meshnode[meshelem[k].p[i]].x; + if(fabs(rn/LengthConv[LengthUnits])<1.e-06) + J[i]-=c*blocklist[lbl].dVolts/r; + else + J[i]-=c*blocklist[lbl].dVolts/(rn*LengthConv[LengthUnits]); + + } + Javg-=c*blocklist[lbl].dVolts/r; + } + } + else + { + for(i=0;i<3;i++) J[i]+=blocklist[lbl].J; // specified current + Javg+=blocklist[lbl].J; + } + + } + + // convert results to A/m^2 + for(i=0;i<3;i++) J[i]*=1.e06; + + return (Javg*1.e06); +} + +CComplex CFemmviewDoc::PlnInt(double a, CComplex *u, CComplex *v) +{ + int i; + CComplex z[3],x; + + z[0]=2.*u[0]+u[1]+u[2]; + z[1]=u[0]+2.*u[1]+u[2]; + z[2]=u[0]+u[1]+2.*u[2]; + + for(i=0,x=0;i<3;i++) x+=v[i]*z[i]; + return a*x/12.; +} + +CComplex CFemmviewDoc::AxiInt(double a, CComplex *u, CComplex *v,double *r) +{ + int i; + static CComplex M[3][3]; + CComplex x, z[3]; + + M[0][0]=6.*r[0]+2.*r[1]+2.*r[2]; + M[0][1]=2.*r[0]+2.*r[1]+1.*r[2]; + M[0][2]=2.*r[0]+1.*r[1]+2.*r[2]; + M[1][1]=2.*r[0]+6.*r[1]+2.*r[2]; + M[1][2]=1.*r[0]+2.*r[1]+2.*r[2]; + M[2][2]=2.*r[0]+2.*r[1]+6.*r[2]; + M[1][0]=M[0][1]; + M[2][0]=M[0][2]; + M[2][1]=M[1][2]; + + for(i=0;i<3;i++) z[i]=M[i][0]*u[0]+M[i][1]*u[1]+M[i][2]*u[2]; + for(i=0,x=0;i<3;i++) x+=v[i]*z[i]; + return PI*a*x/30.; +} + +CComplex CFemmviewDoc::HenrotteVector(int k) +{ + int i,n[3]; + double b[3],c[3],da; + CComplex v; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,v=0;i<3;i++) + v-=meshnode[n[i]].msk*(b[i]+I*c[i])/(da*LengthConv[LengthUnits]); // grad + + return v; +} + +CComplex CFemmviewDoc::BlockIntegral(int inttype) +{ + int i,k; + CComplex c,y,z,J,mu1,mu2,B1,B2,H1,H2,F1,F2; + CComplex A[3],Jn[3],U[3],V[3]; + double a,sig,R,B1p,B2p,Jp; + double r[3]; + + // make weighted stress tensor mask for integrals where it's needed +#define WEIGHTED_INTEGRALS 9 + int mm[WEIGHTED_INTEGRALS] = {18,19,20,21,22,23,25,26,27}; + BOOL bMaskIntegral=FALSE; + for (k=0;k2) + { + CComplex mu; + mu=muo*blocklist[meshelem[i].lbl].mu; + double u=blocklist[meshelem[i].lbl].LocalEnergy; + y=a*Re(B1*conj(B1)+B2*conj(B2))*Re(1./mu)/4.; + y+=a*Re(J*conj(J))*u/4.; + } + else y=a*blockproplist[meshelem[i].blk].DoEnergy(B1,B2); + } + else + { + // correct H and energy stored in magnet for second-quadrant + // representation of a PM. + if (blockproplist[meshelem[i].blk].H_c!=0) + { + int bk=meshelem[i].blk; + + // in the linear case: + if (blockproplist[bk].BHpoints==0) + { + CComplex Hc; + mu1=blockproplist[bk].mu_x; + mu2=blockproplist[bk].mu_y; + H1=B1/(mu1*muo); + H2=B2/(mu2*muo); + Hc = blockproplist[bk].H_c*exp(I*PI*meshelem[i].magdir/180.); + H1=H1-Re(Hc); + H2=H2-Im(Hc); + y = a*0.5*muo*(mu1.re*H1.re*H1.re + mu2.re*H2.re*H2.re); + } + else{ // the material is nonlinear + y=blockproplist[bk].DoEnergy(B1.re,B2.re); + y = y + blockproplist[bk].Nrg + - blockproplist[bk].H_c*Re((B1.re+I*B2.re)/exp(I*PI*meshelem[i].magdir/180.)); + y*=a; + } + } + else y=a*blockproplist[meshelem[i].blk].DoEnergy(B1.re,B2.re); + + // add in "local" stored energy for wound that would be subject to + // prox and skin effect for nonzero frequency cases. + if (blockproplist[meshelem[i].blk].LamType>2) + { + double u=blocklist[meshelem[i].lbl].LocalEnergy; + y+=a*Re(J*J)*u/2.; + } + } + y*=AECF(i); // correction for axisymmetric external region; + + z+=y; + break; + + case 3: // Hysteresis & Laminated eddy current losses + if(Frequency!=0){ + if(ProblemType==1) a*=(2.*PI*R); else a*=Depth; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + GetMu(B1,B2,mu1,mu2,i); + H1=B1/(mu1*muo); + H2=B2/(mu2*muo); + + y=a*PI*Frequency*Im(H1*B1.Conj() + H2*B2.Conj()); + z+=y; + } + break; + + case 4: // Resistive Losses + if (abs(blocklist[meshelem[i].lbl].o)==0) sig=0; + else sig=1.e06/Re(1./blocklist[meshelem[i].lbl].o); + if((blockproplist[meshelem[i].blk].Lam_d!=0) && + (blockproplist[meshelem[i].blk].LamType==0)) sig=0; + if(sig!=0){ + + if (ProblemType==0){ + for(k=0;k<3;k++) V[k]=Jn[k].Conj()/sig; + y=PlnInt(a,Jn,V)*Depth; + } + + if(ProblemType==1) + y=2.*PI*R*a*J*conj(J)/sig; + + if(Frequency!=0) y/=2.; + z+=y; + } + break; + + case 5: // cross-section area + z+=a; + break; + + case 10: // volume + if(ProblemType==1) a*=(2.*PI*R); else a*=Depth; + z+=a; + break; + + case 7: // total current in block; + z+=a*J; + + break; + + case 8: // integrate x or r part of b over the block + if(ProblemType==1) a*=(2.*PI*R); else a*=Depth; + z+=(a*meshelem[i].B1); + break; + + case 9: // integrate y or z part of b over the block + if(ProblemType==1) a*=(2.*PI*R); else a*=Depth; + z+=(a*meshelem[i].B2); + break; + + case 17: // Coenergy + if(ProblemType==1) a*=(2.*PI*R); else a*=Depth; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + if(Frequency!=0){ + // have to compute the energy stored in a special way for + // wound regions subject to prox and skin effects + if (blockproplist[meshelem[i].blk].LamType>2) + { + CComplex mu; + mu=muo*blocklist[meshelem[i].lbl].mu; + double u=blocklist[meshelem[i].lbl].LocalEnergy; + y=a*Re(B1*conj(B1)+B2*conj(B2))*Re(1./mu)/4.; + y+=a*Re(J*conj(J))*u/4.; + } + else y=a*blockproplist[meshelem[i].blk].DoCoEnergy(B1,B2); + } + else + { + y=a*blockproplist[meshelem[i].blk].DoCoEnergy(B1.re,B2.re); + + // add in "local" stored energy for wound that would be subject to + // prox and skin effect for nonzero frequency cases. + if (blockproplist[meshelem[i].blk].LamType>2) + { + double u=blocklist[meshelem[i].lbl].LocalEnergy; + y+=a*Re(J*J)*u/2.; + } + } + y*=AECF(i); // correction for axisymmetric external region; + + z+=y; + break; + + case 24: // Moment of Inertia-like integral + + // For axisymmetric problems, compute the moment + // of inertia about the r=0 axis. + if(ProblemType==1){ + for(k=0;k<3;k++) V[k]=r[k]; + y=AxiInt(a,V,V,r); + } + + // For planar problems, compute the moment of + // inertia about the z=axis. + else{ + for(k=0;k<3;k++) + { + U[k]=meshnode[meshelem[i].p[k]].x*LengthConv[LengthUnits]; + V[k]=meshnode[meshelem[i].p[k]].y*LengthConv[LengthUnits]; + } + y =U[0]*U[0] + U[1]*U[1] + U[2]*U[2]; + y+=U[0]*U[1] + U[0]*U[2] + U[1]*U[2]; + y+=V[0]*V[0] + V[1]*V[1] + V[2]*V[2]; + y+=V[0]*V[1] + V[0]*V[2] + V[1]*V[2]; + y*=(a*Depth/6.); + } + + z+=y; + break; + + case 28: // x (or r) direction Lorentz force, 1X part for incremental AC problems + B2=meshelem[i].B2; + B2p=meshelem[i].B2p; + Jp=meshelem[i].Jp; + y= -(B2p*J + B2*Jp); + if (ProblemType==1) y=0; else y*=Depth; + z+=(a*y); + break; + + case 29: // y (or z) direction Lorentz force, 1X part for incremental AC problems + B1=meshelem[i].B1; + B1p=meshelem[i].B1p; + Jp=meshelem[i].Jp; + for(k=0;k<3;k++) + { + U[k] = 1; + V[k] = (B1p*J + B1*Jp); + } + if(ProblemType==0) + y=PlnInt(a,U,V)*Depth; + else + y=AxiInt(-a,U,V,r); + + z+=y; + + break; + + case 30: // Lorentz Torque, 1X part for incremental AC problems + if(ProblemType==0) + { + B1=meshelem[i].B1; + B2=meshelem[i].B2; + B1p=meshelem[i].B1p; + B2p=meshelem[i].B2p; + Jp=meshelem[i].Jp; + c=Ctr(i)*LengthConv[LengthUnits]; + y= c.im*(B2*Jp + B2p*J) + c.re*(B1*Jp + B1p*J); + z+=(a*y*Depth); + } + break; + default: + break; + } + } + + // integrals that need to be evaluated over all elements, + // regardless of which elements are actually selected. + if(bMaskIntegral) + { + a=ElmArea(i)*pow(LengthConv[LengthUnits],2.); + if(ProblemType==1){ + for(k=0;k<3;k++) + r[k]=meshnode[meshelem[i].p[k]].x*LengthConv[LengthUnits]; + R=(r[0]+r[1]+r[2])/3.; + a*=(2.*PI*R); + } + else a*=Depth; + + switch(inttype){ + + case 18: // x (or r) direction Henrotte force, SS part. + if(ProblemType!=0) break; + + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + y=(((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + 2.*Re(B1*conj(B2))*Im(c))/(2.*muo); + if(Frequency!=0) y/=2.; + + y*=AECF(i); // correction for axisymmetric external region; + + z+=(a*y); + break; + + case 19: // y (or z) direction Henrotte force, SS part. + + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + + y=(((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + 2.*Re(B1*conj(B2))*Re(c))/(2.*muo); + + y*=AECF(i); // correction for axisymmetric external region; + + if(Frequency!=0) y/=2.; + z+=(a*y); + + break; + + case 20: // x (or r) direction Henrotte force, 2x part. + + if(ProblemType!=0) break; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + z+=a*((((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*muo)) * AECF(i); + + break; + + case 21: // y (or z) direction Henrotte force, 2x part. + + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + z+= a*((((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*muo)) * AECF(i); + + break; + + case 22: // Henrotte torque, SS part. + if(ProblemType!=0) break; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + + F1 = (((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + + 2.*Re(B1*conj(B2))*Im(c))/(2.*muo); + F2 = (((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + + 2.*Re(B1*conj(B2))*Re(c))/(2.*muo); + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3.; + + y=Re(c)*F2 -Im(c)*F1; + if(Frequency!=0) y/=2.; + y*=AECF(i); + z+=(a*y); + + break; + + case 23: // Henrotte torque, 2x part. + + if(ProblemType!=0) break; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + c=HenrotteVector(i); + F1 = (((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*muo); + F2 = (((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*muo); + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3; + + z+=a*(Re(c)*F2 -Im(c)*F1)*AECF(i); + + break; + + case 25: // x (or r) direction Henrotte force, 1x part for incremental AC problems + + if(ProblemType!=0) break; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + B1p=meshelem[i].B1p; + B2p=meshelem[i].B2p; + c=HenrotteVector(i); + z+=a*((B1*B1p - B2*B2p)*Re(c) + (B1p*B2 + B1*B2p)*Im(c))/muo * AECF(i); + + break; + + case 26: // y (or z) direction Henrotte force, 1x part for incremental AC problems + + B1=meshelem[i].B1; + B2=meshelem[i].B2; + B1p=meshelem[i].B1p; + B2p=meshelem[i].B2p; + c=HenrotteVector(i); + z+=a*((B1p*B2 + B1*B2p)*Re(c) + (-(B1*B1p) + B2*B2p)*Im(c))/muo * AECF(i); + + break; + + case 27: // Henrotte torque, 1x part for incremental AC problems + + if(ProblemType!=0) break; + B1=meshelem[i].B1; + B2=meshelem[i].B2; + B1p=meshelem[i].B1p; + B2p=meshelem[i].B2p; + c=HenrotteVector(i); + F1 = ((B1*B1p - B2*B2p)*Re(c) + (B1p*B2 + B1*B2p)*Im(c))/muo; + F2 = ((B1p*B2 + B1*B2p)*Re(c) + (-(B1*B1p) + B2*B2p)*Im(c))/muo; + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3; + + z+=a*(Re(c)*F2 -Im(c)*F1)*AECF(i); + + break; + + default: + break; + } + } + } + + return z; +} + +void CFemmviewDoc::LineIntegral(int inttype, CComplex *z) +{ +// inttype Integral +// 0 B.n +// 1 H.t +// 2 Contour length +// 3 Stress Tensor Force +// 4 Stress Tensor Torque +// 5 (B.n)^2 + + // inttype==0 => B.n + if(inttype==0){ + CComplex a0,a1; + CPointVals u; + double l; + int i,k; + + k=(int) contour.GetSize(); + GetPointValues(contour[0].re,contour[0].im, u); + a0=u.A; + GetPointValues(contour[k-1].re,contour[k-1].im,u); + a1=u.A; + if(ProblemType==0){ + for(i=0,l=0;i H.t + if(inttype==1){ + CComplex n,t,pt,Ht; + CPointVals v; + double dz,u,l; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + Ht = t.re*v.H1 + t.im*v.H2; + z[0]+=(Ht*dz*LengthConv[LengthUnits]); + } + } + + + for(i=0,l=0;i Contour Length + if(inttype==2){ + int i,k; + k=(int) contour.GetSize(); + for(i=0,z[0].re=0;i Stress Tensor Force + if(inttype==3){ + CComplex n,t,pt,Hn,Bn,BH,dF1,dF2; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + for(i=0;i<4;i++) z[i]=0; + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE) + if(Frequency==0){ + Hn= n.re*v.H1 + n.im*v.H2; + Bn= n.re*v.B1 + n.im*v.B2; + BH= v.B1*v.H1 + v.B2*v.H2; + dF1=v.H1*Bn + v.B1*Hn - n.re*BH; + dF2=v.H2*Bn + v.B2*Hn - n.im*BH; + + dza=dz*LengthConv[LengthUnits]; + if(ProblemType==1){ + dza*=2.*PI*pt.re*LengthConv[LengthUnits]; + dF1=0; + } + else dza*=Depth; + + z[0]+=(dF1*dza/2.); + z[1]+=(dF2*dza/2.); + } + else{ + Hn=n.re*v.H1 + n.im*v.H2; + Bn=n.re*v.B1 + n.im*v.B2; + BH = v.B1*v.H1 + v.B2*v.H2; + dF1 = v.H1*Bn + v.B1*Hn - n.re*BH; + dF2 = v.H2*Bn + v.B2*Hn - n.im*BH; + + dza=dz*LengthConv[LengthUnits]; + if(ProblemType==1){ + dza*=2.*PI*pt.re*LengthConv[LengthUnits]; + dF1=0; + } + else dza*=Depth; + + z[0]+=(dF1*dza/4.); + z[1]+=(dF2*dza/4.); + + BH = v.B1*v.H1.Conj() +v.B2*v.H2.Conj(); + + if (ProblemType!=1) + dF1 = v.H1*Bn.Conj() + v.B1*Hn.Conj() - n.re*BH; + dF2= v.H2*Bn.Conj() + v.B2*Hn.Conj() - n.im*BH; + + + z[2]+=(dF1*dza/4.); + z[3]+=(dF2*dza/4.); + } + } + + } + } + + // inttype==4 => Stress Tensor Torque + if(inttype==4){ + CComplex n,t,pt,Hn,Bn,BH,dF1,dF2,dT; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + for(i=0;i<2;i++) z[i].Set(0,0); + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE) + if(Frequency==0){ + Hn= n.re*v.H1 + n.im*v.H2; + Bn= n.re*v.B1 + n.im*v.B2; + BH= v.B1*v.H1 + v.B2*v.H2; + dF1=v.H1*Bn + v.B1*Hn - n.re*BH; + dF2=v.H2*Bn + v.B2*Hn - n.im*BH; + dT= pt.re*dF2 - dF1*pt.im; + dza=dz*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + + z[0]+=(dT*dza*Depth/2.); + } + else{ + Hn=n.re*v.H1 + n.im*v.H2; + Bn=n.re*v.B1 + n.im*v.B2; + BH = v.B1*v.H1 + v.B2*v.H2; + dF1 = v.H1*Bn + v.B1*Hn - n.re*BH; + dF2 = v.H2*Bn + v.B2*Hn - n.im*BH; + dT=pt.re*dF2 - dF1*pt.im; + dza=dz*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + + z[0]+=(dT*dza*Depth/4.); + + BH = v.B1*v.H1.Conj() +v.B2*v.H2.Conj(); + dF1 = v.H1*Bn.Conj() + v.B1*Hn.Conj() - n.re*BH; + dF2= v.H2*Bn.Conj() + v.B2*Hn.Conj() - n.im*BH; + dT= pt.re*dF2 - dF1*pt.im ; + + z[1]+=(dT*dza*Depth/4.); + + } + } + } + + } + + // inttype==5 => (B.n)^2 + if(inttype==5){ + CComplex n,t,pt,Ht; + CPointVals v; + double dz,u,l; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + Ht = n.re*v.B1 + n.im*v.B2; + z[0]+=(Ht*Ht.Conj()*dz*LengthConv[LengthUnits]); + } + } + + + for(i=0,l=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])); +} + +BOOL CFemmviewDoc::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"femmview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LineIntegralPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + int lastd_WeightingScheme=d_WeightingScheme; + sscanf(v,"%i",&d_WeightingScheme); + // update weighting scheme if the weighting scheme was changed in the prefs dialog. + if (lastd_WeightingScheme!=d_WeightingScheme) + { + WeightingScheme=d_WeightingScheme; + bHasMask=FALSE; + } + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShiftH); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void CFemmviewDoc::BendContour(double angle, double anglestep) +{ + if (angle==0) return; + if (anglestep==0) anglestep=1; + + int k,n; + double d,tta,dtta,R; + CComplex c,a0,a1; + + // check to see if there are at least enough + // points to have made one line; + k=(int) contour.GetSize()-1; + if (k<1) return; + + // restrict the angle of the contour to 180 degrees; + if ((angle<-180.) || (angle>180.)) return; + n=(int) ceil(fabs(angle/anglestep)); + tta=angle*PI/180.; + dtta=tta/((double) n); + + // pop last point off of the contour; + a1=contour[k]; + contour.RemoveAt(k); + a0=contour[k-1]; + + // compute location of arc center; + // and radius of the circle that the + // arc lives on. + d=abs(a1-a0); + R=d/(2.*sin(fabs(tta/2.))); + if(tta>0) c=a0 + (R/d)*(a1-a0)*exp(I*(PI-tta)/2.); + else c=a0+(R/d)*(a1-a0)*exp(-I*(PI+tta)/2.); + + // add the points on the contour + for(k=1;k<=n;k++) contour.Add(c+(a0-c)*exp(k*I*dtta)); +} + + +BOOL CFemmviewDoc::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); +} + +CComplex CFemmviewDoc::GetStrandedVoltageDrop(int lbl) +{ + // Derive the voltage drop associated with a stranded and + // current-carrying region. + + int i,k; + CComplex dVolts,rho; + CComplex A[3],J[3],U[3],V[3]; + double a,atot; + double r[3]; + + U[0]=1; U[1]=1; U[2]=1; + + for(i=0,dVolts=0,atot=0;iTurns)>1) + bl->FillFactor=1; + else + bl->FillFactor=-1; + bl->o=bp->Cduct; + bl->mu=0.; + + if (blockproplist[blocklist[lbl].BlockType].LamType<3) return; + + // compute total area of associated block + for(i=0,atot=0;iLamType-3; + // wiretype = 0 for magnet wire + // wiretype = 1 for stranded but non-litz wire + // wiretype = 2 for litz wire + // wiretype = 3 for rectangular wire + // wiretype = 4 for 10% CCA + // wiretype = 5 for 15% CCA + + if(wiretype==3) // rectangular wire + { + w=2.*PI*Frequency; + d=bp->WireD*0.001; + bl->FillFactor=fabs(d*d*((double) bl->Turns)/atot); + dd=d/sqrt(bl->FillFactor); // foil pitch + fill=d/dd; // fill for purposes of equivalent foil analysis + o=bp->Cduct*fill*1.e6; // effective foil conductivity in S/m + W=w*o*muo*d*d*fill/4.; + if((Frequency==0) || (bp->Cduct==0)) + { + bl->o = bp->Cduct*bl->FillFactor; + bl->LocalEnergy = (dd-d)*dd*muo/6.; + bl->mu = 1; + return; + } + + // effective permeability for the equivalent foil. Note that this is + // the same equation as effective permeability of a lamination... + ufd=muo*tanh(sqrt(I*W))/sqrt(I*W); + ueff=(fill*ufd+(1.-fill)*muo); + bl->o= 1./(muo/(fill*o*ufd) + I*dd*dd*(1.-fill)*muo*w/4. - I*dd*dd*ueff*w/12.); + bl->o*=1.e-6; // represent conductivity in units of MS/m for consistency with other parts of code. + bl->mu=ueff/muo; + + // Treat local stored energy separately because it becomes ill-posed as frequency goes to zero. + // use an approximate expression at low frequency. + + if (W > 0.1) + { + // normal higher-frequency regime + bl->LocalEnergy = (1.e-6)*Im(1/bl->o)/w; + } + else{ + // low-frequency asymptotic expression from Mathematica series expansion + bl->LocalEnergy =muo*((dd-d)*dd/6. + (2./189.)*d*dd*W*W); + } + return; + } + + // procedure for round wires; + + switch (wiretype) + { + // wiretype = 1 for stranded but non-litz wire + case 1: + R=bp->WireD*0.0005*sqrt((double) bp->NStrands); + awire=PI*R*R*((double) bl->Turns); + break; + + // wiretype = 2 for magnet wire, litz wire, CCA + default: + R=bp->WireD*0.0005; + awire=PI*R*R*((double) bp->NStrands)*((double) bl->Turns); + break; + } + bl->FillFactor=fabs(awire/atot); + fill=bl->FillFactor; + + // preliminary definitions + w=2.*PI*Frequency; // frequency in rad/s + o=bp->Cduct*1.e6; // conductivity in S/m + W=w*o*muo*R*R/2.; // non-dimensionalized frequency + dd=(1.6494541661869013*R)/sqrt(fill); // foil pitch in equivalent foil geometry + + // curve fits to FEA data for frequency-dependent permeabilty and conductivity + switch (wiretype) + { + case 0: // magnet wire + case 1: // plain stranded + case 2: // litz + + c1=0.7756067409818643 + fill*(0.6873854335408803 + fill*(0.06841584481674128 -0.07143732702512284*fill)); + c2=1.5*fill/c1; + c3=0.8824642871525136+fill*(-0.008605512994838827+fill*(0.7223208744682307-0.2157183942377177*fill)); + c4=log(1.5299240194394943/sqrt(fill))-c3/3.; + break; + + case 4: // 10% CCA + c1=0.7270741505617485 + 0.8902950067721367*fill + 0.11894736885885195*fill*fill - 0.12247276254503957*fill*fill*fill; + c2=0.006784920229549677 + 1.8942880489198526*fill - 1.3631438759519217*fill*fill + 0.504431701685587*fill*fill*fill; + c3=0.7879151117538901 - 0.7216375417404758*fill + 2.266562622770727*fill*fill - 1.1349603497265566*fill*fill*fill; + c4=1.6190358786364027 - 3.967461431323324*fill + 4.068458362148543*fill*fill - 1.7975534375694646*fill*fill*fill; + break; + + case 5: // 15% CCA + c1=0.7486913529860821 + 0.9042845510838825*fill + 0.1361040321433224*fill*fill - 0.10652380745682069*fill*fill*fill; + c2=0.006790468527313965 + 1.8945509985370095*fill - 1.3643501010185972*fill*fill + 0.5036765577982594*fill*fill*fill; + c3=0.7519323306379909 - 0.7184130853903536*fill + 2.2551599408130594*fill*fill - 1.1439852083597326*fill*fill*fill; + c4=1.6204876714534728 - 3.966250827502031*fill + 4.064413095233383*fill*fill - 1.7940297437703776*fill*fill*fill; + break; + } + + // can punch out early if no eddy current effects + if ((Frequency==0) || (bp->Cduct==0)) + { + bl->o = bp->Cduct*fill; + bl->LocalEnergy = muo*(2*(c3 + 3*c4)*R*R/fill - dd*dd)/12; + bl->mu = 1.; // relative permeability of the block. + return; + } + + // fit for frequency-dependent conductivity.... + ufd=c2*(tanh(sqrt(c1*I*W))/sqrt(c1*I*W))+(1.-c2); // relative frequency-dependent permeability + bl->mu=ufd; + ofd=o*fill/(I*c4*W+sqrt(I*c3*W)*(1./tanh(sqrt(I*c3*W)))); // fit to curves in Skin4.nb + ofd=1./(1./ofd-I*w*ufd*muo*dd*dd/12.); // don't double-book local stored energy; + bl->o=ofd*1.e-6; // return frequency-dependent conductivity in MS/m + + // Treat local stored energy separately because it becomes ill-posed as frequency goes to zero. + // use an approximate expression at low frequency. + if (W > 0.1) + { + // normal higher-frequency regime + bl->LocalEnergy = (1.e-6)*Im(1/bl->o)/w; + } + else{ + // low-frequency asymptotic expression from Mathematica series expansion + bl->LocalEnergy =(muo*(21*dd*dd*fill*(-15 + 2*c1*c1*c2*W*W) + + 2*R*R*(315*(c3 + 3*c4) - 2*c3*c3*c3*W*W)))/(3780.*fill); + } +} + +CComplex CFemmviewDoc::GetStrandedLinkage(int lbl) +{ + // This is a routine for the special case of determining + // the flux linkage of a stranded conductor at zero frequency + // when the conductor is carrying zero current. + int i,k; + CComplex FluxLinkage; + CComplex A[3],J[3],U[3],V[3]; + double a,atot; + double r[3]; + + U[0]=1; U[1]=1; U[2]=1; + + for(i=0,FluxLinkage=0,atot=0;i2) // is a region subject to prox effects + { + mu1=blocklist[meshelem[i].lbl].mu; + mu2=mu1; + } + else blockproplist[meshelem[i].blk].GetMu(b1,b2,mu1,mu2); + + double aecf=AECF(i); mu1/=aecf; mu2/=aecf; +} + +void CFemmviewDoc::GetMu(double b1, double b2, double &mu1, double &mu2, int i) +{ + blockproplist[meshelem[i].blk].GetMu(b1,b2,mu1,mu2); + double aecf=AECF(i); mu1/=aecf; mu2/=aecf; +} + +void CFemmviewDoc::GetH(double b1, double b2, double &h1, double &h2, int k) +{ + double mu1,mu2; + CComplex Hc; + + GetMu(b1,b2,mu1,mu2,k); + h1 = b1/(mu1*muo); + h2 = b2/(mu2*muo); + if ((d_ShiftH) && (blockproplist[meshelem[k].blk].H_c!=0)) + { + Hc = blockproplist[meshelem[k].blk].H_c* + exp(I*PI*meshelem[k].magdir/180.); + h1=h1-Re(Hc); + h2=h2-Im(Hc); + } +} + +void CFemmviewDoc::GetH(CComplex b1, CComplex b2, CComplex &h1, CComplex &h2, int k) +{ + CComplex mu1,mu2; + + GetMu(b1,b2,mu1,mu2,k); + h1 = b1/(mu1*muo); + h2 = b2/(mu2*muo); +} + +void CFemmviewDoc::FindBoundaryEdges() +{ + int i, j; + static int plus1mod3[3] = {1, 2, 0}; + static int minus1mod3[3] = {2, 0, 1}; + + // Init all elements' neigh to be unfinished. + for(i = 0; i < meshelem.GetSize(); i ++) { + for(j = 0; j < 3; j ++) + meshelem[i].n[j] = 0; + } + + int orgi, desti; + int ei, ni; + BOOL done; + + // Loop all elements, to find and set there neighs. + for(i = 0; i < meshelem.GetSize(); i ++) { + for(j = 0; j < 3; j ++) { + if(meshelem[i].n[j] == 0) { + // Get this edge's org and dest node index, + orgi = meshelem[i].p[plus1mod3[j]]; + desti = meshelem[i].p[minus1mod3[j]]; + done = FALSE; + // Find this edge's neigh from the org node's list + for(ni = 0; ni < NumList[orgi]; ni ++) { + // Find a Element around org node contained dest node of this edge. + ei = ConList[orgi][ni]; + if(ei == i) continue; // Skip myself. + // Check this Element's 3 vert to see if there exist dest node. + if(meshelem[ei].p[0] == desti) { + done = TRUE; + break; + } else if(meshelem[ei].p[1] == desti) { + done = TRUE; + break; + } else if(meshelem[ei].p[2] == desti) { + done = TRUE; + break; + } + } + if(!done) { + // This edge must be a Boundary Edge. + meshelem[i].n[j] = 1; + } + } // Finish One Edge + } // End of One Element Loop + } // End of Main Loop + +} + +double CFemmviewDoc::ShortestDistance(double p, double q, int segm) +{ + double t,x[3],y[3]; + + x[0]=nodelist[linelist[segm].n0].x; + y[0]=nodelist[linelist[segm].n0].y; + x[1]=nodelist[linelist[segm].n1].x; + y[1]=nodelist[linelist[segm].n1].y; + + t=((p-x[0])*(x[1]-x[0]) + (q-y[0])*(y[1]-y[0]))/ + ((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])); + + if (t>1.) 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 CFemmviewDoc::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;i0) + { + ac+= R*(-agelist[j].brs[k]*cos(n*tta) + agelist[j].brc[k]*sin(n*tta))/((double) n); + } + else{ + ac+=agelist[j].aco; + } + br += agelist[j].brc[k]*cos(n*tta) + agelist[j].brs[k]*sin(n*tta); + bt += agelist[j].btc[k]*cos(n*tta) + agelist[j].bts[k]*sin(n*tta); + } + hr=br/muo; + ht=bt/muo; + + if (Frequency==0){ + switch (PlotType){ + case 0: + p.M[i][1]=Re(ac); + break; + case 1: + p.M[i][1]=Re(sqrt(br*conj(br) + bt*conj(bt))); + break; + case 2: + p.M[i][1]= Re(br); + break; + case 3: + p.M[i][1]= Re(bt); + break; + case 4: + p.M[i][1]=Re(sqrt(hr*conj(hr) + ht*conj(ht))); + break; + case 5: + p.M[i][1]= Re(hr); + break; + case 6: + p.M[i][1]= Re(ht); + break; + default: + p.M[i][1]=0; + break; + } + } + else{ + switch (PlotType){ + case 0: + p.M[i][1]=abs(ac); + p.M[i][2]=Re(ac); + p.M[i][3]=Im(ac); + break; + case 1: + p.M[i][1]=Re(sqrt(br*conj(br) + bt*conj(bt))); + break; + case 2: + p.M[i][2]=Re(br); + p.M[i][3]=Im(br); + p.M[i][1]=abs(br); + break; + case 3: + p.M[i][2]=Re(bt); + p.M[i][3]=Im(bt); + p.M[i][1]=abs(bt); + break; + case 4: + p.M[i][1]=Re(sqrt(hr*conj(hr) + ht*conj(ht))); + break; + case 5: + p.M[i][2]=Re(hr); + p.M[i][3]=Im(hr); + p.M[i][1]=abs(hr); + break; + case 6: + p.M[i][2]=Re(ht); + p.M[i][3]=Im(ht); + p.M[i][1]=abs(ht); + break; + default: + p.M[i][1]=0; + break; + } + } + } +} \ No newline at end of file diff --git a/femm/FemmviewDoc.h b/femm/FemmviewDoc.h new file mode 100644 index 0000000..1099a6b --- /dev/null +++ b/femm/FemmviewDoc.h @@ -0,0 +1,247 @@ +// femmviewDoc.h : interface of the CFemmviewDoc class +// +///////////////////////////////////////////////////////////////////////////// +#include "lua.h" +#include "luadebug.h" +#include "luaconsoledlg.h" + +//#define APPROXGAP + +extern CFemmApp theApp; // + +class CFemmviewDoc : public CDocument +{ + +protected: // create from serialization only + CFemmviewDoc(); + DECLARE_DYNCREATE(CFemmviewDoc) + +// Attributes +public: + + // General problem attributes + double Frequency; + double Depth; + int LengthUnits; + double *LengthConv; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + CString PrevSoln; + int PrevType; + BOOL bIncremental; + BOOL FirstDraw; + BOOL Smooth; + BOOL bMultiplyDefinedLabels; + int WeightingScheme; + double extRo,extRi,extZo; + + double A_High, A_Low; + double A_lb, A_ub; + + double PlotBounds[9][2]; + double d_PlotBounds[9][2]; +// double Br_High,Br_Low; +// double Bi_High,Bi_Low; + double B_High, B_Low; + double H_High; +// double B_lb, B_ub; +// double Jr_High,Jr_Low; +// double Ji_High,Ji_Low; +// double J_High, J_Low; + + // Some default behaviors + CString BinDir; + int d_LineIntegralPoints; + int d_WeightingScheme; + BOOL d_ShiftH; + BOOL bHasMask; + + // lists of nodes, segments, and block labels + CArray< femmviewdata::CNode, femmviewdata::CNode&> nodelist; + CArray< femmviewdata::CSegment, femmviewdata::CSegment&> linelist; + CArray< femmviewdata::CBlockLabel, femmviewdata::CBlockLabel&> blocklist; + CArray< femmviewdata::CArcSegment, femmviewdata::CArcSegment&> arclist; + + // CArrays containing the mesh information + CArray< femmviewdata::CMeshNode, femmviewdata::CMeshNode&> meshnode; + CArray< femmviewdata::CElement, femmviewdata::CElement&> meshelem; + CArray< femmviewdata::CAirGapElement, femmviewdata::CAirGapElement&> agelist; + + // List of elements connected to each node; + int *NumList; + int **ConList; + + // lists of properties + CArray< femmviewdata::CMaterialProp, femmviewdata::CMaterialProp& > blockproplist; + CArray< femmviewdata::CBoundaryProp, femmviewdata::CBoundaryProp& > lineproplist; + CArray< femmviewdata::CPointProp, femmviewdata::CPointProp& > nodeproplist; + CArray< femmviewdata::CCircuit, femmviewdata::CCircuit& > circproplist; + + // list of points in a user-defined contour; + CArray< CComplex, CComplex& > contour; + + // stuff that PTLOC needs + CArray< CMeshNode, CMeshNode&> *pmeshnode; + CArray< CElement, CElement&> *pmeshelem; +// TriEdge recenttri; +// int samples; +// unsigned long randomseed; +// TriEdge bdrylinkhead[512]; +// int numberofbdrylink; + + // member functions + int InTriangle(double x, double y); + BOOL InTriangleTest(double x, double y, int i); + BOOL GetPointValues(double x, double y, CPointVals &u); + BOOL GetPointValues(double x, double y, int k, CPointVals &u); + void GetLineValues(CXYPlot &p, int PlotType, int npoints); + void GetGapValues(CXYPlot &p, int PlotType, int npoints, int myAGE); + void GetElementB(femmviewdata::CElement &elm); + void OnReload(); + void FindBoundaryEdges(); + int ClosestNode(double x, double y); + int ClosestSegment(double x, double y); + double ShortestDistance(double p, double q, int segm); + CComplex Ctr(int i); + double ElmArea(int i); + double ElmArea(femmviewdata::CElement *elm); + void GetPointB(double x, double y, CComplex &B1, CComplex &B2, + femmviewdata::CElement &elm); + void GetNodalB(CComplex *b1, CComplex *b2,femmviewdata::CElement &elm); + CComplex BlockIntegral(int inttype); + void LineIntegral(int inttype, CComplex *z); + int ClosestArcSegment(double x, double y); + void GetCircle(femmviewdata::CArcSegment &asegm,CComplex &c, double &R); + double ShortestDistanceFromArc(CComplex p, femmviewdata::CArcSegment &arc); + double ShortestDistanceFromSegment(double p, double q, int segm); + CComplex GetJA(int k,CComplex *J,CComplex *A); + CComplex PlnInt(double a, CComplex *u, CComplex *v); + CComplex AxiInt(double a, CComplex *u, CComplex *v,double *r); + BOOL ScanPreferences(); + void BendContour(double angle, double anglestep); + BOOL MakeMask(); + CComplex HenrotteVector(int k); + BOOL IsKosher(int k); + double AECF(int k); + void GetFillFactor(int lbl); + + CComplex GetStrandedVoltageDrop(int lbl); + CComplex GetVoltageDrop(int circnum); + CComplex GetFluxLinkage(int circnum); + CComplex GetStrandedLinkage(int lbl); + CComplex GetSolidAxisymmetricLinkage(int lbl); + CComplex GetParallelLinkage(int numcirc); + CComplex GetParallelLinkageAlt(int numcirc); + void GetMu(CComplex b1, CComplex b2,CComplex &mu1, CComplex &mu2, int i); + void GetMu(double b1, double b2, double &mu1, double &mu2, int i); + void GetMagnetization(int n, CComplex &M1, CComplex &M2); + void GetH(double b1, double b2, double &h1, double &h2, int k); + void GetH(CComplex b1, CComplex b2, CComplex &h1, CComplex &h2, int k); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmviewDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + // lua extensions + bool luafired; + void initalise_lua(); + static int lua_dumpheader(lua_State * L); + static int lua_getpointvals(lua_State * L); + static int lua_exitpost(lua_State * L); + static int lua_addcontour(lua_State * L); + static int lua_clearcontour(lua_State * L); + static int lua_lineintegral(lua_State * L); + static int lua_selectblock(lua_State * L); + static int lua_groupselectblock(lua_State * L); + static int lua_blockintegral(lua_State * L); + static int lua_clearblock(lua_State * L); + static int lua_zoomout(lua_State * L); + static int lua_zoomin(lua_State * L); + static int lua_zoomnatural(lua_State * L); + static int lua_hidemesh(lua_State * L); + static int lua_showmesh(lua_State * L); + static int lua_showgrid(lua_State * L); + static int lua_hidegrid(lua_State * L); + static int lua_showdensity(lua_State * L); + static int lua_hidedensity(lua_State * L); + static int lua_hidecountour(lua_State * L); + static int lua_showcountour(lua_State * L); + static int lua_zoom(lua_State * L); + static int lua_smoothing(lua_State * L); + static int lua_hidepoints(lua_State * L); + static int lua_showpoints(lua_State * L); + static int lua_gridsnap(lua_State * L); + static int lua_setgrid(lua_State * L); + static int lua_getprobleminfo(lua_State * L); + static int lua_savebitmap(lua_State * L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC) ; + static int lua_getcircuitprops(lua_State *L); + static int lua_saveWMF(lua_State *L); + static int lua_refreshview(lua_State *L); + static int lua_selectline(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_bendcontour(lua_State *L); + static int lua_makeplot(lua_State *L); + static int lua_shownames(lua_State *L); + static int lua_vectorplot(lua_State *L); + static int lua_gradient(lua_State *L); + static int lua_reload(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_gettitle(lua_State *L); + static int lua_weighting(lua_State *L); + + // commands to access low-level information through Lua + static int lua_numnodes(lua_State *L); + static int lua_numelements(lua_State *L); + static int lua_getnode(lua_State *L); + static int lua_getelement(lua_State *L); + + // functions used for compatibility with older versions + static int old_lua_lineintegral(lua_State * L); + static int old_lua_getpointvals(lua_State * L); + static int old_lua_blockintegral(lua_State * L); + static int old_lua_getcircuitprops(lua_State *L); + + // functions used to query air gap elements + static int lua_getAGEflux(lua_State *L); + static int lua_gapintegral(lua_State *L); + static int lua_getgapa(lua_State *L); + static int lua_getgapharmonics(lua_State *L); + + virtual ~CFemmviewDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmviewDoc) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); diff --git a/femm/FemmviewView.cpp b/femm/FemmviewView.cpp new file mode 100644 index 0000000..eed85ce --- /dev/null +++ b/femm/FemmviewView.cpp @@ -0,0 +1,4761 @@ +// femmviewView.cpp : implementation of the CFemmviewView class +// + +#include "stdafx.h" +#include +#include +#include "femm.h" +#include "problem.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewView.h" +#include "GridMod.h" +#include "EnterPt.h" +#include "CPlotDlg.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "KbdZoom.h" +#include "CPlotDlg2.h" +#include "cv_DPlotDlg2.h" +#include "MyMsgBox.h" +#include "XYPlotDlg.h" +#include "LIntDlg.h" +#include "BlockInt.h" +#include "CircDlg.h" +#include "BendContourDlg.h" +#include "VPlotDlg.h" +#include "GapIntegral.h" +#include "GapPlotDlg.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm; +extern int Ym; + +#define MSKHI (1. + 1.e-08) +#define MSKLO (0. - 1.e-08) + +extern lua_State * lua; +extern BOOL bLinehook; + + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewView + +IMPLEMENT_DYNCREATE(CFemmviewView, CView) + +BEGIN_MESSAGE_MAP(CFemmviewView, CView) + //{{AFX_MSG_MAP(CFemmviewView) + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_CPLOT, OnCplot) + ON_COMMAND(ID_DPLOT, OnDplot) + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWindow) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_RELOAD, OnReload) + ON_COMMAND(ID_MENU_AREA, OnMenuArea) + ON_COMMAND(ID_MENU_CONTOUR, OnMenuContour) + ON_COMMAND(ID_MENU_POINT, OnMenuPoint) + ON_WM_KEYDOWN() + ON_COMMAND(ID_MENU_PLOT, OnMenuPlot) + ON_COMMAND(ID_MENU_INTEGRATE, OnMenuIntegrate) + ON_COMMAND(ID_MENUSHOWPTS, OnMenushowpts) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_COMMAND(ID_SMOOTH, OnSmooth) + ON_WM_ERASEBKGND() + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_VIEW_CIRCPROPS, OnViewCircprops) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_BHCURVES, OnViewBHcurves) + ON_COMMAND(ID_VIEW_INFO, OnViewInfo) + ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames) + ON_COMMAND(ID_VPLOT, OnVplot) + ON_WM_SIZE() + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_LBUTTONDBLCLK() +END_MESSAGE_MAP() + +void MyMessageBox(CString s) +{ + CString z; + char linfeed[3]; + int i; + + sprintf(linfeed,"%c%c",0x0D,0x0A); + for(i=0;iNumViews++; + + // TODO: add construction code here + d_EditAction=0; + d_GridFlag=FALSE; + d_SnapFlag=FALSE; + d_MeshFlag=FALSE; + d_LegendFlag=TRUE; + d_GreyContours=FALSE; + d_NumContours=19; + d_ShowAr=TRUE; + d_ShowAi=FALSE; + d_ShowMask=FALSE; + d_DensityPlot=0; + d_VectorPlot=0; + d_PtsFlag=TRUE; + d_ResetOnReload=FALSE; + d_Smooth=TRUE; + d_PlotPoints=1500; + d_ShowNames=FALSE; + + ox=0.; oy=0.; mag=100.; // lower left corner is origin; 100 dpi + GridSize=0.25; // 1/4" grid + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + VectorScaleFactor=1; + + ////////////////////////////// + // Default Colors // + ////////////////////////////// + + // Greyscale Colormap + Grey00=dGrey00; + Grey01=dGrey01; + Grey02=dGrey02; + Grey03=dGrey03; + Grey04=dGrey04; + Grey05=dGrey05; + Grey06=dGrey06; + Grey07=dGrey07; + Grey08=dGrey08; + Grey09=dGrey09; + Grey10=dGrey10; + Grey11=dGrey11; + Grey12=dGrey12; + Grey13=dGrey13; + Grey14=dGrey14; + Grey15=dGrey15; + Grey16=dGrey16; + Grey17=dGrey17; + Grey18=dGrey18; + Grey19=dGrey19; + + // BELA Colormap + Color19=dColor19; + Color18=dColor18; + Color17=dColor17; + Color16=dColor16; + Color15=dColor15; + Color14=dColor14; + Color13=dColor13; + Color12=dColor12; + Color11=dColor11; + Color10=dColor10; + Color09=dColor09; + Color08=dColor08; + Color07=dColor07; + Color06=dColor06; + Color05=dColor05; + Color04=dColor04; + Color03=dColor03; + Color02=dColor02; + Color01=dColor01; + Color00=dColor00; + + // Other colors + SelColor = dSelColor; + MeshColor = dMeshColor; + BlockColor = dBlockColor; + LineColor = dLineColor; + RegionColor = dRegionColor; + GridColor = dGridColor; + BackColor = dBackColor; + NodeColor = dNodeColor; + TextColor = dTextColor; + RealFluxLineColor = dRealFluxLineColor; + ImagFluxLineColor = dImagFluxLineColor; + MaskLineColor = dMaskLineColor; + NameColor = dNameColor; + RealVectorColor = dRealVectorColor; + ImagVectorColor = dImagVectorColor; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // Apply default behaviors + EditAction=d_EditAction; + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowAi=d_ShowAi; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; + ShowNames=d_ShowNames; +} + +CFemmviewView::~CFemmviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL CFemmviewView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewView drawing +void CFemmviewView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +BOOL CFemmviewView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CFemmviewView::DoContours(CDC *pDC,int *p,int side,int Aflag) +{ + int i,j,k; + static double q[4][4]; + static double *m[4]; + static int u[4]; + double *swap; + double hi,lo,a,b,z,offset; + double a0,a1,r0,r1,md; + + CFemmviewDoc *pDoc=GetDocument(); + + switch(side) + { + case 0 : u[0]=p[0]; u[1]=p[1]; u[2]=p[1]; u[3]=p[2]; break; + case 1 : u[0]=p[1]; u[1]=p[2]; u[2]=p[2]; u[3]=p[0]; break; + default: u[0]=p[2]; u[1]=p[0]; u[2]=p[0]; u[3]=p[1]; break; + } + + for(i=0;i<4;i++){ + m[i]=q[i]; + m[i][0]=(double) pDoc->meshnode[u[i]].xs; + m[i][1]=(double) pDoc->meshnode[u[i]].ys; + m[i][3]=pDoc->meshnode[u[i]].x; + if (Aflag==0) m[i][2]=pDoc->meshnode[u[i]].A.re; + if (Aflag==1) m[i][2]=pDoc->meshnode[u[i]].A.im; + if (Aflag==2) m[i][2]=pDoc->meshnode[u[i]].msk; + } + + // scale A for easier analysis. Not necessary if mask is being displayed, + // since mask always varies between zero and one. + + if (Aflag<2) + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-pDoc->A_Low)/ + (pDoc->A_High-pDoc->A_Low); + offset=-NumContours*pDoc->A_Low/(pDoc->A_High-pDoc->A_Low); + } + else + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-MSKLO)/(MSKHI-MSKLO); + offset=-NumContours*MSKLO/(MSKHI-MSKLO); + } + + // swap around so that lowest magnitude is first point in + // each line... + if (m[0][2]>m[1][2]){ + swap=m[1]; + m[1]=m[0]; + m[0]=swap; + } + if (m[2][2]>m[3][2]){ + swap=m[3]; + m[3]=m[2]; + m[2]=swap; + } + + // figure out which contours lie in this section + lo=m[0][2]; if(m[2][2]>lo) lo=m[2][2]; + hi=m[1][2]; if(m[3][2]=0) && (iProblemType==1) && (Aflag!=2)){ + + r0=m[0][3]; r1=m[1][3]; + if(fabs(r0)>1.e-06) a0=(m[0][2]-offset)/r0; else a0=0; + if(fabs(r1)>1.e-06) a1=(m[1][2]-offset)/r1; else a1=0; + md=(a0+a1)*(r0+r1)/4. + offset; + + if((md>m[0][2]) && (md1.e-2)) + { + a=(3.*m[0][2] + m[1][2] - 4.*md + + sqrt(pow(3.*m[0][2] + m[1][2] - 4.*md,2.) - + 8.*(m[0][2] + m[1][2] - 2.*md)*(m[0][2] - z)))/ + (4.*(m[0][2] + m[1][2] - 2*md)); + } + + + r0=m[2][3]; r1=m[3][3]; + if(fabs(r0)>1.e-06) a0=(m[2][2]-offset)/r0; else a0=0; + if(fabs(r1)>1.e-06) a1=(m[3][2]-offset)/r1; else a1=0; + md=(a0+a1)*(r0+r1)/4. + offset; + + if((md>m[2][2]) && (md1.e-2)) + { + b=(3.*m[2][2] + m[3][2] - 4.*md + + sqrt(pow(3.*m[2][2] + m[3][2] - 4.*md,2.) - + 8.*(m[2][2] + m[3][2] - 2.*md)*(m[2][2] - z)))/ + (4.*(m[2][2] + m[3][2] - 2*md)); + } + + } + + MyMoveTo(pDC,(int) ((m[1][0]-m[0][0])*a+m[0][0]), + (int) ((m[1][1]-m[0][1])*a+m[0][1])); + MyLineTo(pDC,(int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1])); + + if(Aflag==0) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), RealFluxLineColor ); + + if(Aflag==1) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), ImagFluxLineColor ); + + if(Aflag==2) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), MaskLineColor ); + } +} +//////////////// +void CFemmviewView::PlotFluxDensity(CDC *pDC,int elmnum,int flag) +{ + if(flag==0) return; + + + int i,j,k,n,lav; + double b,bn[3],bh,bl,y,z; + CComplex b1,b2,h1,h2,J[3],A[3]; + POINT ps[3]; + static double c[64][3],p[3][2]; + CElement elm; + CFemmviewDoc *pDoc=GetDocument(); + + elm=pDoc->meshelem[elmnum]; + + if (((pDoc->meshnode[elm.p[0]].xs == pDoc->meshnode[elm.p[1]].xs) && + (pDoc->meshnode[elm.p[1]].xs == pDoc->meshnode[elm.p[2]].xs)) || + ((pDoc->meshnode[elm.p[0]].ys == pDoc->meshnode[elm.p[1]].ys) && + (pDoc->meshnode[elm.p[1]].ys == pDoc->meshnode[elm.p[2]].ys) )) return; + + if(pDoc->blocklist[elm.lbl].IsSelected==TRUE) return; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + bl=pDoc->PlotBounds[flag-1][0]; + bh=pDoc->PlotBounds[flag-1][1]; + + if (pDoc->Frequency!=0) switch(flag) + { + case 1: // |B| + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + bn[i]=sqrt(b1.re*b1.re + b1.im*b1.im + b2.re*b2.re + b2.im*b2.im); + } + + break; + + case 2: // Re(B) + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + bn[i]=sqrt(b1.re*b1.re + b2.re*b2.re); + } + + break; + + case 3: // Im(B) + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + bn[i]=sqrt(b1.im*b1.im + b2.im*b2.im); + } + + break; + + case 4: // |H| + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + pDoc->GetH(b1,b2,h1,h2,elmnum); + bn[i]=sqrt(h1.re*h1.re + h1.im*h1.im + h2.re*h2.re + h2.im*h2.im); + } + + break; + + case 5: // Re(H) + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + pDoc->GetH(b1,b2,h1,h2,elmnum); + bn[i]=sqrt(h1.re*h1.re + h2.re*h2.re); + } + + break; + + case 6: // Im(H) + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + pDoc->GetH(b1,b2,h1,h2,elmnum); + bn[i]=sqrt(h1.im*h1.im + h2.im*h2.im); + } + + break; + + case 7: // |J| + pDoc->GetJA(elmnum,J,A); + for(i=0;i<3;i++) bn[i]=abs(J[i])*1.e-6; + break; + + case 8: // Re(J) + pDoc->GetJA(elmnum,J,A); + for(i=0;i<3;i++) bn[i]=fabs(J[i].re)*1.e-6; + break; + + case 9: // Im(J) + pDoc->GetJA(elmnum,J,A); + for(i=0;i<3;i++) bn[i]=fabs(J[i].im)*1.e-6; + break; + } + else switch(flag) + { + case 1: // |B| + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + bn[i]=sqrt(b1.re*b1.re + b1.im*b1.im + b2.re*b2.re + b2.im*b2.im); + } + break; + + case 2: // |H| + + for(i=0;i<3;i++) + { + if (pDoc->Smooth==TRUE) + { + b1=elm.b1[i]; b2=elm.b2[i]; + } + else{ + b1=elm.B1; b2=elm.B2; + } + pDoc->GetH(b1.re,b2.re,h1.re,h2.re,elmnum); + bn[i]=sqrt(h1.re*h1.re + h2.re*h2.re); + } + break; + + case 3: // |J| + + pDoc->GetJA(elmnum,J,A); + for(i=0;i<3;i++) bn[i]=abs(J[i])*1.e-6; + break; + } + + if(bh==bl) return; + else for(i=0;i<3;i++) bn[i]=20.*(bn[i]-bl)/(bh-bl); + + // find subtriangle edges; + for(i=0,n=0;i<3;i++) + { + c[n][0]=(double) pDoc->meshnode[elm.p[i]].xs; + c[n][1]=(double) pDoc->meshnode[elm.p[i]].ys; + c[n][2]=bn[i]; + n++; if(n>=64) return; + j=i+1; if(j==3) j=0; + p[0][0]=(double) pDoc->meshnode[elm.p[i]].xs; + p[0][1]=(double) pDoc->meshnode[elm.p[i]].ys; + p[1][0]=(double) pDoc->meshnode[elm.p[j]].xs; + p[1][1]=(double) pDoc->meshnode[elm.p[j]].ys; + p[2][0]=bn[i]; + p[2][1]=bn[j]; + if(p[2][0]=0) && (z<20)) n++; + if(n>=64) return; + } + else + for(z=floor(p[2][0]);z>p[2][1];z--) + { + y=(z-p[2][0])/(p[2][1]-p[2][0]); + c[n][0]=(1.-y)*p[0][0] + y*p[1][0]; + c[n][1]=(1.-y)*p[0][1] + y*p[1][1]; + c[n][2]=(1.-y)*p[2][0] + y*p[2][1]; + if ((z>=0) && (z<20)) n++; + if(n>=64) return; + } + + } + + // subtriangle vertices are now listed in the c[][] array. + // there are n vertices. Now, plot out these subtriangles; + + do{ + // find lowest vertex & neighbors; + for(i=1,j=0;i=n) k=0; + + // plot triangle; + b=(c[i][2]+c[j][2]+c[k][2])/3.; + lav=19-((int) b); + if(lav>19) lav=19; + if(lav<0) lav=0; + + { + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + BOOL DrawIt=TRUE; + + if (GreyContours==FALSE){ + if(mymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(mymap[lav]); + FillPen.CreatePen(PS_SOLID,1,mymap[lav]); + } + } + else{ + if(greymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(greymap[lav]); + FillPen.CreatePen(PS_SOLID,1,greymap[lav]); + } + } + if(DrawIt==TRUE) + { + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + ps[0].x=(long) c[i][0]; ps[0].y=(long) c[i][1]; + ps[1].x=(long) c[j][0]; ps[1].y=(long) c[j][1]; + ps[2].x=(long) c[k][0]; ps[2].y=(long) c[k][1]; + pDC->Polygon(ps,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); + } + } + + // remove middle point from the list; + for(i=j;i2); +} + +/////////////// + +void CFemmviewView::PlotSelectedElm(CDC *pDC,CElement &elm) +{ + int i; + POINT p[3]; + CFemmviewDoc *pDoc=GetDocument(); + + if (elm.lbl!=DrawSelected) + if (pDoc->blocklist[elm.lbl].IsSelected==FALSE) return; + + for(i=0;i<3;i++){ + p[i].x=pDoc->meshnode[elm.p[i]].xs; + p[i].y=pDoc->meshnode[elm.p[i]].ys; + } + + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + if (pDoc->blocklist[elm.lbl].IsSelected==TRUE) + { + FillBrush.CreateSolidBrush(RegionColor); + FillPen.CreatePen(PS_SOLID,1,RegionColor); + } + else{ + FillBrush.CreateSolidBrush(0x00ffffff); + FillPen.CreatePen(PS_SOLID,1,0x00ffffff); + } + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + pDC->Polygon(p,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); +} + +void CFemmviewView::DrawUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CFemmviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,FALSE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,FALSE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,FALSE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CFemmviewView::EraseUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CFemmviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,TRUE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,TRUE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,TRUE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CFemmviewView::OnDraw(CDC* pDC) +{ + CFemmviewDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + RECT r; + static RECT oldr; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,dt,R; + double xss,yss,rss,rt; + CComplex p,c,s; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if(pDoc->FirstDraw<0) + { + pDoc->Smooth=d_Smooth; + pDoc->FirstDraw=FALSE; + } + + if(pDoc->FirstDraw==TRUE){ + // Apply default behaviors + ox=0.; oy=0.; mag=100.; + GridSize=0.25; + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + VectorScaleFactor=1; + if (pDoc->bMultiplyDefinedLabels){ + EditAction=2; + ShowNames=TRUE; + } + else{ + EditAction=d_EditAction; + ShowNames=d_ShowNames; + } + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowAi=d_ShowAi; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + if (pDoc->Frequency==0) + { + switch(DensityPlot) + { + case 1: case 2: case 3: + DensityPlot=1; break; + case 4: case 5: case 6: + DensityPlot=2; break; + case 7: case 8: case 9: + DensityPlot=3; break; + default: DensityPlot=0; break; + } + } + VectorPlot=d_VectorPlot; + PtsFlag=d_PtsFlag; + pDoc->Smooth=d_Smooth; + + // catch inconsistent default settings + if(pDoc->Frequency==0) + { + if (DensityPlot==2) DensityPlot=1; + if (DensityPlot>1) DensityPlot=0; + d_ShowAi=FALSE; + } + + OnZoomNatural(); + LinePix.RemoveAll(); + oldr=r; + OnViewInfo(); + } + + if((oldr.right!=r.right) || (oldr.bottom!=r.bottom)) + { + LinePix.RemoveAll(); + oldr=r; + } + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + // just give up and make sure that the right + // buttons are checked every time through OnDraw; + // otherwise, it's just too easy to get the buttons + // so that they don't match the actual mode. + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen, + penMesh,penReal,penImag,penMask, + penNode,penText,penRealVector,penImagVector; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penReal.CreatePen(PS_SOLID,1,RealFluxLineColor); + penImag.CreatePen(PS_SOLID,1,ImagFluxLineColor); + penMask.CreatePen(PS_SOLID,1,MaskLineColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penText.CreatePen(PS_SOLID,1,TextColor); + penRealVector.CreatePen(PS_SOLID,1,RealVectorColor); + penImagVector.CreatePen(PS_SOLID,1,ImagVectorColor); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=2.; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // get center and radius of the screen in drawing coords. + // can then use to find out whether elements are off the screen. + xs=(r.right+r.left)/2; + ys=(r.top+r.bottom)/2; + ScreenToDwg(xs,ys, &xss, &yss, &r); + rss=sqrt(pow((double)r.bottom,2.) + pow((double)r.right,2.))/(2.*mag); + + // Draw selected area... + if (EditAction==2) + { + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + PlotSelectedElm(pDC,pDoc->meshelem[i]); + } + } + } + + // Draw flux densities if they are enabled... + if(DensityPlot!=0){ + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=abs(CComplex(xss,yss)-pDoc->meshelem[i].ctr); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + { + PlotFluxDensity(pDC,i,DensityPlot); + } + } + } + } + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + { + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + int pi,po,OnBoundary; + + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshelem.GetSize();i++) + { + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + + OnBoundary=FALSE; + for(j=0;j<3;j++) + if (pDoc->meshelem[i].n[j] == 1) + OnBoundary=TRUE; + + for(j=0;j<3;j++) + { + k=j+1; if (k==3) k=0; + pi=pDoc->meshelem[i].p[j]; + po=pDoc->meshelem[i].p[k]; + + if((po>pi) || (OnBoundary==TRUE)) + { + MyMoveTo(pDC,pDoc->meshnode[pi].xs, + pDoc->meshnode[pi].ys); + MyLineTo(pDC,pDoc->meshnode[po].xs, + pDoc->meshnode[po].ys); + } + } + } + } + pDC->SelectObject( pOldPen ); + } + + // Draw contour lines, if they are enabled. + pOldPen = pDC->SelectObject( &penReal ); + if (ShowAr==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,0); + } + } + + pDC->SelectObject(&penImag); + if (ShowAi==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,1); + } + } + + pDC->SelectObject(&penMask); + if (ShowMask==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,2); + } + } + + pDC->SelectObject( pOldPen ); + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].Hidden==FALSE){ + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else{ +// if (EditAction==2) pOldPen = pDC->SelectObject( &penGreen ); +// else + pOldPen = pDC->SelectObject( &penRed ); + } + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].Hidden==FALSE){ + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else + { +// if (EditAction==2) pOldPen = pDC->SelectObject( &penGreen ); +// else + pOldPen = pDC->SelectObject( &penRed ); + } + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].MaxSideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + if(PtsFlag==TRUE) for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw vectors + if ((VectorPlot>0) && (pDoc->nodelist.GetSize()>0)) + { + CPointVals u; + BOOL drawgrid=TRUE; + BOOL PlotB; + double MaxVal; + int xp,yp; + CComplex vr,va,c0,c1; + int ilo,ihi,jlo,jhi; + + if ((VectorPlot==1) || (VectorPlot==3) || (VectorPlot==5)){ + MaxVal=pDoc->B_High; + PlotB=TRUE; + } + else{ + MaxVal=pDoc->H_High; + PlotB=FALSE; + } + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Vectors too dense to display.",TRUE); + } + else{ + + // VectorPlot = 1 -> B_re; + // VectorPlot = 2 -> H_re; + // VectorPlot = 3 -> B_im; + // VectorPlot = 4 -> H_im; + // VectorPlot = 5 -> B_re & B_im; + // VectorPlot = 6 -> H_re & H_im; + + int MakePlots=(VectorPlot+1)/2; + + for(k=0;kmeshelem.GetSize();k++) + { + rt=abs(CComplex(xss,yss)-pDoc->meshelem[k].ctr); + if( rt < ( sqrt(pDoc->meshelem[k].rsqr) + rss) ) + { + c0=pDoc->meshelem[k].ctr-sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c1=pDoc->meshelem[k].ctr+sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c0/=GridSize; + c1/=GridSize; + ilo=(int) floor(Re(c0)); + ihi=(int) ceil (Re(c1)); + jlo=(int) floor(Im(c0)); + jhi=(int) ceil (Im(c1)); + for(i=ilo;i<=ihi;i++) + { + for(j=jlo;j<=jhi;j++) + { + xd=GridSize*((double) i); + yd=GridSize*((double) j); + if(pDoc->InTriangleTest(xd,yd,k)) + { + pDoc->GetPointValues(xd,yd,k,u); + + // Plot real vector + if (MakePlots & 1) + { + pOldPen = pDC->SelectObject( &penRealVector ); + if (PlotB) vr=Re(u.B1)+I*Re(u.B2); + else vr=Re(u.H1)+I*Re(u.H2); + vr*=(GridSize*VectorScaleFactor/MaxVal); + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, RealVectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + pDC->SelectObject( pOldPen ); + } + + // Plot imag vector + if (MakePlots & 2) + { + pOldPen = pDC->SelectObject( &penImagVector ); + if (PlotB) vr=Im(u.B1)+I*Im(u.B2); + else vr=Im(u.H1)+I*Im(u.H2); + vr*=(GridSize*VectorScaleFactor/MaxVal); + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, ImagVectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + pDC->SelectObject( pOldPen ); + } + + } + } + } + } // end of if(rt<... + } + } + } + + + if(EditAction==1) DrawUserContour(TRUE); + + // draw block labels/names + if(ShowNames){ + pDC->SetTextColor(NameColor); + pOldPen = pDC->SelectObject( &penGreen ); + CString lbl; + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // draw arrows indicating magnetization direction + // if the block is a permanent magnet + if ((pDoc->blockproplist[pDoc->blocklist[i].BlockType].H_c!=0) && + (pDoc->blocklist[i].MagDirFctn.GetLength()==0)) + { + int vx,vy; + CComplex ar; + ar=(cos(pDoc->blocklist[i].MagDir*PI/180))+ + I*(sin(pDoc->blocklist[i].MagDir*PI/180)); + vx=xs - ((int) (10.*ar.re)); + vy=ys + ((int) (10.*ar.im)); + MyMoveTo(pDC,vx,vy); + vx=xs + ((int) (10.*ar.re)); + vy=ys - ((int) (10.*ar.im)); + MyLineTo(pDC,vx,vy); + ar/=(1.+I)/sqrt(2.); + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + MyMoveTo(pDC,vx,vy); + ar*=I; + MyLineTo(pDC,vx-((int) (6.*ar.re)),vy+((int) (6*ar.im))); + } + + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + lbl=pDoc->blockproplist[pDoc->blocklist[i].BlockType].BlockName; + pDC->TextOut(xs+5,ys,lbl); + + pDC->SetTextAlign(TA_TOP); + + if (pDoc->blocklist[i].InCircuit>=0) + { + k=pDoc->blocklist[i].InCircuit; + if(pDoc->circproplist[k].CircType==1) + lbl.Format("[%s:%i]",pDoc->circproplist[k].CircName, + pDoc->blocklist[i].Turns); + else lbl="["+pDoc->circproplist[k].CircName+"]"; + pDC->TextOut(xs+5,ys,lbl); + } + + } + pDC->SelectObject( pOldPen ); + } + + // Draw Legend if it is enabled; + if((LegendFlag==TRUE) && (DensityPlot!=0)) + { + CBrush *pOldBrush; + char cc[80]; + double dta; + CBrush BackBrush; + + pOldPen = pDC->SelectObject( &penText ); + pDC->SetTextColor(TextColor); + pDC->SetTextAlign(TA_TOP); + pDC->SetTextAlign(TA_LEFT); + pDC->SetBkMode(TRANSPARENT); + + BackBrush.CreateSolidBrush(BackColor); + pOldBrush = pDC->SelectObject( &BackBrush ); + pDC->Rectangle(r.right-212-6,r.top+6,r.right-6,r.top+24+21*16 ); + pDC->SelectObject(pOldBrush); + + if (pDoc->Frequency!=0){ + if (DensityPlot==1) sprintf(cc,"Density Plot: |B|, Tesla"); + if (DensityPlot==2) sprintf(cc,"Density Plot: |B_re|, Tesla"); + if (DensityPlot==3) sprintf(cc,"Density Plot: |B_im|, Tesla"); + if (DensityPlot==4) sprintf(cc,"Density Plot: |H|, A/m"); + if (DensityPlot==5) sprintf(cc,"Density Plot: |H_re|, A/m"); + if (DensityPlot==6) sprintf(cc,"Density Plot: |H_im|, A/m"); + if (DensityPlot==7) sprintf(cc,"Density Plot: |J|, MA/m^2"); + if (DensityPlot==8) sprintf(cc,"Density Plot: |J_re|, MA/m^2"); + if (DensityPlot==9) sprintf(cc,"Density Plot: |J_im|, MA/m^2"); + } + else{ + if (DensityPlot==1) sprintf(cc,"Density Plot: |B|, Tesla"); + if (DensityPlot==2) sprintf(cc,"Density Plot: |H|, A/m"); + if (DensityPlot==3) sprintf(cc,"Density Plot: |J|, MA/m^2"); + } + + pDC->TextOut(r.right-212,r.top+16*20+16,cc,(int) strlen(cc)); + + dta=(pDoc->PlotBounds[DensityPlot-1][1] - pDoc->PlotBounds[DensityPlot-1][0])/20.; + + for(i=0;i<20;i++){ + + { + CBrush FillBrush; + + if (GreyContours==FALSE) FillBrush.CreateSolidBrush(mymap[i]); + else FillBrush.CreateSolidBrush(greymap[i]); + pOldBrush = pDC->SelectObject( &FillBrush ); + pDC->Rectangle(r.right-212,r.top+16*i+12,r.right-187,r.top+12+16*(i+1) ); + pDC->SelectObject(pOldBrush); + } + + { + double B_lb=pDoc->PlotBounds[DensityPlot-1][0]; + if(i==0) + sprintf(cc,"%.3e : >%.3e",((double) (19-i))*dta + B_lb, + ((double) (20-i))*dta + B_lb); + else if(i==19) + sprintf(cc,"<%.3e : %.3e",((double) (19-i))*dta + B_lb, + ((double) (20-i))*dta + B_lb); + else + sprintf(cc,"%.3e : %.3e",((double) (19-i))*dta + B_lb, + ((double) (20-i))*dta + B_lb); + pDC->TextOut(r.right-182,r.top+16*i+12,cc,(int) strlen(cc)); + } + } + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewView printing + +BOOL CFemmviewView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CFemmviewView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CFemmviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewView diagnostics + +#ifdef _DEBUG +void CFemmviewView::AssertValid() const +{ + CView::AssertValid(); +} + +void CFemmviewView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CFemmviewDoc* CFemmviewView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFemmviewDoc))); + return (CFemmviewDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmviewView message handlers + +void CFemmviewView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CFemmviewDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ((SnapFlag==TRUE) && (EditAction!=2) && (ZoomWndFlag==0)){ + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + // draw box for window zoom; + if(ZoomWndFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + } + + + // update mouse position; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CFemmviewView::OnZoomIn() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + RedrawView(); +} + +void CFemmviewView::OnZoomOut() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + RedrawView(); +} + +void CFemmviewView::OnZoomNatural() +{ + CFemmviewDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else RedrawView(); +} + + +void CFemmviewView::OnKbdZoom() +{ + CFemmviewDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + RedrawView(); +} + +void CFemmviewView::OnSetGrid() +{ + CGridMod pDlg; + CFemmviewDoc *pDoc=GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + RedrawView(); + } +} + +void CFemmviewView::OnSnapGrid() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CFemmviewView::OnShowMesh() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + } + + RedrawView(); +} + + +void CFemmviewView::OnCplot() +{ + CFemmviewDoc *pDoc=GetDocument(); + + if(pDoc->Frequency!=0){ + CCPlotDlg dlg; + dlg.m_showar=ShowAr; + dlg.m_showai=ShowAi; + dlg.m_showmask=ShowMask; + dlg.m_numcontours=NumContours; + dlg.m_alow=pDoc->A_Low; + dlg.m_ahigh=pDoc->A_High; + dlg.Alb=pDoc->A_lb; + dlg.Aub=pDoc->A_ub; + if(dlg.DoModal()==IDOK){ + ShowAr=dlg.m_showar; + ShowAi=dlg.m_showai; + ShowMask=dlg.m_showmask; + pDoc->A_Low=dlg.m_alow; + pDoc->A_High=dlg.m_ahigh; + NumContours=dlg.m_numcontours; + RedrawView(); + } + } + else{ + CCplotDlg2 dlg; + dlg.m_showa=ShowAr; + dlg.m_showmask=ShowMask; + dlg.m_numcontours=NumContours; + dlg.m_alow=pDoc->A_Low; + dlg.m_ahigh=pDoc->A_High; + dlg.Alb=pDoc->A_lb; + dlg.Aub=pDoc->A_ub; + if(dlg.DoModal()==IDOK){ + ShowAr=dlg.m_showa; + ShowMask=dlg.m_showmask; + ShowAi=FALSE; + pDoc->A_Low=dlg.m_alow; + pDoc->A_High=dlg.m_ahigh; + NumContours=dlg.m_numcontours; + RedrawView(); + } + } +} + +void CFemmviewView::OnDplot() +{ + CFemmviewDoc *pDoc=GetDocument(); + int i,k; + + cvCDPlotDlg2 dlg; + + if(!DensityPlot) dlg.m_showit=FALSE; + else dlg.m_showit=TRUE; + dlg.m_showlegend=LegendFlag; + dlg.m_gscale=GreyContours; + dlg.DensityPlot=DensityPlot; + + if(pDoc->Frequency==0) + { + dlg.listtype=1; + for(i=0;i<3;i++) + for(k=0;k<2;k++) + { + dlg.PlotBounds[i][k]=pDoc->PlotBounds[i][k]; + dlg.d_PlotBounds[i][k]=pDoc->d_PlotBounds[i][k]; + } + } + else + { + dlg.listtype=2; + for(i=0;i<9;i++) + for(k=0;k<2;k++) + { + dlg.PlotBounds[i][k]=pDoc->PlotBounds[i][k]; + dlg.d_PlotBounds[i][k]=pDoc->d_PlotBounds[i][k]; + } + } + + if(dlg.DoModal()==IDOK){ + if(dlg.m_showit) DensityPlot=dlg.DensityPlot; + else DensityPlot=0; + LegendFlag=dlg.m_showlegend; + GreyContours=dlg.m_gscale; + for(i=0;i<9;i++) + for(k=0;k<2;k++) + pDoc->PlotBounds[i][k]=dlg.PlotBounds[i][k]; + RedrawView(); + } +} + +void CFemmviewView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame"); + else{ + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + Dspl=&MFrm->m_dlgBar; + } +} + +void CFemmviewView::DisplayPointProperties(double px, double py) +{ + CFemmviewDoc* pDoc = GetDocument(); + CPointVals u; + CComplex Jtot; + if (pDoc->nodelist.GetSize()==0) return; + if(pDoc->GetPointValues(px, py, u)==TRUE) + { + char c[80]; + CString s,outbox; + if (pDoc->ProblemType>=0) + { + if(pDoc->Frequency==0) + { + if (pDoc->ProblemType==0) + { + s.Format("Point: x=%g, y=%g\r\n",px,py); + outbox=s; + s.Format("A = %g Wb/m\r\n",u.A.re); + outbox+=s; + s.Format("|B| = %g T\r\n",sqrt(u.B1.re*u.B1.re + u.B2.re*u.B2.re)); + outbox+=s; + s.Format("Bx = %g T\r\n",u.B1.re); + outbox+=s; + s.Format("By = %g T\r\n",u.B2.re); + outbox+=s; + s.Format("|H| = %g A/m\r\n",sqrt(u.H1.re*u.H1.re + u.H2.re*u.H2.re)); + outbox+=s; + s.Format("Hx = %g A/m\r\n",u.H1.re); + outbox+=s; + s.Format("Hy = %g A/m\r\n",u.H2.re); + outbox+=s; + + if(u.Hc==0){ + s.Format("mu_x= %g (rel)\r\n",u.mu1.re); + outbox+=s; + s.Format("mu_y = %g (rel)\r\n",u.mu2.re); + outbox+=s; + if (Re(u.mu12)!=0) + { + s.Format("mu_xy= %g (rel)\r\n", u.mu12.re); + outbox += s; + } + } + else{ + double bh=abs(u.B1*u.H1+u.B2*u.H2); + s.Format("B.H = %g J/m^3 (%g MGOe)\r\n",bh,muo*bh*100.); + outbox+=s; + } + s.Format("E = %g J/m^3\r\n",u.E); + outbox+=s; + s.Format("J = %g MA/m^2\r\n",u.Js.re); + outbox+=s; + if (u.ff>0){ + s.Format("Winding Fill = %.2f%%\r\n",u.ff*100.); + outbox+=s; + } + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + else{ + s.Format("Point: r=%g, z=%g\r\n",px,py); + outbox=s; + s.Format("Flux= %g Wb\r\n",u.A.re); + outbox+=s; + s.Format("|B| = %g T\r\n",sqrt(u.B1.re*u.B1.re + u.B2.re*u.B2.re)); + outbox+=s; + s.Format("Br = %g T\r\n",u.B1.re); + outbox+=s; + s.Format("Bz = %g T\r\n",u.B2.re); + outbox+=s; + s.Format("|H| = %g A/m\r\n",sqrt(u.H1.re*u.H1.re + u.H2.re*u.H2.re)); + outbox+=s; + s.Format("Hr = %g A/m\r\n",u.H1.re); + outbox+=s; + s.Format("Hz = %g A/m\r\n",u.H2.re); + outbox+=s; + if(u.Hc==0) + { + s.Format("mu_r= %g (rel)\r\n",u.mu1.re); + outbox+=s; + s.Format("mu_z= %g (rel)\r\n",u.mu2.re); + outbox+=s; + if (Re(u.mu12) != 0) + { + s.Format("mu_rz= %g (rel)\r\n", u.mu12.re); + outbox += s; + } + } + else{ + double bh=abs(u.B1*u.H1+u.B2*u.H2); + s.Format("B.H = %g J/m^3 (%g MGOe)\r\n",bh,muo*bh*100.); + outbox+=s; + } + s.Format("E = %g J/m^3\r\n",u.E); + outbox+=s; + s.Format("J = %g MA/m^2\r\n",u.Js.re); + outbox+=s; + if (u.ff>0){ + s.Format("Winding Fill = %.2f%%\r\n",u.ff*100.); + outbox+=s; + } + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + } + // Harmonic problems... + else{ + if(pDoc->ProblemType==0){ + s.Format("Point: x=%g, y=%g",px,py); + outbox=s; + s.Format("A = %s Wb/m",u.A.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|B| = %g T",sqrt(u.B1.re*u.B1.re + u.B2.re*u.B2.re + +u.B1.im*u.B1.im + u.B2.im*u.B2.im)); + outbox+="\r\n"+s; + s.Format("Bx = %s T",u.B1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("By = %s T",u.B2.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|H| = %g A/m",sqrt(u.H1.re*u.H1.re + u.H2.re*u.H2.re + +u.H1.im*u.H1.im + u.H2.im*u.H2.im)); + outbox+="\r\n"+s; + s.Format("Hx = %s A/m",u.H1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Hy = %s A/m",u.H2.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("mu_x = %s (rel)",u.mu1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("mu_y = %s (rel)",u.mu2.ToStringAlt(c)); + outbox+="\r\n"+s; + if ((Re(u.mu12)!=0) | (Re(u.mu12)!=0)) + { + s.Format("mu_xy= %s (rel)",u.mu12.ToStringAlt(c)); + outbox+="\r\n"+s; + } + Jtot=u.Je + u.Js; + s.Format("J= %s MA/m^2",Jtot.ToStringAlt(c)); + outbox+="\r\n"+s; + if (u.ff>0){ + s.Format("\r\nWinding Fill = %.2f%%",u.ff*100.); + outbox+=s; + } + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + if(pDoc->ProblemType==1){ + s.Format("Point: r=%g, z=%g",px,py); + outbox=s; + s.Format("Flux= %s Wb",u.A.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|B| = %g T",sqrt(u.B1.re*u.B1.re + u.B2.re*u.B2.re + +u.B1.im*u.B1.im + u.B2.im*u.B2.im)); + outbox+="\r\n"+s; + s.Format("Br = %s T",u.B1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Bz = %s T",u.B2.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|H| = %g A/m",sqrt(u.H1.re*u.H1.re + u.H2.re*u.H2.re + +u.H1.im*u.H1.im + u.H2.im*u.H2.im)); + outbox+="\r\n"+s; + s.Format("Hr = %s A/m",u.H1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Hz = %s A/m",u.H2.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("mu_r = %s (rel)",u.mu1.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("mu_z = %s (rel)",u.mu2.ToStringAlt(c)); + outbox+="\r\n"+s; + if ((Re(u.mu12)!=0) | (Re(u.mu12)!=0)) + { + s.Format("mu_rz= %s (rel)",u.mu12.ToStringAlt(c)); + outbox+="\r\n"+s; + } + Jtot=u.Je + u.Js; + s.Format("J= %s MA/m^2",Jtot.ToStringAlt(c)); + outbox+="\r\n"+s; + if (u.ff>0){ + s.Format("\r\nWinding Fill = %.2f%%",u.ff*100.); + outbox+=s; + } + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + } + } +} +} + +void CFemmviewView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonDown(nFlags, point); + return; + } + + int i,j,k,m; + + if (ZoomWndFlag==1) + { + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0) DisplayPointProperties(mx,my); + + if (EditAction==1){ + CFemmviewDoc *pDoc=GetDocument(); + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + DrawUserContour(FALSE); + return; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(y); + DrawUserContour(FALSE); + } + } + } + } + + if (EditAction==2){ + CFemmviewDoc *pDoc=GetDocument(); + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + pDoc->blocklist[pDoc->meshelem[k].lbl].ToggleSelect(); + DrawSelected=pDoc->meshelem[k].lbl; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } +/* else{ // if not in an element, select nearest arc or line + CFemmviewDoc *pDoc=GetDocument(); + int clseg,claseg; + int myType=0; + double dseg,daseg; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0){ + dseg=pDoc->ShortestDistance(mx,my,clseg); + myType+=1; + } + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + { + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + myType+=2; + } + else daseg=-1.; + + switch(myType) + { + case 1: pDoc->linelist[clseg].ToggleSelect(); break; + case 2: pDoc->arclist[claseg].ToggleSelect(); break; + case 3: + if (dseglinelist[clseg].ToggleSelect(); + else pDoc->arclist[claseg].ToggleSelect(); + break; + default: return; + } + + CDC *pDC=GetDC(); + OnDraw(pDC); + ReleaseDC(pDC); + + } */ + } + + } + + CView::OnLButtonDown(nFlags, point); +} + +void CFemmviewView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag>0){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + RedrawView(); + return; + } + RECT r; + double z,cmag,m[2]; + if (mxcontour.GetSize(); + if(i>0){ + if (z!=pDoc->contour[i-1]) + pDoc->contour.Add(z); + } + else pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CFemmviewView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CFemmviewView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CBitmap *oldbitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + oldbitmap=tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); + ReleaseDC(pDC); +} + +void CFemmviewView::OnReload() +{ + CFemmviewDoc *pDoc=GetDocument(); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->OnReload(); + if (bLinehook==FALSE) EndWaitCursor(); + if (d_ResetOnReload==FALSE) pDoc->FirstDraw=FALSE; + RedrawView(); + OnViewInfo(); +} + +void CFemmviewView::OnMenuArea() +{ + CFemmviewDoc *pDoc=GetDocument(); + if(EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, TRUE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CFemmviewView::OnMenushowpts() +{ + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(PtsFlag==FALSE){ + PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + } + else{ + PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + } + RedrawView(); +} + +void CFemmviewView::OnMenuContour() +{ + CFemmviewDoc *pDoc=GetDocument(); + + if(EditAction==2){ + int i; + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (pDoc->blocklist[i].IsSelected==TRUE){ + pDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + for(i=0;ilinelist.GetSize();i++){ + if (pDoc->linelist[i].IsSelected==TRUE){ + pDoc->linelist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + for(i=0;iarclist.GetSize();i++){ + if (pDoc->arclist[i].IsSelected==TRUE){ + pDoc->arclist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) RedrawView(); + } + + EditAction=1; + + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, TRUE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CFemmviewView::OnMenuPoint() +{ + CFemmviewDoc *pDoc=GetDocument(); + + if (EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + if (EditAction==2){ + int i; + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (pDoc->blocklist[i].IsSelected==TRUE){ + pDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + for(i=0;ilinelist.GetSize();i++){ + if (pDoc->linelist[i].IsSelected==TRUE){ + pDoc->linelist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + for(i=0;iarclist.GetSize();i++){ + if (pDoc->arclist[i].IsSelected==TRUE){ + pDoc->arclist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) RedrawView(); + } + + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, TRUE); +} + +void CFemmviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CFemmviewDoc *pDoc=GetDocument(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if ((nChar==VK_TAB) && (EditAction!=2)) EnterPoint(); + + if ((nChar==VK_DELETE) && (EditAction==1)){ + int k; + k=(int) pDoc->contour.GetSize(); + + if(k>1){ + EraseUserContour(FALSE); + pDoc->contour.RemoveAt(k-1); + DrawUserContour(TRUE); + } + else if(k!=0){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAt(0); + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==1)){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + + if ((nChar==VK_SHIFT) && (EditAction==1)){ + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==2)){ + BOOL flg=FALSE; + int i; + + for(i=0;iblocklist.GetSize();i++) + { + if(pDoc->blocklist[i].IsSelected==TRUE) + { + flg=TRUE; + pDoc->blocklist[i].IsSelected=FALSE; + } + } + + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==TRUE) + { + flg=TRUE; + pDoc->linelist[i].IsSelected=FALSE; + } + } + + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==TRUE) + { + flg=TRUE; + pDoc->arclist[i].IsSelected=FALSE; + } + } + if (flg==TRUE) RedrawView(); + + } + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + + +void CFemmviewView::EnterPoint() +{ + CEnterPt pDlg; + double x,y,t; + CFemmviewDoc* pDoc = GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + if (EditAction==0) DisplayPointProperties(x,y); + if (EditAction==1){ + CComplex z; + z.Set(x,y); + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + } +} + +void CFemmviewView::SpecialLine(CDC *pDC, int X0, int Y0, int X1, int Y1, int flag) +{ + double l; + int i,j,k,p,x,y,z; + int hi,lo,zj; + BOOL InLine,DrawIt; + COLORREF c; + COLORREF Red; + RECT r; + + GetClientRect(&r); + Red=SelColor; + + int x0,y0,x1,y1,xb,yb; + + x0=X0; y0=Y0; + x1=X1; y1=Y1; + xb=r.right; + yb=r.bottom; + DrawIt=TRUE; + + // test to see if any of the endpoints are offscreen. + // if they are, crop them to the screen size + if ((x0<0) || (x0>xb) || (x1<0) || (x1>xb) || + (y0<0) || (y0>yb) || (y1<0) || (y1>yb)) + { + DrawIt=FALSE; + double z,dx0,dx1,dy0,dy1,dxb,dyb; + dx0=(double) x0; + dy0=(double) y0; + dx1=(double) x1; + dy1=(double) y1; + dxb=(double) xb; + dyb=(double) yb; + + + if ((x1-x0)!=0) + { + // test left side; + z=(-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0<0) + { + dx0=0; + x0=0; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=0; + x1=0; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + // test right side; + z=(dxb-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0>xb) + { + dx0=dxb; + x0=xb; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=dxb; + x1=xb; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + } + + if ((y1-y0)!=0) + { + // test top side; + z=(-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0<0) + { + dy0=0; + y0=0; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=0; + y1=0; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + + // test bottom side; + z=(dyb-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0>dyb) + { + dy0=dyb; + y0=yb; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=dyb; + y1=yb; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + } + } + + if(!DrawIt) return; + + l=(double)((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + l=sqrt(l); + k=(int) l; + for(i=0;i<=k;i++) + { + if(k!=0){ + x=x0+((x1-x0)*i)/k; + y=y0+((y1-y0)*i)/k; + } + else{ + x=x0; + y=y0; + } + + z=x+y*r.right; + + // check if this point is already in the line + // in the case that a red line is supposed to be drawn; + + if(flag==FALSE) + { + // bisection search to see if the pixel under + // consideration is already in LinePix + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj) InLine=TRUE; + } + zj=LinePix[hi].z; + if(z>=zj){ + hi+=1; + lo=hi; + if(z==zj) InLine=TRUE; + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + break; + } + else if(zjGetPixel(x,y); + if (hi==(int) LinePix.GetSize()) LinePix.Add(NewPixel); + else LinePix.InsertAt(hi,NewPixel); + } + } + + // if line is to be erased, get entry out of the pixel list + if(flag!=FALSE){ + // bisection search to find the pixel + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj){ + InLine=TRUE; + p=0; + } + } + zj=LinePix[hi].z; + if(z>=zj){ + lo=hi; + if(z==zj){ + InLine=TRUE; + p=hi; + } + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + p=j; + break; + } + else if(zjPtVisible(x,y)!=FALSE) + { + if(flag==FALSE) pDC->SetPixel(x,y,Red); + else if(InLine==TRUE) pDC->SetPixel(x,y,c); + } + } + +} + +void CFemmviewView::OnMenuPlot() +{ + + CFemmviewDoc *pDoc=GetDocument(); + int PlotType,npoints,FileFormat,myAGE; + BOOL ToFile; + CXYPlot xyplot; + + if (pDoc->contour.GetSize()==0) + { + // if no AGE, throw error message and return + if (pDoc->agelist.GetSize()==0) + { + MsgBox("Cannot create a plot;\nNo contour has been defined"); + return; + } + + // otherwise, invoke functionality to plot air gap values + CGapPlotDlg dlg; + dlg.pagelist=&pDoc->agelist; + dlg.m_npoints=d_PlotPoints; + if (dlg.DoModal()==IDOK) + { + PlotType=dlg.XYPlotType; + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + myAGE=dlg.m_age; + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->GetGapValues(xyplot,PlotType,npoints,myAGE); + if (bLinehook==FALSE) EndWaitCursor(); + } + else return; + } + else{ + // do normal plot along a defined contour + CXYPlotDlg dlg; + if (pDoc->Frequency==0) dlg.ListType=0; + else dlg.ListType=1; + dlg.m_npoints=d_PlotPoints; + if (dlg.DoModal()==IDOK){ + PlotType=dlg.XYPlotType; + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->GetLineValues(xyplot,PlotType,npoints); + if (bLinehook==FALSE) EndWaitCursor(); + } + else return; + } + + if(ToFile==FALSE){ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else xyplot.ToDisk(FileFormat); +} + +void CFemmviewView::OnMenuIntegrate() +{ + CFemmviewDoc *pDoc=GetDocument(); + int inttype; + int bBlocksAreSelected=FALSE; + + if ((EditAction==0) && (pDoc->agelist.GetSize()==0)) + { + MsgBox("Cannot integrate;\nNo contour or area\nhas been defined."); + return; + } + + if ((EditAction==1) && (pDoc->contour.GetSize()==0) && (pDoc->agelist.GetSize()==0)) + { + MsgBox("Cannot integrate;\nNo contour has been defined"); + return; + } + + if (EditAction==2) + { + int i; + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].IsSelected==TRUE) bBlocksAreSelected=TRUE; + if((bBlocksAreSelected==FALSE) && (pDoc->agelist.GetSize()==0)){ + MsgBox("Cannot integrate;\nNo area has been selected"); + return; + } + } + + if ((EditAction==1) && (pDoc->contour.GetSize()>0)) + { + CLIntDlg dlg; + int inttype; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.linttype; + char s[512]; char c[80]; char d[80]; + CComplex *z; + switch(inttype) + { + case 0: + z=(CComplex *)calloc(2,sizeof(CComplex)); + pDoc->LineIntegral(inttype,z); + if(pDoc->Frequency==0) + sprintf(s,"Normal flux = %g Webers\nAverage B.n = %g Tesla",z[0].re,z[1].re); + else + sprintf(s,"Normal flux = %s Webers\nAverage B.n = %s Tesla",z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + MyMessageBox(s); + free(z); + break; + + case 1: + z=(CComplex *)calloc(2,sizeof(CComplex)); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if(pDoc->Frequency==0) + sprintf(s,"MMF drop along contour = %g Amp-turns\nAverage H.t = %g Amp/Meter",z[0].re,z[1].re); + else + sprintf(s,"MMF drop along contour = %s Amp-turns\nAverage H.t = %s Amp/Meter",z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + + MyMessageBox(s); + free(z); + break; + case 2: + z=(CComplex *)calloc(1,sizeof(CComplex)); + pDoc->LineIntegral(inttype,z); + sprintf(s,"Contour length = %g meters\nSurface Area = %g meter^2",z[0].re,z[0].im); + MyMessageBox(s); + free(z); + break; + case 3: + z=(CComplex *)calloc(4,sizeof(CComplex)); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if(pDoc->Frequency==0) + { + if (pDoc->ProblemType==0) + sprintf(s,"Force in x-direction = %g N\nForce in y-direction = %g N\n",z[0].re,z[1].re); + else + sprintf(s,"Force in z-direction = %g N",z[1].re); + MyMessageBox(s); + } + else{ + CString ss; + if (pDoc->ProblemType==0){ + sprintf(s,"DC Force:\n x-direction = %g N\n y-direction = %g N\n",z[2].re,z[3].re); + ss=s; + sprintf(s,"\n%f Hz Force:\n x-direction = %s N\n y-direction = %s N", + pDoc->Frequency*2.,z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + ss+=s; + } + else{ + sprintf(s,"DC Force:\n z-direction = %g N",z[3].re); + ss=s; + sprintf(s,"\n%g Hz Force:\n z-direction = %s N", + pDoc->Frequency*2.,z[1].ToStringAlt(c)); + ss+=s; + } + + MyMessageBox(ss); + // AfxMessageBox(ss,MB_ICONINFORMATION); + } + free(z); + break; + + case 4: + z=(CComplex *)calloc(2,sizeof(CComplex)); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if(pDoc->Frequency==0) + { + if (pDoc->ProblemType==0) + sprintf(s,"Torque about (0,0) = %g N*m",z[0].re); + else + sprintf(s,"No net torque in axisymmetric case."); + + MyMessageBox(s); + // AfxMessageBox(s,MB_ICONINFORMATION); + } + else{ + CString ss; + if (pDoc->ProblemType==0){ + sprintf(s,"Torque about (0,0):\nDC Torque = %g N*m\n",z[1].re); + ss=s; + sprintf(s,"%g Hz Torque = %s N*m", + pDoc->Frequency*2.,z[0].ToStringAlt(c)); + ss+=s; + } + else{ + sprintf(s,"No net torque in axisymmetric case"); + ss=s; + } + + MyMessageBox(ss); + //AfxMessageBox(ss,MB_ICONINFORMATION); + } + + free(z); + break; + + case 5: + z=(CComplex *)calloc(2,sizeof(CComplex)); + pDoc->LineIntegral(inttype,z); + if(pDoc->Frequency==0) + sprintf(s,"Result = %g Webers^2\nAverage (B.n)^2 = %g Tesla^2",z[0].re,z[1].re); + else + sprintf(s,"Result = %s Webers^2\nAverage (B.n)^2 = %s Tesla^2",z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + + MyMessageBox(s); + free(z); + break; + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + } + return; + } + + if((EditAction==2) && (bBlocksAreSelected)){ + CBlockInt dlg; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.binttype; + CComplex z,z1,z2,z3,z4; + char s[512]; char c[80]; char d[80]; + + switch(inttype) + { + case 0: + z=pDoc->BlockIntegral(inttype); + if(pDoc->Frequency==0) + sprintf(s,"%g Henry Amp^2",z.re); + else + sprintf(s,"%s Henry Amp^2",z.ToStringAlt(c)); + break; + case 1: + z=pDoc->BlockIntegral(inttype); + z1=pDoc->BlockIntegral(5); + if(pDoc->Frequency==0) + sprintf(s,"Integral of A over selection:\n%g Henry Amp meter^2\nIntegral of A / selected area:\n%g Henry Amp",z.re,z.re/z1.re); + else + sprintf(s,"Integral of A over selection:\n%s Henry Amp meter^2\nIntegral of A / selected area:\n%s Henry Amp",z.ToStringAlt(c), + (z/z1.re).ToStringAlt(d)); + break; + case 2: + z=pDoc->BlockIntegral(inttype); + sprintf(s,"%g Joules",z.re); + break; + + case 3: + z=pDoc->BlockIntegral(inttype); + sprintf(s,"%g Watts",z.re); + break; + + case 4: + z=pDoc->BlockIntegral(inttype); + sprintf(s,"%g Watts",z.re); + break; + + case 5: + z=pDoc->BlockIntegral(inttype); + sprintf(s,"%g meter^2",z.re); + break; + + case 6: + z=pDoc->BlockIntegral(inttype); + sprintf(s,"%g Watts",z.re); + break; + + case 7: + z=pDoc->BlockIntegral(inttype); + if(pDoc->Frequency==0) + sprintf(s,"%g Amps",z.re); + else + sprintf(s,"%s Amps",z.ToStringAlt(c)); + break; + + case 8: + z1=pDoc->BlockIntegral(8); + z2=pDoc->BlockIntegral(9); + if((pDoc->ProblemType==0) && (pDoc->Frequency==0)) + sprintf(s,"x-component: %g Tesla meter^3\ny-component: %g Tesla meter^3",z1.re,z2.re); + if((pDoc->ProblemType==0) && (pDoc->Frequency!=0)) + sprintf(s,"x-component: %s Tesla meter^3\ny-component: %s Tesla meter^3",z1.ToStringAlt(c),z2.ToStringAlt(d)); + if((pDoc->ProblemType==1) && (pDoc->Frequency==0)) + sprintf(s,"r-component: %g Tesla meter^3\nz-component: %g Tesla meter^3",z1.re,z2.re); + if((pDoc->ProblemType==1) && (pDoc->Frequency!=0)) + sprintf(s,"r-component: %s Tesla meter^3\nz-component: %s Tesla meter^3",z1.ToStringAlt(c),z2.ToStringAlt(d)); + break; + case 9: + z=pDoc->BlockIntegral(10); + sprintf(s,"%g meter^3",z.re); + break; + case 10: // Lorentz Force + + // just report 1X results for incremental permeability AC solutions + if (pDoc->bIncremental==1) + { + z3=pDoc->BlockIntegral(28); + z4=pDoc->BlockIntegral(29); + if(pDoc->ProblemType==0) + { + if (pDoc->Frequency==0) + sprintf(s,"Interaction force:\nx-component: %s N\ny-component: %s N",z3.ToStringAlt(c),z4.ToStringAlt(d)); + else + sprintf(s,"1x Frequency force:\nx-component: %s N\ny-component: %s N",z3.ToStringAlt(c),z4.ToStringAlt(d)); + } + else + { + sprintf(s,"1x Frequency force:\nr-component: 0. N\nz-component: %s N",z4.ToStringAlt(d)); + } + break; + } + + if(pDoc->bIncremental==2) + { + z1=pDoc->BlockIntegral(11); + z2=pDoc->BlockIntegral(12); + z3=pDoc->BlockIntegral(28); + z4=pDoc->BlockIntegral(29); + if(pDoc->ProblemType==0) + sprintf(s,"Self force:\nx-component: %g N\ny-component: %g N\nInteraction force:\nx-component: %s N\ny-component: %s N",z1.re,z2.re,z3.ToStringAlt(c),z4.ToStringAlt(d)); + else + sprintf(s,"Self force:\nr-component: 0. N\nz-component: %g NInteraction Frequency force:\nr-component: 0. N\nz-component: %s N",z2.re,z4.ToStringAlt(d)); + break; + } + + // otherwise, report DC force (and 2X force as applicable) + z1=pDoc->BlockIntegral(11); + z2=pDoc->BlockIntegral(12); + if(pDoc->Frequency!=0){ + z3=pDoc->BlockIntegral(13); + z4=pDoc->BlockIntegral(14); + } + if((pDoc->ProblemType==0) && (pDoc->Frequency==0)) + sprintf(s,"x-component: %g N\ny-component: %g N",z1.re,z2.re); + if((pDoc->ProblemType==1) && (pDoc->Frequency==0)) + sprintf(s,"r-component: %g N\nz-component: %g N",0.,z2.re); + if((pDoc->ProblemType==0) && (pDoc->Frequency!=0)) + sprintf(s,"Steady-state force:\nx-component: %g N\ny-component: %g N\n2x Frequency force:\nx-component: %s N\ny-component: %s N", + z1.re,z2.re,z3.ToStringAlt(c),z4.ToStringAlt(d)); + if((pDoc->ProblemType==1) && (pDoc->Frequency!=0)) + sprintf(s,"Steady-state force:\nr-component: 0. N\nz-component: %g N\n2x Frequency force:\nr-component: 0. N\nz-component: %s N", + z2.re,z4.ToStringAlt(d)); + break; + + case 11: // Lorentz Torque + + if(pDoc->ProblemType==1) + { + sprintf(s,"No Lorentz torque possible in axisymmetric case"); + break; + } + + // just report 1X results for incremental permeability AC solutions + if (pDoc->bIncremental==1) + { + z4=pDoc->BlockIntegral(30); + if (pDoc->Frequency==0) + sprintf(s,"Interaction torque about (0,0): %s N*m",z4.ToStringAlt(d)); + else + sprintf(s,"1x Freq torque about (0,0): %s N*m",z4.ToStringAlt(d)); + break; + } + + // report self- and interaction-components for frozen permeability DC solutions + if (pDoc->bIncremental==2) + { + z1=pDoc->BlockIntegral(15); + z4=pDoc->BlockIntegral(30); + sprintf(s,"Self torque about (0,0): %g\nInteraction torque about (0,0): %s N*m",z1.re,z4.ToStringAlt(d)); + break; + } + // otherwise, report DC torque (and 2X torque as applicable) + z1=pDoc->BlockIntegral(15); + z2=pDoc->BlockIntegral(16); + if((pDoc->ProblemType==0) && (pDoc->Frequency==0)) + sprintf(s,"Torque about (0,0): %g N*m",z1.re); + if((pDoc->ProblemType==0) && (pDoc->Frequency!=0)) + sprintf(s,"Torque about (0,0):\nSteady State: %g N*m\n2x Frequency: %s", + z1.re,z2.ToStringAlt(d)); + + if(pDoc->ProblemType==1) + sprintf(s,"No Lorentz torque possible in axisymmetric case"); + break; + case 12: + z=pDoc->BlockIntegral(17); + sprintf(s,"%g Joules",z.re); + break; + + // Henrotte Force + case 13: + + // just report 1X force as the force if this is an incremental permeability AC problem + if (pDoc->bIncremental==1) + { + z3=pDoc->BlockIntegral(25); + z4=pDoc->BlockIntegral(26); + if(pDoc->ProblemType==0) + { + if (pDoc->Frequency==0) + sprintf(s,"Interaction force:\nx-component: %s N\ny-component: %s N",z3.ToStringAlt(c),z4.ToStringAlt(d)); + else + sprintf(s,"1x Frequency force:\nx-component: %s N\ny-component: %s N",z3.ToStringAlt(c),z4.ToStringAlt(d)); + } + else + { + sprintf(s,"1x Frequency force:\nr-component: 0. N\nz-component: %s N",z4.ToStringAlt(d)); + } + } + else if (pDoc->bIncremental==2) + { + z1=pDoc->BlockIntegral(18); + z2=pDoc->BlockIntegral(19); + z3=pDoc->BlockIntegral(25); + z4=pDoc->BlockIntegral(26); + if(pDoc->ProblemType==0) + sprintf(s,"Self force:\nx-component: %g N\ny-component: %g N\nInteraction force:\nx-component: %s N\ny-component: %s N",z1.re,z2.re,z3.ToStringAlt(c),z4.ToStringAlt(d)); + else + sprintf(s,"Self force:\nr-component: 0. N\nz-component: %g N\nInteraction force:\nr-component: 0. N\nz-component: %s N",z2.re,z4.ToStringAlt(d)); + } + // otherwise. report DC force (and 2X force if applicable) + else{ + z1=pDoc->BlockIntegral(18); + z2=pDoc->BlockIntegral(19); + if(pDoc->Frequency!=0){ + z3=pDoc->BlockIntegral(20); + z4=pDoc->BlockIntegral(21); + } + if((pDoc->ProblemType==0) && (pDoc->Frequency==0)) + sprintf(s,"x-component: %g N\ny-component: %g N",z1.re,z2.re); + if((pDoc->ProblemType==1) && (pDoc->Frequency==0)) + sprintf(s,"r-component: %g N\nz-component: %g N",0.,z2.re); + if((pDoc->ProblemType==0) && (pDoc->Frequency!=0)) + sprintf(s,"Steady-state force:\nx-component: %g N\ny-component: %g N\n2x Frequency force:\nx-component: %s N\ny-component: %s N", + z1.re,z2.re,z3.ToStringAlt(c),z4.ToStringAlt(d)); + if((pDoc->ProblemType==1) && (pDoc->Frequency!=0)) + sprintf(s,"Steady-state force:\nr-component: 0. N\nz-component: %g N\n2x Frequency force:\nr-component: 0. N\nz-component: %s N", + z2.re,z4.ToStringAlt(d)); + } + + if (ShowMask) InvalidateRect(NULL); + break; + + // Henrotte Torque + case 14: + if(pDoc->ProblemType==1) + { + sprintf(s,"No torque possible in axisymmetric case"); + break; + } + + // just report 1X torque as the torque if this is an incremental permeability AC problem + if (pDoc->bIncremental==1) + { + z4=pDoc->BlockIntegral(27); + if(pDoc->Frequency==0) + sprintf(s,"Interaction torque about (0,0): %s N*m",z4.ToStringAlt(d)); + else + sprintf(s,"1x Freq torque about (0,0): %s N*m",z4.ToStringAlt(d)); + } + else if (pDoc->bIncremental==2) + { + z1=pDoc->BlockIntegral(22); + z4=pDoc->BlockIntegral(27); + sprintf(s,"Self torque about (0,0): %g N*m\nInteraction torque about (0,0): %s N*m",z1.re,z4.ToStringAlt(d)); + } + // otherwise report DC torque (and 2X torque if applicable) + else{ + z1=pDoc->BlockIntegral(22); + if(pDoc->Frequency==0) sprintf(s,"Torque about (0,0): %g N*m",z1.re); + else{ + z2=pDoc->BlockIntegral(23); + sprintf(s,"Torque about (0,0):\nSteady State: %g N*m\n2x Frequency: %s N*m",z1.re,z2.ToStringAlt(d)); + } + } + + if (ShowMask) InvalidateRect(NULL); + break; + + case 15: + z1=pDoc->BlockIntegral(24); + if(pDoc->ProblemType) sprintf(s,"Integral of R^2: %g m^5",Re(z1)); + else sprintf(s,"Integral of (x^2 + y^2): %g m^5",Re(z1)); + break; + case 16: + z=Re(pDoc->BlockIntegral(6)/pDoc->BlockIntegral(10)); + sprintf(s,"%g Watts/meter^3",z.re); + break; + default: + sprintf(s,"This space left intentionally blank"); + break; + } + MyMessageBox(s); + } + return; + } + + // Otherwise, prompt for air gap integrals!!! + // Works for any EditAction so long as no other integration region has been defined + // and at least one Air Gap Element exists + GapIntegral dlg; + CString s; + double y1,y2; + CComplex z1,z2; + char c[80],d[80]; + int n; + + dlg.pagelist=&pDoc->agelist; + dlg.Frequency=pDoc->Frequency; + dlg.bIncremental=pDoc->bIncremental; + n = lua_gettop(lua); lua_pop(lua, n); + if(dlg.DoModal()==IDOK){ + switch (dlg.myIntType) + { + case 0: // Torque + if (pDoc->Frequency==0) + { + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,0); + pDoc->lua_gapintegral(lua); + s.Format("Torque = %g Nm",lua_todouble(lua,-1)); + n = lua_gettop(lua); lua_pop(lua, n); + } + else + { + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,0); //DC part of torque + pDoc->lua_gapintegral(lua); + y1=lua_todouble(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,3); //2X part of torque + pDoc->lua_gapintegral(lua); + z1=lua_tonumber(lua,-2); + z2=lua_tonumber(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + s.Format("DC Torque = %g Nm\n2X Torque = %s",y1,z1.ToStringAlt(c)); + } + MyMessageBox(s); + break; + + case 1: //Force + if (pDoc->Frequency==0) + { + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,1); + pDoc->lua_gapintegral(lua); + y1=lua_todouble(lua,-2); + y2=lua_todouble(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + s.Format("Fx = %g N\nFy = %g N",y1,y2); + } + else + { + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,1); //DC part of torque + pDoc->lua_gapintegral(lua); + y1=lua_todouble(lua,-2); + y2=lua_todouble(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,4); //2X part of torque + pDoc->lua_gapintegral(lua); + z1=lua_tonumber(lua,-2); + z2=lua_tonumber(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + s.Format("DC Fx = %g Nm\nDC Fy = %g\n2X Fx = %s\n2X Fy = %s",y1,y2,z1.ToStringAlt(c),z2.ToString(d)); + } + MyMessageBox(s); + break; + + case 2: //Energy + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,2); + pDoc->lua_gapintegral(lua); + y1=lua_todouble(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + if (pDoc->Frequency==0) + s.Format("Stored Energy = %g J",y1); + else + s.Format("Average Stored Energy = %g J",y1); + MyMessageBox(s); + break; + + case 3: //Interaction Torque + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,5); + pDoc->lua_gapintegral(lua); + z1=lua_tonumber(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + s.Format("Torque = %s Nm",z1.ToStringAlt(c)); + MyMessageBox(s); + break; + + case 4: //Interaction Force + lua_pushstring(lua,dlg.BdryName); + lua_pushnumber(lua,6); + pDoc->lua_gapintegral(lua); + z2=lua_tonumber(lua,-2); + z1=lua_tonumber(lua,-1); + n = lua_gettop(lua); lua_pop(lua, n); + + s.Format("1X Fx = %s Nm\n1X Fx = %s",z1.ToStringAlt(c),z2.ToStringAlt(d)); + MyMessageBox(s); + break; + + default: + break; + } + } + +} + + + +void CFemmviewView::OnSmooth() +{ + CFemmviewDoc *pDoc=GetDocument(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if (pDoc->Smooth==TRUE){ + pDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + } + else{ + pDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + RedrawView(); +} + +BOOL CFemmviewView::OnEraseBkgnd(CDC* pDC) +{ + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + return TRUE; + +} + +void CFemmviewView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + CFemmviewDoc *pDoc=GetDocument(); + + if(EditAction==0){ + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + sprintf(s,"Closest input node:\n(%g,%g)",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + AfxMessageBox(s,MB_ICONINFORMATION); + } + } + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + CView::OnRButtonDblClk(nFlags, point); +} + + + + +void CFemmviewView::OnPanDown() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy-=0.25*y/mag; + + RedrawView(); +} + +void CFemmviewView::OnPanLeft() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; + + RedrawView(); +} + +void CFemmviewView::OnPanRight() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; + + RedrawView(); +} + +void CFemmviewView::OnPanUp() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy+=0.25*y/mag; + + RedrawView(); +} + +void CFemmviewView::OnViewCircprops() +{ + CCircDlg dlg; + + dlg.TheDoc=GetDocument(); + dlg.DoModal(); + +} + +void CFemmviewView::RedrawView() +{ + LinePix.RemoveAll(); + InvalidateRect(NULL); +} + +BOOL CFemmviewView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"femmview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAi); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + + +BOOL CFemmviewView::WritePreferences() +{ + FILE *fp; + CString fname; + CFemmviewDoc *pDoc=GetDocument(); + + fname=BinDir+"femmview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("FluxIColor",ImagFluxLineColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorRColor", RealVectorColor,fp); + WriteColor("VectorIColor", ImagVectorColor,fp); + WriteColor("NameColor", NameColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",d_EditAction); + fprintf(fp," = %i\n",d_DensityPlot); + fprintf(fp," = %i\n",d_VectorPlot); + fprintf(fp," = %i\n",d_GridFlag); + fprintf(fp," = %i\n",d_SnapFlag); + fprintf(fp," = %i\n",d_MeshFlag); + fprintf(fp," = %i\n",d_LegendFlag); + fprintf(fp," = %i\n",d_NumContours); + fprintf(fp," = %i\n",d_ShowAr); + fprintf(fp," = %i\n",d_ShowAi); + fprintf(fp," = %i\n",d_ShowMask); + fprintf(fp," = %i\n",d_GreyContours); + fprintf(fp," = %i\n",d_PtsFlag); + fprintf(fp," = %i\n",d_ResetOnReload); + fprintf(fp," = %i\n",d_Smooth); + fprintf(fp," = %i\n",d_PlotPoints); + fprintf(fp," = %i\n", + pDoc->d_LineIntegralPoints); + fprintf(fp," = %i\n",pDoc->d_ShiftH); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void CFemmviewView::CheckIt() +{ + // make sure all of the right things are checked + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar1,*pToolBar2; + pToolBar1=&MFrm->m_FV_toolBar1; + pToolBar2=&MFrm->m_leftbar; + CToolBarCtrl *tc1=&pToolBar1->GetToolBarCtrl(); + CToolBarCtrl *tc2=&pToolBar2->GetToolBarCtrl(); + if(SnapFlag==FALSE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc2->PressButton(ID_SNAP_GRID,TRUE); + } + + + if(GridFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc2->PressButton(ID_SHOW_GRID,TRUE); + } + + if(MeshFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc1->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc1->PressButton(ID_SHOW_MESH,TRUE); + } + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc1->PressButton(ID_MENU_AREA, FALSE); + tc1->PressButton(ID_MENU_CONTOUR, FALSE); + tc1->PressButton(ID_MENU_POINT,FALSE); + + if (EditAction==2){ + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + tc1->PressButton(ID_MENU_AREA, TRUE); + } + if (EditAction==1){ + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + tc1->PressButton(ID_MENU_CONTOUR, TRUE); + } + if (EditAction==0){ + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc1->PressButton(ID_MENU_POINT,TRUE); + } + + if(PtsFlag==TRUE) + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + CFemmviewDoc *pDoc=GetDocument(); + if (pDoc->Smooth==FALSE) + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + + if(ShowNames==FALSE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } +} + +void CFemmviewView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + CFemmviewDoc *pDoc=GetDocument(); + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if(EditAction==2) + { + CFemmviewDoc *pDoc=GetDocument(); + int i,k,grp,sel; + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + grp=pDoc->blocklist[pDoc->meshelem[k].lbl].InGroup; + sel=pDoc->blocklist[pDoc->meshelem[k].lbl].IsSelected; + for(i=0;iblocklist.GetSize();i++) + if ((pDoc->blocklist[i].InGroup==grp) && + (pDoc->blocklist[i].IsSelected!=sel)) + { + pDoc->blocklist[i].IsSelected=sel; + DrawSelected=i; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + } + } + + CView::OnLButtonDblClk(nFlags, point); +} + +void CFemmviewView::OnViewBHcurves() +{ + CXYPlotDlg dlg; + CFemmviewDoc *pDoc=GetDocument(); + int PlotType,npoints,FileFormat; + int i,k; + BOOL ToFile; + + for(k=0,i=0;kblockproplist.GetSize();k++) + if(pDoc->blockproplist[k].BHpoints>0) i++; + if(i==0){ + MsgBox("No nonlinear materials in this solution"); + return; + } + + dlg.ListType=2; + dlg.pDoc=pDoc; + dlg.m_npoints=d_PlotPoints; + + if (dlg.DoModal()==IDOK){ + // figure out the right material index; + PlotType=dlg.XYPlotType; + for(k=0,i=0;kblockproplist.GetSize();k++) + { + if(pDoc->blockproplist[k].BHpoints>0) + { + if(i==PlotType) + { + PlotType=k; + k=(int) pDoc->blockproplist.GetSize(); + } + else i++; + } + } + + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + CXYPlot xyplot; + + if(pDoc->Frequency==0){ + xyplot.Create(npoints,2); + strcpy(xyplot.lbls[0],"H, A/m"); + strcpy(xyplot.lbls[1],"B, T"); + } + else{ + xyplot.Create(npoints,3); + strcpy(xyplot.lbls[0],"H, A/m"); + strcpy(xyplot.lbls[1],"Re[B], T"); + strcpy(xyplot.lbls[2],"Im[B], T"); + } + + CMaterialProp *blk=&(pDoc->blockproplist[PlotType]); + double b; + double db=(blk->Bdata[blk->BHpoints-1])/((double) (npoints-1)); + CComplex B,H; + + for(i=1,b=db;iGetH(CComplex(b)); + B=abs(H)*b/H; + H=abs(H); + xyplot.M[i][0]=Re(H); + xyplot.M[i][1]=Re(B); + if (pDoc->Frequency!=0) xyplot.M[i][2]=Im(B); + } + + if(ToFile==FALSE){ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else xyplot.ToDisk(FileFormat); + + } +} + +void CFemmviewView::OnViewInfo() +{ + CFemmviewDoc *pDoc=GetDocument(); + CString s,z,tmp; + + // first line; + s.Format("Title: %s\r\n",pDoc->GetTitle()); + + // second line; + switch(pDoc->LengthUnits){ + case 0: + s+="Length Units: Inches\r\n"; + z=" in"; + break; + case 1: + s+="Length Units: Millimeters\r\n"; + z=" mm"; + break; + case 2: + s+="Length Units: Centimeters\r\n"; + z=" cm"; + break; + case 4: + s+="Length Units: Mils\r\n"; + z=" mil"; + break; + case 5: + s+="Length Units: Micrometers\r\n"; + z=" um"; + break; + default: + s+="Length Units: Meters\r\n"; + z=" m"; + break; + } + + // third line + if(pDoc->ProblemType==TRUE) s+="Axisymmetric Solution\r\n"; + else{ + tmp.Format("2-D Planar (Depth: %g",pDoc->Depth/pDoc->LengthConv[pDoc->LengthUnits]); + s+=tmp+z+")\r\n"; + } + + // fourth line + tmp.Format("Frequency: %g Hz\r\n\r\n",pDoc->Frequency); + s+=tmp; + + // sixth line + tmp.Format("%i Nodes\r\n",pDoc->meshnode.GetSize()); + s+=tmp; + + // seventh line + tmp.Format("%i Elements",pDoc->meshelem.GetSize()); + s+=tmp; + + // display it + Dspl->SetDlgItemText(IDC_OUTBOX,s); + OutputWindowText=s; +} +void CFemmviewView::OnViewShownames() +{ + ShowNames=1-ShowNames; + RedrawView(); +} + +void CFemmviewView::OnVplot() +{ + // TODO: Add your command handler code here + CVPlotDlg dlg; + CFemmviewDoc *pDoc=GetDocument(); + + dlg.m_vectorscalefactor=VectorScaleFactor; + dlg.m_plottype=VectorPlot; + if (pDoc->Frequency==0) dlg.ListType=0; + else dlg.ListType=1; + + if(dlg.DoModal()==IDOK) + { + VectorScaleFactor=dlg.m_vectorscalefactor; + VectorPlot=dlg.m_plottype; + InvalidateRect(NULL); + } +} + +void CFemmviewView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CFemmviewView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm)MoveTo(Xm,Ym); + pDC->LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC->MoveTo((int) Re(pc), (int) Im(pc)); + pDC->LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +BOOL CFemmviewView::IsMinimized() +{ + CChildFrame *pChildFrm = (CChildFrame *)GetParentFrame(); + if (pChildFrm->GetStyle() & WS_MINIMIZE) return TRUE; return FALSE; +} + +void CFemmviewView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if ((bActivate) && (pActivateView==this)){ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(2); + CheckIt(); + } + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CFemmviewView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CFemmviewView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + // The child frame makes a special effort to pass down the + // WM_SIZE message when a window is minimized. The view + // uses this message to minimize the output window, if it is visible. + if(nType==SIZE_MINIMIZED) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if(MFrm->m_dlgBar.GetStyle() & WS_VISIBLE) + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + } + +} + +// if((theApp.bShowOutputWindow) && (!IsMinimized()) && +// (!MFrm->IsIconic()) && ((MFrm->m_dlgBar.GetStyle() & WS_VISIBLE)!=0)){ +// MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); +// MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); +// } \ No newline at end of file diff --git a/femm/FemmviewView.h b/femm/FemmviewView.h new file mode 100644 index 0000000..b9b53d0 --- /dev/null +++ b/femm/FemmviewView.h @@ -0,0 +1,230 @@ +// femmviewView.h : interface of the CFemmviewView class +// +///////////////////////////////////////////////////////////////////////////// + +class CFemmviewView : public CView +{ +protected: // create from serialization only + CFemmviewView(); + DECLARE_DYNCREATE(CFemmviewView) + +// Attributes +public: + + CFemmviewDoc* GetDocument(); + + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void EnterPoint(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL LegendFlag; + BOOL ShowNames; + BOOL GreyContours; + BOOL PtsFlag; + BOOL Coords; // False=Cartesian; True=Polar + int ZoomWndFlag; + int DrawSelected; + int VectorPlot; + double VectorScaleFactor; + double wzx,wzy; + +// default behaviors + int d_EditAction; + BOOL d_GridFlag; + BOOL d_SnapFlag; + BOOL d_MeshFlag; + BOOL d_LegendFlag; + BOOL d_GreyContours; + int d_NumContours; + BOOL d_ShowAr; + BOOL d_ShowAi; + BOOL d_ShowMask; + int d_DensityPlot; + BOOL d_PtsFlag; + BOOL d_ResetOnReload; + BOOL d_Smooth; + BOOL d_ShowNames; + BOOL d_PlotPoints; + int d_VectorPlot; + + COutBox *Dspl; + CString BinDir; // pathname for triangle.exe + + int NumContours; + BOOL ShowAr,ShowAi,ShowMask; + int DensityPlot; + CString OutputWindowText; + + CArray< CPixel, CPixel& > LinePix; + CArray< CZPix, CZPix& > ZoomPix; + + // Greyscale Density Plot Colormap + COLORREF Grey00; + COLORREF Grey01; + COLORREF Grey02; + COLORREF Grey03; + COLORREF Grey04; + COLORREF Grey05; + COLORREF Grey06; + COLORREF Grey07; + COLORREF Grey08; + COLORREF Grey09; + COLORREF Grey10; + COLORREF Grey11; + COLORREF Grey12; + COLORREF Grey13; + COLORREF Grey14; + COLORREF Grey15; + COLORREF Grey16; + COLORREF Grey17; + COLORREF Grey18; + COLORREF Grey19; + + // Density Plot Colormap + COLORREF Color00; + COLORREF Color01; + COLORREF Color02; + COLORREF Color03; + COLORREF Color04; + COLORREF Color05; + COLORREF Color06; + COLORREF Color07; + COLORREF Color08; + COLORREF Color09; + COLORREF Color10; + COLORREF Color11; + COLORREF Color12; + COLORREF Color13; + COLORREF Color14; + COLORREF Color15; + COLORREF Color16; + COLORREF Color17; + COLORREF Color18; + COLORREF Color19; + + // Other colors + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF RegionColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF TextColor; + COLORREF NodeColor; + COLORREF RealFluxLineColor; + COLORREF ImagFluxLineColor; + COLORREF MaskLineColor; + COLORREF NameColor; + COLORREF RealVectorColor; + COLORREF ImagVectorColor; + +// Operations +public: + + void DoContours(CDC *pDC, int *p, int side, int Aflag); + void PlotFluxDensity(CDC *pDC,int elmnum,int flag); + void DisplayPointProperties(double px, double py); + void DrawUserContour(BOOL flag); + void EraseUserContour(BOOL flag); + void SpecialLine(CDC *pDC, int x0, int y0, int x1, int y1, BOOL flag); + void PlotSelectedElm(CDC *pDC,CElement &elm); + void RedrawView(); + BOOL IsMinimized(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void CheckIt(); + void LuaViewInfo(); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmviewView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmviewView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmviewView) + afx_msg void OnZoomIn(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnCplot(); + afx_msg void OnDplot(); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomOut(); + afx_msg void OnZoomWindow(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnEditCopy(); + afx_msg void OnReload(); + afx_msg void OnMenuArea(); + afx_msg void OnMenuContour(); + afx_msg void OnMenuPoint(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMenuPlot(); + afx_msg void OnMenuIntegrate(); + afx_msg void OnMenushowpts(); + afx_msg void OnKbdZoom(); + afx_msg void OnSmooth(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnViewCircprops(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnViewBHcurves(); + afx_msg void OnViewInfo(); + afx_msg void OnViewShownames(); + afx_msg void OnVplot(); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); +}; + +#ifndef _DEBUG // debug version in femmviewView.cpp +inline CFemmviewDoc* CFemmviewView::GetDocument() + { return (CFemmviewDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + + diff --git a/femm/GRIDDLG.CPP b/femm/GRIDDLG.CPP new file mode 100644 index 0000000..75b9007 --- /dev/null +++ b/femm/GRIDDLG.CPP @@ -0,0 +1,62 @@ +// GRIDDLG.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "GRIDDLG.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// GRIDDLG dialog + + +GRIDDLG::GRIDDLG(CWnd* pParent /*=NULL*/) + : CDialog(GRIDDLG::IDD, pParent) +{ + //{{AFX_DATA_INIT(GRIDDLG) + m_gridsize = 0.0; + //}}AFX_DATA_INIT +} + + +void GRIDDLG::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(GRIDDLG) + DDX_Control(pDX, IDC_COORDS, m_coords); + DDX_Text(pDX, IDC_GRIDSIZE, m_gridsize); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_GRIDSIZE, m_IDC_gridsize); +} + + +BEGIN_MESSAGE_MAP(GRIDDLG, CDialog) + //{{AFX_MSG_MAP(GRIDDLG) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// GRIDDLG message handlers + +BOOL GRIDDLG::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_coords.SetCurSel(coords); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void GRIDDLG::OnOK() +{ + // TODO: Add extra validation here + coords=m_coords.GetCurSel(); + CDialog::OnOK(); +} diff --git a/femm/GRIDDLG.H b/femm/GRIDDLG.H new file mode 100644 index 0000000..97eabfe --- /dev/null +++ b/femm/GRIDDLG.H @@ -0,0 +1,41 @@ +// GRIDDLG.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// GRIDDLG dialog + +class GRIDDLG : public CDialog +{ +// Construction +public: + GRIDDLG(CWnd* pParent = NULL); // standard constructor + + BOOL coords; + +// Dialog Data + //{{AFX_DATA(GRIDDLG) + enum { IDD = IDD_GRIDDLG }; + CComboBox m_coords; + double m_gridsize; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(GRIDDLG) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(GRIDDLG) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_gridsize; +}; diff --git a/femm/GapIntegral.cpp b/femm/GapIntegral.cpp new file mode 100644 index 0000000..1054dfa --- /dev/null +++ b/femm/GapIntegral.cpp @@ -0,0 +1,85 @@ +// GapIntegral.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "problem.h" +#include "XYPlot.h" +#include "femmviewdoc.h" +#include "GapIntegral.h" + + +// GapIntegral dialog + +IMPLEMENT_DYNAMIC(GapIntegral, CDialog) + +GapIntegral::GapIntegral(CWnd* pParent /*=NULL*/) + : CDialog(GapIntegral::IDD, pParent) +{ + +} + +GapIntegral::~GapIntegral() +{ +} + +void GapIntegral::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_AGENAME, m_AGEname); + DDX_Control(pDX, IDC_GAPINTTYPE, m_IntType); +} + +BEGIN_MESSAGE_MAP(GapIntegral, CDialog) + //{{AFX_MSG_MAP(GapIntegral) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +// GapIntegral message handlers + +BOOL GapIntegral::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &agelist=*pagelist; + int i; + + // TODO: Add extra initialization here + for(i=0;i &agelist=*pagelist; + BdryName=agelist[m_AGEname.GetCurSel()].BdryName; + + if (bIncremental==FALSE) + { + myIntType=m_IntType.GetCurSel(); + } + else{ + myIntType=m_IntType.GetCurSel() + 3; + } + + CDialog::OnOK(); +} \ No newline at end of file diff --git a/femm/GapIntegral.h b/femm/GapIntegral.h new file mode 100644 index 0000000..f577968 --- /dev/null +++ b/femm/GapIntegral.h @@ -0,0 +1,38 @@ +#pragma once +#include "afxwin.h" + + +// GapIntegral dialog + +class GapIntegral : public CDialog +{ + DECLARE_DYNAMIC(GapIntegral) + +public: + GapIntegral(CWnd* pParent = NULL); // standard constructor + virtual ~GapIntegral(); + + + CArray *pagelist; + double Frequency; + int bIncremental; + CString BdryName; + int myIntType; + +// Dialog Data + enum { IDD = IDD_GAPINTEGRAL }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + // Generated message map functions + //{{AFX_MSG(GapIntegral) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CComboBox m_AGEname; + CComboBox m_IntType; +}; diff --git a/femm/GapPlotDlg.cpp b/femm/GapPlotDlg.cpp new file mode 100644 index 0000000..73ecad7 --- /dev/null +++ b/femm/GapPlotDlg.cpp @@ -0,0 +1,101 @@ +// GapPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "problem.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewView.h" +#include "MainFrm.h" +#include "lua.h" + +#include "GapPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGapPlotDlg dialog + + +CGapPlotDlg::CGapPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(CGapPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGapPlotDlg) + m_ToFile = FALSE; + m_npoints = 150; + m_age=0; + //}}AFX_DATA_INIT + XYPlotType=0; + FileFormat=0; +} + + +void CGapPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGapPlotDlg) + DDX_Control(pDX, IDC_FILEFORMAT, m_fileformat); + DDX_Control(pDX, IDC_XYPLOTTYPE, m_XYPlotType); + DDX_Control(pDX, IDC_BDRYNAME, m_BdryName); + DDX_Check(pDX, IDC_TOFILE, m_ToFile); + DDX_Text(pDX, IDC_NPOINTS, m_npoints); + DDV_MinMaxInt(pDX, m_npoints, 10, 100000); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_NPOINTS, m_IDC_npoints); +} + + +BEGIN_MESSAGE_MAP(CGapPlotDlg, CDialog) + //{{AFX_MSG_MAP(CGapPlotDlg) + ON_BN_CLICKED(IDC_TOFILE, OnToFileClicked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGapPlotDlg message handlers + +BOOL CGapPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CArray &agelist=*pagelist; + for (int k=0;k *pagelist; + +// Dialog Data + //{{AFX_DATA(CGapPlotDlg) + enum { IDD = IDD_GAPPLOTDLG }; + CComboBox m_fileformat; + CComboBox m_XYPlotType; + CComboBox m_BdryName; + BOOL m_ToFile; + int m_npoints; + int m_age; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGapPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGapPlotDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnToFileClicked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_npoints; +}; \ No newline at end of file diff --git a/femm/GeneralPrefs.cpp b/femm/GeneralPrefs.cpp new file mode 100644 index 0000000..ef5f354 --- /dev/null +++ b/femm/GeneralPrefs.cpp @@ -0,0 +1,170 @@ +// GeneralPrefs.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "GeneralPrefs.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGeneralPrefs dialog + + +CGeneralPrefs::CGeneralPrefs(CWnd* pParent /*=NULL*/) + : CDialog(CGeneralPrefs::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGeneralPrefs) + m_def_lua_console = FALSE; + m_def_xyplot = FALSE; + m_def_show_output_window = TRUE; + m_def_smartmesh = TRUE; + //}}AFX_DATA_INIT + + s_defdoc=0; +} + + +void CGeneralPrefs::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGeneralPrefs) + DDX_Control(pDX, IDC_DEF_DOC, m_defdoc); + DDX_Check(pDX, IDC_DEF_LUA_CONSOLE, m_def_lua_console); + DDX_Check(pDX, IDC_DEF_XYPLOT, m_def_xyplot); + DDX_Check(pDX, IDC_DEF_SHOWOUTWND, m_def_show_output_window); + DDX_Check(pDX, IDC_DEF_SMARTMESH, m_def_smartmesh); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGeneralPrefs, CDialog) + //{{AFX_MSG_MAP(CGeneralPrefs) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGeneralPrefs message handlers +char* StripKey(char *c); + +void CGeneralPrefs::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "femm.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_def_lua_console); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_def_xyplot); + q[0]=NULL; + } + + if( _strnicmp(q,"",18)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_def_show_output_window); + q[0]=NULL; + } + + if( _strnicmp(q,"",18)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_def_smartmesh); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_defdoc); + q[0]=NULL; + } + } + fclose(fp); + } +} + +void CGeneralPrefs::WritePrefs() +{ + FILE *fp; + CString fname; + + UpdateData(); + + fname=((CFemmApp *)AfxGetApp())->GetExecutablePath()+"femm.cfg"; + s_defdoc=m_defdoc.GetCurSel(); + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + fprintf(fp," = %i\n",m_def_lua_console); + fprintf(fp," = %i\n",m_def_xyplot); + fprintf(fp," = %i\n",m_def_show_output_window); + fprintf(fp," = %i\n",m_def_smartmesh); + fprintf(fp," = %i\n",s_defdoc); + fclose(fp); + } + + // bubble xy plot preference back to the main app + ((CFemmApp *)AfxGetApp())->d_sepplot=m_def_xyplot; +} + +BOOL CGeneralPrefs::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +BOOL CGeneralPrefs::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_defdoc.SetCurSel(s_defdoc); + + UpdateData(FALSE); + + return TRUE; +} + diff --git a/femm/GeneralPrefs.h b/femm/GeneralPrefs.h new file mode 100644 index 0000000..2d6658c --- /dev/null +++ b/femm/GeneralPrefs.h @@ -0,0 +1,58 @@ +#if !defined(AFX_GENERALPREFS_H__9C2D61CC_B458_496C_9A23_BD2CD5D22AC8__INCLUDED_) +#define AFX_GENERALPREFS_H__9C2D61CC_B458_496C_9A23_BD2CD5D22AC8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GeneralPrefs.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGeneralPrefs dialog + +class CGeneralPrefs : public CDialog +{ +// Construction +public: + CGeneralPrefs(CWnd* pParent = NULL); // standard constructor + int s_defdoc; + + void WritePrefs(); + void ScanPrefs(); + +// Dialog Data + //{{AFX_DATA(CGeneralPrefs) + enum { IDD = IDD_GENPREFS }; + CComboBox m_defdoc; + BOOL m_def_lua_console; + BOOL m_def_xyplot; + BOOL m_def_show_output_window; + BOOL m_def_smartmesh; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGeneralPrefs) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGeneralPrefs) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GENERALPREFS_H__9C2D61CC_B458_496C_9A23_BD2CD5D22AC8__INCLUDED_) diff --git a/femm/GridMod.cpp b/femm/GridMod.cpp new file mode 100644 index 0000000..6dd44eb --- /dev/null +++ b/femm/GridMod.cpp @@ -0,0 +1,63 @@ +// GridMod.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "GridMod.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGridMod dialog + + +CGridMod::CGridMod(CWnd* pParent /*=NULL*/) + : CDialog(CGridMod::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGridMod) + m_gridsize = 0.0; + //}}AFX_DATA_INIT +} + + +void CGridMod::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGridMod) + DDX_Control(pDX, IDC_COORDS, m_coords); + DDX_Text(pDX, IDC_GRIDSIZE, m_gridsize); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_GRIDSIZE, m_IDC_gridsize); +} + + +BEGIN_MESSAGE_MAP(CGridMod, CDialog) + //{{AFX_MSG_MAP(CGridMod) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGridMod message handlers + +BOOL CGridMod::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_coords.SetCurSel(coords); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CGridMod::OnOK() +{ + // TODO: Add extra validation here + coords=m_coords.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/GridMod.h b/femm/GridMod.h new file mode 100644 index 0000000..d853ab6 --- /dev/null +++ b/femm/GridMod.h @@ -0,0 +1,40 @@ +// GridMod.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGridMod dialog + +class CGridMod : public CDialog +{ +// Construction +public: + CGridMod(CWnd* pParent = NULL); // standard constructor + int coords; + +// Dialog Data + //{{AFX_DATA(CGridMod) + enum { IDD = IDD_GRIDMOD }; + CComboBox m_coords; + double m_gridsize; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGridMod) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGridMod) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_gridsize; +}; diff --git a/femm/GroupNumber.cpp b/femm/GroupNumber.cpp new file mode 100644 index 0000000..ead7d7e --- /dev/null +++ b/femm/GroupNumber.cpp @@ -0,0 +1,44 @@ +// GroupNumber.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "GroupNumber.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGroupNumber dialog + + +CGroupNumber::CGroupNumber(CWnd* pParent /*=NULL*/) + : CDialog(CGroupNumber::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGroupNumber) + m_groupnumber = 0; + //}}AFX_DATA_INIT +} + + +void CGroupNumber::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGroupNumber) + DDX_Text(pDX, IDC_GROUPNUMBER, m_groupnumber); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_GROUPNUMBER, m_IDC_groupnumber); +} + + +BEGIN_MESSAGE_MAP(CGroupNumber, CDialog) + //{{AFX_MSG_MAP(CGroupNumber) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGroupNumber message handlers diff --git a/femm/GroupNumber.h b/femm/GroupNumber.h new file mode 100644 index 0000000..c525f6a --- /dev/null +++ b/femm/GroupNumber.h @@ -0,0 +1,37 @@ +// GroupNumber.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGroupNumber dialog + +class CGroupNumber : public CDialog +{ +// Construction +public: + CGroupNumber(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGroupNumber) + enum { IDD = IDD_GROUPNO }; + int m_groupnumber; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGroupNumber) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGroupNumber) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_groupnumber; +}; diff --git a/femm/HDRAWDOC.CPP b/femm/HDRAWDOC.CPP new file mode 100644 index 0000000..c880368 --- /dev/null +++ b/femm/HDRAWDOC.CPP @@ -0,0 +1,2639 @@ +// 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) +#include + +#include "lua.h" +#include "luaconsoledlg.h" +#include "luadebug.h" + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +extern CFemmApp theApp; // + +// hdrawDoc.h : interface of the ChdrawDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class ChdrawDoc : public CDocument +{ +protected: // create from serialization only + ChdrawDoc(); + DECLARE_DYNCREATE(ChdrawDoc) + +// Attributes +public: + + // General problem attributes + double Precision; + double MinAngle; + int SmartMesh; + double Depth; + int LengthUnits; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + CString PrevSoln; + BOOL FirstDraw; + BOOL NoDraw; + double dT; + + // default behaviors + double d_prec; + double d_minangle; + double d_depth; + int d_coord; + int d_length; + int d_type; + + CString BinDir; + + // lists of nodes, segments, and block labels + CArray< hdrawdata::CNode, hdrawdata::CNode&> nodelist; + CArray< hdrawdata::CSegment, hdrawdata::CSegment&> linelist; + CArray< hdrawdata::CArcSegment, hdrawdata::CArcSegment&> arclist; + CArray< hdrawdata::CBlockLabel, hdrawdata::CBlockLabel&> blocklist; + + // lists of nodes, segments, and block labels for undo purposes... + CArray< hdrawdata::CNode, hdrawdata::CNode&> undonodelist; + CArray< hdrawdata::CSegment, hdrawdata::CSegment&> undolinelist; + CArray< hdrawdata::CArcSegment, hdrawdata::CArcSegment&> undoarclist; + CArray< hdrawdata::CBlockLabel, hdrawdata::CBlockLabel&> undoblocklist; + + // CArrays containing the mesh information + CArray< CPoint, CPoint&> meshline; + CArray< CPoint, CPoint&> greymeshline; + CArray< hdrawdata::CNode, hdrawdata::CNode&> meshnode; + + // lists of properties + CArray< hdrawdata::CMaterialProp, hdrawdata::CMaterialProp& > blockproplist; + CArray< hdrawdata::CBoundaryProp, hdrawdata::CBoundaryProp& > lineproplist; + CArray< hdrawdata::CPointProp, hdrawdata::CPointProp& > nodeproplist; + CArray< hdrawdata::CCircuit, hdrawdata::CCircuit& > circproplist; + double extRo,extRi,extZo; + +// Operations +public: + + void UnselectAll(); + double ShortestDistance(double p, double q, int segm); + + BOOL AddNode(double x, double y, double d); + + BOOL AddSegment(int n0, int n1, double tol=0); + BOOL AddSegment(int n0, int n1, hdrawdata::CSegment *parsegm, double tol=0); + BOOL AddArcSegment(hdrawdata::CArcSegment &asegm, double tol=0); + BOOL AddBlockLabel(double x, double y, double d); + BOOL AddNode(hdrawdata::CNode &node, double d); + BOOL AddSegment(CComplex p0, CComplex p1, hdrawdata::CSegment &segm, double tol=0); + BOOL AddArcSegment(CComplex p0, CComplex p1, hdrawdata::CArcSegment &asegm, double tol=0); + + BOOL AddBlockLabel(hdrawdata::CBlockLabel &blabel, double d); + int ClosestNode(double x, double y); + int ClosestBlockLabel(double x, double y); + int ClosestSegment(double x, double y); + BOOL GetIntersection(int n0, int n1, int segm, double *xi, double *yi); + int ClosestArcSegment(double x, double y); + void GetCircle(hdrawdata::CArcSegment &asegm,CComplex &c, double &R); + int GetLineArcIntersection(hdrawdata::CSegment &seg, hdrawdata::CArcSegment &arc, CComplex *p); + int GetArcArcIntersection(hdrawdata::CArcSegment &arc1, hdrawdata::CArcSegment &arc2, CComplex *p); + double ShortestDistanceFromArc(CComplex p, hdrawdata::CArcSegment &arc); + void RotateMove(CComplex c, double t, int EditAction); + void TranslateMove(double dx, double dy, int EditAction); + void ScaleMove(double bx, double by, double sf, int EditAction); + void MirrorSelected(double x0, double y0, double x1, double y1, int ea); + void RotateCopy(CComplex c, double t, int ncopies, int EditAction); + void TranslateCopy(double dx, double dy, int ncopies, int EditAction); + BOOL DeleteSelectedNodes(); + BOOL DeleteSelectedSegments(); + BOOL DeleteSelectedArcSegments(); + BOOL DeleteSelectedBlockLabels(); + BOOL OpBlkDlg(); + void OpNodeDlg(); + void OpSegDlg(); + void OpArcSegDlg(); + void OpGrpDlg(); + BOOL LoadMesh(); + BOOL OnWritePoly(); + BOOL FunnyOnWritePoly(); + BOOL ReadDXF(CString fname, double DefTol=-1.); + BOOL WriteDXF(CString fname); + BOOL HasPeriodicBC(); + BOOL CanCreateRadius(int n); + BOOL CreateRadius(int n, double r); + double LineLength(int i); + BOOL ScanPreferences(); + + void UpdateUndo(); + void Undo(); + void EnforcePSLG(); // makes sure that everything is kosher... + void EnforcePSLG(double tol); + void FancyEnforcePSLG(double tol); + BOOL SelectOrphans(); + BOOL dxf_line_hook(); +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ChdrawDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + void initalise_lua(); + static int lua_prob_def(lua_State *L); + static int luaSaveDocument(lua_State *L); + static int lua_create_mesh(lua_State *L); + static int lua_smartmesh(lua_State *L); + static int lua_purge_mesh(lua_State *L); + static int lua_show_mesh(lua_State *L); + static int lua_analyze(lua_State *L); + static int lua_runpost(lua_State *L); + static int lua_addnode(lua_State *L); + static int lua_addlabel(lua_State *L); + static int lua_addline(lua_State *L); + static int lua_addarc(lua_State *L); + static int lua_selectnode(lua_State *L); + static int lua_selectlabel(lua_State *L); + static int lua_selectsegment(lua_State *L); + static int lua_selectarcsegment(lua_State *L); + static int lua_clearselected(lua_State *L); + static int lua_setnodeprop(lua_State *L); + static int lua_setblockprop(lua_State *L); + static int lua_setsegmentprop(lua_State *L); + static int lua_setarcsegmentprop(lua_State *L); + static int lua_deleteselected(lua_State *L); + static int lua_deleteselectedsegments(lua_State *L); + static int lua_deleteselectednodes(lua_State *L); + static int lua_deleteselectedlabels(lua_State *L); + static int lua_deleteselectedarcsegments(lua_State *L); + static int lua_zoomout(lua_State *L); + static int lua_zoomnatural(lua_State *L); + static int lua_zoomin(lua_State *L); + static int lua_move_translate(lua_State *L); + static int lua_move_rotate(lua_State *L); + static int lua_copy_translate(lua_State *L); + static int lua_copy_rotate(lua_State *L); + static int lua_mirror(lua_State *L); + static int lua_scale(lua_State *L); + static int lua_addmatprop(lua_State *L); + static int lua_addpointprop(lua_State *L); + static int lua_addboundprop(lua_State *L); + static int lua_addcircuitprop(lua_State *L); + static int lua_delcircuitprop(lua_State *L); + static int lua_delpointprop(lua_State *L); + static int lua_delboundprop(lua_State *L); + static int lua_delmatprop(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_selectgroup(lua_State *L); + static int lua_zoom(lua_State *L); + static int lua_newdocument(lua_State *L); + static int lua_savebitmap(lua_State * L); + static int lua_modmatprop(lua_State *L); + static int lua_modboundprop(lua_State *L); + static int lua_modpointprop(lua_State *L); + static int lua_modcircprop(lua_State *L); + static int lua_exitpre(lua_State *L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC); + static int lua_saveWMF(lua_State *L); + static int lua_updatewindow(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_showgrid(lua_State *L); + static int lua_hidegrid(lua_State *L); + static int lua_gridsnap(lua_State *L); + static int lua_setgrid(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int lua_readdxf(lua_State *L); + static int lua_savedxf(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_defineouterspace(lua_State *L); + static int lua_attachouterspace(lua_State *L); + static int lua_detachouterspace(lua_State *L); + static int lua_attachdefault(lua_State *L); + static int lua_detachdefault(lua_State *L); + static int lua_createradius(lua_State *L); + static int lua_addtkpoint(lua_State *L); + static int lua_cleartkpoints(lua_State *L); + static int lua_gettitle(lua_State *L); + static int lua_setgroup(lua_State *L); + static int lua_getmaterial(lua_State *L); + static int lua_getboundingbox(lua_State *L); + static int lua_getprobleminfo(lua_State *L); + static int lua_selectcircle(lua_State *L); + static int lua_selectrectangle(lua_State *L); + virtual ~ChdrawDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(ChdrawDoc) + afx_msg void OnDefineProblem(); + afx_msg void OnEditMatprops(); + afx_msg void OnEditPtprops(); + afx_msg void OnEditSegprops(); + afx_msg void OnEditCircprops(); + afx_msg void OnEditExterior(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); +char *ParseDbl(char *t, double *f); +char *ParseInt(char *t, int *f); diff --git a/femm/HDRAWLUA.CPP b/femm/HDRAWLUA.CPP new file mode 100644 index 0000000..b2caec0 --- /dev/null +++ b/femm/HDRAWLUA.CPP @@ -0,0 +1,2891 @@ +// hdrawDoc.cpp : implementation of the ChdrawDoc class +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hdrawView.h" +#include "promptbox.h" +#include "MainFrm.h" +#include "ChildFrm.h" + +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern void *phdrawDoc; +extern lua_State * lua; +extern BOOL bLinehook; +extern int m_luaWindowStatus; + +#define CatchNullDocument(); if (phdrawDoc==NULL)\ + { CString msg="No heat flow input in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//---------------------Lua Extensions------------------------ + +void ChdrawDoc::initalise_lua() +{ + + // register lua extensions + lua_register(lua,"hi_setfocus",lua_switchfocus); + lua_register(lua,"hi_saveas",luaSaveDocument); + lua_register(lua,"hi_createmesh",lua_create_mesh); + lua_register(lua,"hi_smartmesh",lua_smartmesh); + lua_register(lua,"hi_showmesh",lua_show_mesh); + lua_register(lua,"hi_purgemesh",lua_purge_mesh); + lua_register(lua,"hi_probdef",lua_prob_def); + lua_register(lua,"hi_analyse",lua_analyze); + lua_register(lua,"hi_loadsolution",lua_runpost); + lua_register(lua,"hi_addnode",lua_addnode); + lua_register(lua,"hi_addblocklabel",lua_addlabel); + lua_register(lua,"hi_addsegment",lua_addline); + lua_register(lua,"hi_addarc",lua_addarc); + lua_register(lua,"hi_selectnode",lua_selectnode); + lua_register(lua,"hi_selectlabel",lua_selectlabel); + lua_register(lua,"hi_selectsegment",lua_selectsegment); + lua_register(lua,"hi_selectarcsegment",lua_selectarcsegment); + lua_register(lua,"hi_clearselected",lua_clearselected); + lua_register(lua,"hi_setnodeprop",lua_setnodeprop); + lua_register(lua,"hi_setblockprop",lua_setblockprop); + lua_register(lua,"hi_setsegmentprop",lua_setsegmentprop); + lua_register(lua,"hi_setarcsegmentprop",lua_setarcsegmentprop); + lua_register(lua,"hi_deleteselected",lua_deleteselected); + lua_register(lua,"hi_deleteselectednodes",lua_deleteselectednodes); + lua_register(lua,"hi_deleteselectedlabels",lua_deleteselectedlabels); + lua_register(lua,"hi_deleteselectedsegments",lua_deleteselectedsegments); + lua_register(lua,"hi_deleteselectedarcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"hi_zoomnatural",lua_zoomnatural); + lua_register(lua,"hi_zoomout",lua_zoomout); + lua_register(lua,"hi_zoomin",lua_zoomin); + lua_register(lua,"hi_zoom",lua_zoom); + lua_register(lua,"hi_addmaterial",lua_addmatprop); + lua_register(lua,"hi_addpointprop",lua_addpointprop); + lua_register(lua,"hi_addconductorprop",lua_addcircuitprop); + lua_register(lua,"hi_addboundprop",lua_addboundprop); + lua_register(lua,"hi_modifymaterial",lua_modmatprop); + lua_register(lua,"hi_modifyboundprop",lua_modboundprop); + lua_register(lua,"hi_modifypointprop",lua_modpointprop); + lua_register(lua,"hi_modifyconductorprop",lua_modcircprop); + lua_register(lua,"hi_deletematerial",lua_delmatprop); + lua_register(lua,"hi_deleteboundprop",lua_delboundprop); + lua_register(lua,"hi_deleteconductor",lua_delcircuitprop); + lua_register(lua,"hi_deletepointprop",lua_delpointprop); + lua_register(lua,"hi_moverotate",lua_move_rotate); + lua_register(lua,"hi_movetranslate",lua_move_translate); + lua_register(lua,"hi_copyrotate",lua_copy_rotate); + lua_register(lua,"hi_copytranslate",lua_copy_translate); + lua_register(lua,"hi_mirror",lua_mirror); + lua_register(lua,"hi_scale",lua_scale); + lua_register(lua,"hi_seteditmode",lua_seteditmode); + lua_register(lua,"hi_selectgroup",lua_selectgroup); + lua_register(lua,"hi_newdocument",lua_newdocument); + lua_register(lua,"hi_savebitmap",lua_savebitmap); + lua_register(lua,"hi_savemetafile",lua_saveWMF); + lua_register(lua,"hi_close",lua_exitpre); + lua_register(lua,"hi_refreshview",lua_updatewindow); + lua_register(lua,"hi_shownames",lua_shownames); + lua_register(lua,"hi_showgrid",lua_showgrid); + lua_register(lua,"hi_hidegrid",lua_hidegrid); + lua_register(lua,"hi_gridsnap",lua_gridsnap); + lua_register(lua,"hi_setgrid",lua_setgrid); + lua_register(lua,"hi_readdxf",lua_readdxf); + lua_register(lua,"hi_savedxf",lua_savedxf); + lua_register(lua,"hi_defineouterspace",lua_defineouterspace); + lua_register(lua,"hi_attachouterspace",lua_attachouterspace); + lua_register(lua,"hi_detachouterspace",lua_detachouterspace); + lua_register(lua,"hi_attachdefault",lua_attachdefault); + lua_register(lua,"hi_detachdefault",lua_detachdefault); + lua_register(lua,"hi_attach_default",lua_attachdefault); + lua_register(lua,"hi_detach_default",lua_detachdefault); + lua_register(lua,"hi_resize",luaResize); + lua_register(lua,"hi_minimize",luaMinimize); + lua_register(lua,"hi_gettitle",lua_gettitle); + lua_register(lua,"hi_get_title",lua_gettitle); + lua_register(lua,"hi_maximize",luaMaximize); + lua_register(lua,"hi_restore", luaRestore); + lua_register(lua,"hi_createradius",lua_createradius); + lua_register(lua,"hi_addtkpoint",lua_addtkpoint); + lua_register(lua,"hi_cleartkpoints",lua_cleartkpoints); + lua_register(lua,"hi_setgroup",lua_setgroup); + lua_register(lua,"hi_set_group",lua_setgroup); + lua_register(lua,"hi_getmaterial",lua_getmaterial); + lua_register(lua,"hi_get_material",lua_getmaterial); + lua_register(lua,"hi_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"hi_getboundingbox",lua_getboundingbox); + lua_register(lua,"hi_selectcircle",lua_selectcircle); + lua_register(lua,"hi_selectrectangle",lua_selectrectangle); + + // compatibility lua function names + lua_register(lua,"hi_select_rectangle",lua_selectrectangle); + lua_register(lua,"hi_select_circle",lua_selectcircle); + lua_register(lua,"hi_clear_tk_points",lua_cleartkpoints); + lua_register(lua,"hi_add_tk_point",lua_addtkpoint); + lua_register(lua,"hi_define_outer_space",lua_defineouterspace); + lua_register(lua,"hi_attach_outer_space",lua_attachouterspace); + lua_register(lua,"hi_detach_outer_space",lua_detachouterspace); + lua_register(lua,"hi_set_focus",lua_switchfocus); + lua_register(lua,"hi_save_as",luaSaveDocument); + lua_register(lua,"hi_create_mesh",lua_create_mesh); + lua_register(lua,"hi_show_mesh",lua_show_mesh); + lua_register(lua,"hi_purge_mesh",lua_purge_mesh); + lua_register(lua,"hi_prob_def",lua_prob_def); + lua_register(lua,"hi_analyze",lua_analyze); + lua_register(lua,"hi_load_solution",lua_runpost); + lua_register(lua,"hi_add_node",lua_addnode); + lua_register(lua,"hi_add_block_label",lua_addlabel); + lua_register(lua,"hi_add_segment",lua_addline); + lua_register(lua,"hi_add_arc",lua_addarc); + lua_register(lua,"hi_select_node",lua_selectnode); + lua_register(lua,"hi_select_label",lua_selectlabel); + lua_register(lua,"hi_select_segment",lua_selectsegment); + lua_register(lua,"hi_select_arcsegment",lua_selectarcsegment); + lua_register(lua,"hi_clear_selected",lua_clearselected); + lua_register(lua,"hi_set_node_prop",lua_setnodeprop); + lua_register(lua,"hi_set_block_prop",lua_setblockprop); + lua_register(lua,"hi_set_segment_prop",lua_setsegmentprop); + lua_register(lua,"hi_set_arcsegment_prop",lua_setarcsegmentprop); + lua_register(lua,"hi_delete_selected",lua_deleteselected); + lua_register(lua,"hi_delete_selected_nodes",lua_deleteselectednodes); + lua_register(lua,"hi_delete_selected_labels",lua_deleteselectedlabels); + lua_register(lua,"hi_delete_selected_segments",lua_deleteselectedsegments); + lua_register(lua,"hi_delete_selected_arcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"hi_zoom_natural",lua_zoomnatural); + lua_register(lua,"hi_zoom_out",lua_zoomout); + lua_register(lua,"hi_zoom_in",lua_zoomin); + lua_register(lua,"hi_add_material",lua_addmatprop); + lua_register(lua,"hi_add_point_prop",lua_addpointprop); + lua_register(lua,"hi_add_conductor_prop",lua_addcircuitprop); + lua_register(lua,"hi_add_bound_prop",lua_addboundprop); + lua_register(lua,"hi_modify_material",lua_modmatprop); + lua_register(lua,"hi_modify_bound_prop",lua_modboundprop); + lua_register(lua,"hi_modify_point_prop",lua_modpointprop); + lua_register(lua,"hi_modify_conductor_prop",lua_modcircprop); + lua_register(lua,"hi_delete_material",lua_delmatprop); + lua_register(lua,"hi_delete_bound_prop",lua_delboundprop); + lua_register(lua,"hi_delete_conductor",lua_delcircuitprop); + lua_register(lua,"hi_delete_point_prop",lua_delpointprop); + lua_register(lua,"hi_move_rotate",lua_move_rotate); + lua_register(lua,"hi_move_translate",lua_move_translate); + lua_register(lua,"hi_copy_rotate",lua_copy_rotate); + lua_register(lua,"hi_copy_translate",lua_copy_translate); + lua_register(lua,"hi_set_edit_mode",lua_seteditmode); + lua_register(lua,"hi_select_group",lua_selectgroup); + lua_register(lua,"hi_new_document",lua_newdocument); + lua_register(lua,"hi_save_bitmap",lua_savebitmap); + lua_register(lua,"hi_save_metafile",lua_saveWMF); + lua_register(lua,"hi_refresh_view",lua_updatewindow); + lua_register(lua,"hi_show_grid",lua_showgrid); + lua_register(lua,"hi_hide_grid",lua_hidegrid); + lua_register(lua,"hi_grid_snap",lua_gridsnap); + lua_register(lua,"hi_set_grid",lua_setgrid); + lua_register(lua,"hi_show_names",lua_shownames); + lua_register(lua,"hi_read_dxf",lua_readdxf); + lua_register(lua,"hi_save_dxf",lua_savedxf); + lua_register(lua,"hi_create_radius",lua_createradius); + + phdrawDoc=(ChdrawDoc *)this; +} + +int ChdrawDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + ChdrawDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".feh") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<3;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(ChdrawDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".feh") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + phdrawDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int ChdrawDoc::lua_exitpre(lua_State *L) +{ + CatchNullDocument(); + ((ChdrawDoc *)phdrawDoc)->OnCloseDocument( ); + + return 0; +} + +int ChdrawDoc::luaSaveDocument(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + int n; + n=lua_gettop(L); + + CString temp; + temp.Format("%s",lua_tostring(L,n)); + thisDoc->OnSaveDocument(temp); + thisDoc->SetPathName(temp); + + return 0; +} + +int ChdrawDoc::lua_readdxf(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + double DefTol; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + if (n==2) DefTol=lua_todouble(L,2); + else DefTol=0; + + result=thisDoc->ReadDXF(DocTitle,DefTol); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int ChdrawDoc::lua_savedxf(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + + result=thisDoc->WriteDXF(DocTitle); + if (result) theView->InvalidateRect(NULL); + + return result; +} + + +int ChdrawDoc::lua_prob_def(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + CString units,type; + int n; + n=lua_gettop(L); + + // error traps + int LengthUnits=-1; + int ProblemType=-1; + double Precision; + double MinAngle=-1; + CString PrevSoln=""; + double dT=0; + + units.Format("%s",lua_tostring(L,1)); + type.Format("%s",lua_tostring(L,2)); + Precision=lua_todouble(L,3); + if(n>3) thisDoc->Depth=lua_todouble(L,4); + if(n>4) MinAngle =lua_todouble(L,5); + if(units=="inches") LengthUnits=0; + if(units=="millimeters") LengthUnits=1; + if(units=="centimeters") LengthUnits=2; + if(units=="meters") LengthUnits=3; + if(units=="mills") LengthUnits=4; + if(units=="mils") LengthUnits=4; + if(units=="micrometers") LengthUnits=5; + if(type=="planar") ProblemType=0; + if(type=="axi") ProblemType=1; + if (n>5) PrevSoln.Format("%s",lua_tostring(L,6)); + if (n>6) dT=lua_todouble(L,7); + + // error detection and nice variable handling + + if (LengthUnits==-1) + { + CString msg; + msg.Format("Unknown length unit %s",units); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + thisDoc->LengthUnits=LengthUnits; + } + + if (ProblemType==-1) + { + CString msg; + msg.Format("Unknown problem type %s",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->ProblemType=ProblemType; + } + + + if (Precision < 1.e-16 || Precision >1.e-8) + { + CString msg; + msg.Format("Invalid Precision %lf",Precision); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->Precision=Precision; + } + + if ((MinAngle <=MINANGLE_MAX) && (MinAngle>=1.)) + { + thisDoc->MinAngle=MinAngle; + } + + if (thisDoc->Depth<=0) thisDoc->Depth=1; + + // Test to see if the previous solution and specified time step are consistent + if (PrevSoln.GetLength()==0) dT=0; + if (dT==0) PrevSoln=""; + + thisDoc->PrevSoln=PrevSoln; + thisDoc->dT=dT; + +// CString temp; +// temp.Format("%s",lua_tostring(L,n)); + + + + + return 0; +} + +int ChdrawDoc::lua_create_mesh(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + theView->lnuMakeMesh(); + + return 1; +} + +int ChdrawDoc::lua_smartmesh(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + if (lua_gettop(L)!=0) + { + int k = (int)lua_todouble(L,1); + if (k!=0) k=1; + thisDoc->SmartMesh=k; + } + + return 0; +} + +int ChdrawDoc::lua_show_mesh(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + theView->lnu_show_mesh(); + + return 0; +} + +int ChdrawDoc::lua_purge_mesh(lua_State *L) +{ + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + theView->lnu_purge_mesh(); + + return 0; +} + +int ChdrawDoc::lua_analyze(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + int bHide=0; + if ((n==0) && (theApp.GetMainWnd()->GetStyle() & WS_MINIMIZE)) bHide=1; + if (n>0) bHide=(int)lua_todouble(L,1); + if (bHide!=0) bHide=1; + + theView->lnu_analyze(bHide); + + return 0; +} + +int ChdrawDoc::lua_runpost(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + CString pn = thisDoc->GetPathName(); + + if (pn.GetLength()==0){ + CString msg; + msg.Format("No results to display"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".anh\""; + if (((CFemmApp *) AfxGetApp())->HOCheckIfAlreadyOpen(rootname)==FALSE) + AfxGetApp( )->OpenDocumentFile(rootname); + + return 0; +} + + +int ChdrawDoc::lua_addnode(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + double x,y,d; + + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddNode(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + +int ChdrawDoc::lua_addlabel(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + double x,y,d; + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddBlockLabel(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + + +int ChdrawDoc::lua_addline(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + CPoint mypntstart,mypntend; + + double sx,sy,ex,ey; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(ChdrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + flag=thisDoc->AddSegment(thisDoc->ClosestNode(sx,sy),thisDoc->ClosestNode(ex,ey)); + + if(flag==TRUE) + { + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int ChdrawDoc::lua_addarc(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + double sx,sy,ex,ey; + double angle,maxseg; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + angle=lua_todouble(L,5); + maxseg=lua_todouble(L,6); + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(ChdrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + CArcSegment asegm; + asegm.n0=thisDoc->ClosestNode(sx,sy); + asegm.n1=thisDoc->ClosestNode(ex,ey); + thisDoc->nodelist[asegm.n1].ToggleSelect(); + theView->DrawPSLG(); + + asegm.MaxSideLength=maxseg; + asegm.ArcLength=angle; + asegm.BoundaryMarker=""; + + flag=thisDoc->AddArcSegment(asegm); + flag=FALSE; + thisDoc->UnselectAll(); + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int ChdrawDoc::lua_selectnode(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->nodelist.GetSize()==0) return 0; + node=thisDoc->ClosestNode(mx,my); + thisDoc->nodelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[node].x); + lua_pushnumber(L,thisDoc->nodelist[node].y); + + return 2; +} + +int ChdrawDoc::lua_selectlabel(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->blocklist.GetSize()==0) return 0; + node=thisDoc->ClosestBlockLabel(mx,my); + thisDoc->blocklist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->blocklist[node].x); + lua_pushnumber(L,thisDoc->blocklist[node].y); + + return 2; +} + + +int ChdrawDoc::lua_selectsegment(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->linelist.GetSize()==0) return 0; + node=thisDoc->ClosestSegment(mx,my); + thisDoc->linelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].y); + + return 4; +} + + +int ChdrawDoc::lua_selectarcsegment(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->arclist.GetSize()==0) return 0; + node=thisDoc->ClosestArcSegment(mx,my); + thisDoc->arclist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].y); + + return 4; +} + +int ChdrawDoc::lua_clearselected(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + thisDoc->UnselectAll(); + return 0; +} + +int ChdrawDoc::lua_setnodeprop(lua_State *L) +{ + CatchNullDocument(); + CString nodeprop,inconductor; + int groupno; + + nodeprop.Format("%s",lua_tostring(L,1)); + groupno=(int) lua_todouble(L,2); + inconductor.Format("%s",lua_tostring(L,3)); + + if (groupno<0) + { + CString msg; + msg.Format("Invalid group no %d",groupno); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int i; + + // check to see how many (if any) nodes are selected. + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].IsSelected==TRUE) + { + thisDoc->nodelist[i].InGroup=groupno; + thisDoc->nodelist[i].BoundaryMarker=nodeprop; + thisDoc->nodelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int ChdrawDoc::lua_setblockprop(lua_State *L) +{ + CatchNullDocument(); + CString blocktype; + BOOL automesh; + double meshsize; + int group; + + int n=lua_gettop(L); + + blocktype=""; + automesh=1; + meshsize=0; + group=0; + + if (n>0) blocktype.Format("%s",lua_tostring(L,1)); + if (n>1) automesh=(int) lua_todouble(L,2); + if (n>2) meshsize=lua_todouble(L,3); + if (n>3) group=(int) lua_todouble(L,4); + + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].MaxArea=PI*meshsize*meshsize/4.; + thisDoc->blocklist[i].BlockType=blocktype; + thisDoc->blocklist[i].InGroup=group; + if(automesh==1) thisDoc->blocklist[i].MaxArea=0; + } + } + + return 0; +} + +int ChdrawDoc::lua_setsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString prop,inconductor; + double elesize; + int automesh,hide,group; + + prop.Format("%s",lua_tostring(L,1)); + elesize=lua_todouble(L,2); + automesh=(int) lua_todouble(L,3); + hide=(int) lua_todouble(L,4); + group=(int) lua_todouble(L,5); + inconductor.Format("%s",lua_tostring(L,6)); + + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + for(int i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].IsSelected==TRUE){ + if (automesh==1) thisDoc->linelist[i].MaxSideLength=-1; + else{ + if (elesize>0) + thisDoc->linelist[i].MaxSideLength=elesize; + else elesize=-1; + } + thisDoc->linelist[i].BoundaryMarker=prop; + thisDoc->linelist[i].Hidden=hide; + thisDoc->linelist[i].InGroup=group; + thisDoc->linelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int ChdrawDoc::lua_setarcsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString boundprop,inconductor; + double maxsegdeg; + int hide,group; + + maxsegdeg=lua_todouble(L,1); + if (maxsegdeg>10) maxsegdeg=10; + if (maxsegdeg<=0) maxsegdeg=1; + boundprop.Format("%s",lua_tostring(L,2)); + hide=(int) lua_todouble(L,3); + group=(int) lua_todouble(L,4); + inconductor.Format("%s",lua_tostring(L,5)); + + ChdrawDoc *thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].IsSelected==TRUE){ + thisDoc->arclist[i].BoundaryMarker=boundprop; + thisDoc->arclist[i].MaxSideLength=maxsegdeg; + thisDoc->arclist[i].Hidden=hide; + thisDoc->arclist[i].InGroup=group; + thisDoc->arclist[i].InConductor=inconductor; + } + } + + return 0; +} + +int ChdrawDoc::lua_deleteselectednodes(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + thisDoc->DeleteSelectedNodes(); + return 0; +} + +int ChdrawDoc::lua_deleteselectedlabels(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + thisDoc->DeleteSelectedBlockLabels(); + return 0; + +} + +int ChdrawDoc::lua_deleteselectedsegments(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + thisDoc->DeleteSelectedSegments(); + return 0; +} + +int ChdrawDoc::lua_deleteselectedarcsegments(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + thisDoc->DeleteSelectedArcSegments(); + return 0; +} + +int ChdrawDoc::lua_deleteselected(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + thisDoc->DeleteSelectedSegments(); + thisDoc->DeleteSelectedArcSegments(); + thisDoc->DeleteSelectedNodes(); + thisDoc->DeleteSelectedBlockLabels(); + + return 0; +} + +int ChdrawDoc::lua_newdocument(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + + thisDoc=(ChdrawDoc *)phdrawDoc; + thisDoc->OnNewDocument(); + thisDoc->SetPathName("Untitled",FALSE); + thisDoc->SetTitle("Untitled"); + return 0; +} + + +int ChdrawDoc::lua_zoomnatural(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomnatural(); + + return 0; +} + + +int ChdrawDoc::lua_zoomout(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + theView->lua_zoomout(); + + return 0; +} + +int ChdrawDoc::lua_zoomin(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomin(); + + return 0; +} + +int ChdrawDoc::lua_zoom(lua_State *L) +{ + CatchNullDocument(); + + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CRect r; + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int ChdrawDoc::lua_copy_rotate(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + // IF N=5 WE Have an edit action, if n=4 we dont ! + + int EditAction,copies; + + double x,y,angle; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + angle=lua_todouble(L,3); + copies=(int) lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for copy rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + thisDoc->RotateCopy(CComplex(x,y),angle,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + +int ChdrawDoc::lua_copy_translate(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + int EditAction, copies; + double x,y; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + copies=(int) lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for copy translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->TranslateCopy(x,y,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + + +int ChdrawDoc::lua_move_translate(lua_State *L) +{ + CatchNullDocument(); + + double x,y; + int EditAction; + + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + if (n==3) EditAction=(int) lua_todouble(L,3); + if (n==2) EditAction=theView->EditAction; + + if(n!=3 && n!=2) + { + CString msg; + msg.Format("Invalid number of parameters for move translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->TranslateMove(x,y,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + +int ChdrawDoc::lua_move_rotate(lua_State *L) +{ + CatchNullDocument(); + + double x,y,shiftangle; + int EditAction; + + int n; + n=lua_gettop(L); + + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + shiftangle=lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for move rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->RotateMove(CComplex(x,y),shiftangle,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + + +int ChdrawDoc::lua_mirror(lua_State *L) +{ + CatchNullDocument(); + double m_pax,m_pay,m_pbx,m_pby; + int EditAction; + + ChdrawDoc *thisDoc; + ChdrawView *theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + m_pax=lua_todouble(L,1); + m_pay=lua_todouble(L,2); + m_pbx=lua_todouble(L,3); + m_pby=lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for mirror"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->MirrorSelected(m_pax,m_pay,m_pbx,m_pby,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int ChdrawDoc::lua_scale(lua_State *L) +{ + CatchNullDocument(); + int EditAction; + double x,y,scalefactor; + + int n; + n=lua_gettop(L); + + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + scalefactor=lua_todouble(L,3); + EditAction=(int) lua_todouble(L,4); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for scale"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->ScaleMove(x,y,scalefactor,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int ChdrawDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + ChdrawDoc * thisDoc;ChdrawView * theView; + + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int iEditAction; + iEditAction=-1; + + if (EditAction=="nodes") iEditAction=0; + if (EditAction=="segments") iEditAction=1; + if (EditAction=="blocks") iEditAction=2; + if (EditAction=="arcsegments") iEditAction=3; + if (EditAction=="group") iEditAction=4; + + if(iEditAction==-1) + { + CString msg; + msg.Format("Invalid Edit Action %s",EditAction); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + theView->EditAction=iEditAction; + } + + + return 0; +} + +int ChdrawDoc::lua_selectgroup(lua_State *L) +{ + CatchNullDocument(); + int group,i; + group=(int) lua_todouble(L,1); + + if(group<0) + { + CString msg; + msg.Format("Invalid group %d",group); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + +// thisDoc->UnselectAll(); + + // select nodes + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].InGroup==group) + thisDoc->nodelist[i].IsSelected=TRUE; + } + + // select segments + for(i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].InGroup==group) + thisDoc->linelist[i].IsSelected=TRUE; + } + + // select arc segments + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].InGroup==group) + thisDoc->arclist[i].IsSelected=TRUE; + } + + // select blocks + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].InGroup==group) + thisDoc->blocklist[i].IsSelected=TRUE; + } + + + theView->EditAction=4; // set to group + + return 0; +} + + +int ChdrawDoc::lua_addmatprop(lua_State *L) +{ + CatchNullDocument(); + + CMaterialProp m; + int n=lua_gettop(L); + + if (n>0) m.BlockName.Format("%s",lua_tostring(L,1)); + if (n>1){ + m.Kx=lua_todouble(L,2); + m.Ky=m.Kx; + } + if(n>2) m.Ky=lua_todouble(L,3); + if(n>3) m.qv=lua_todouble(L,4); + if(n>4) m.Kt=lua_todouble(L,5); + + ((ChdrawDoc *)phdrawDoc)->blockproplist.Add(m); + + return 0; +} + + + +int ChdrawDoc::lua_modmatprop(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k,modprop; + + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->blockproplist[k].BlockName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->blockproplist[k].Kx=lua_todouble(L,3); + break; + case 2: + thisDoc->blockproplist[k].Ky=lua_todouble(L,3); + break; + case 3: + thisDoc->blockproplist[k].qv=lua_todouble(L,3); + break; + case 4: + thisDoc->blockproplist[k].Kt=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int ChdrawDoc::lua_addboundprop(lua_State *L) +{ + CatchNullDocument(); + + CBoundaryProp m; + int n=lua_gettop(L); + + if(n>0) m.BdryName.Format("%s",lua_tostring(L,1)); + if(n>1) m.BdryFormat=(int) lua_todouble(L,2); + if(n>2) m.Tset=lua_todouble(L,3); + if(n>3) m.qs=lua_todouble(L,4); + if(n>4) m.Tinf=lua_todouble(L,5); + if(n>5) m.h=lua_todouble(L,6); + if(n>6) m.beta=lua_todouble(L,7); + + ((ChdrawDoc *)phdrawDoc)->lineproplist.Add(m); + + return 0; +} + +int ChdrawDoc::lua_modboundprop(lua_State *L) +{ + CatchNullDocument(); + CString BdryName; + int k,modprop; + + ChdrawDoc * thisDoc=(ChdrawDoc *)phdrawDoc; + + // find the index of the boundary property to modify; + if (thisDoc->lineproplist.GetSize()==0) return TRUE; + BdryName.Format("%s",lua_tostring(L,1)); + for(k=0;klineproplist.GetSize();k++) + if(BdryName==thisDoc->lineproplist[k].BdryName) break; + + // get out of here if there's no matching material + if(k==thisDoc->lineproplist.GetSize()){ + MsgBox("Boundary \"%s\" not found",BdryName); + return 0; + } + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->lineproplist[k].BdryName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->lineproplist[k].BdryFormat=(int)lua_todouble(L,3); + break; + case 2: + thisDoc->lineproplist[k].Tset =lua_todouble(L,3); + break; + case 3: + thisDoc->lineproplist[k].qs =lua_todouble(L,3); + break; + case 4: + thisDoc->lineproplist[k].Tinf =lua_todouble(L,3); + break; + case 5: + thisDoc->lineproplist[k].h =lua_todouble(L,3); + break; + case 6: + thisDoc->lineproplist[k].beta = lua_todouble(L,3); + break; + + default: + break; + } + + return 0; +} + +int ChdrawDoc::lua_addpointprop(lua_State *L) +{ + CatchNullDocument(); + + CPointProp m; + int n=lua_gettop(L); + + if(n>0) m.PointName.Format("%s",lua_tostring(L,1)); + if(n>1) m.T=lua_todouble(L,2); + if(n>2) m.qp=lua_todouble(L,3); + + ((ChdrawDoc *)phdrawDoc)->nodeproplist.Add(m); + + return 0; +} + +int ChdrawDoc::lua_modpointprop(lua_State *L) +{ + CatchNullDocument(); + CString PointName; + int k,modprop; + + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + + // find the index of the material to modify; + if (thisDoc->nodeproplist.GetSize()==0) return TRUE; + PointName.Format("%s",lua_tostring(L,1)); + for(k=0;knodeproplist.GetSize();k++) + if(PointName==thisDoc->nodeproplist[k].PointName) break; + + // get out of here if there's no matching material + if(k==thisDoc->nodeproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->nodeproplist[k].PointName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->nodeproplist[k].T=lua_todouble(L,3); + break; + case 2: + thisDoc->nodeproplist[k].qp=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int ChdrawDoc::lua_addcircuitprop(lua_State *L) +{ + CatchNullDocument(); + + CCircuit m; + int n=lua_gettop(L); + + if(n>0) m.CircName=lua_tostring(L,1); + if(n>1) m.T=lua_todouble(L,2); + if(n>2) m.q=lua_todouble(L,3); + if(n>3) m.CircType=(int) lua_todouble(L,4); + + ((ChdrawDoc *)phdrawDoc)->circproplist.Add(m); + + return 0; +} + +int ChdrawDoc::lua_modcircprop(lua_State *L) +{ + CatchNullDocument(); + CString CircName; + int k,modprop; + + ChdrawDoc * thisDoc=(ChdrawDoc *)phdrawDoc; + + // find the index of the material to modify; + if (thisDoc->circproplist.GetSize()==0) return TRUE; + CircName.Format("%s",lua_tostring(L,1)); + for(k=0;kcircproplist.GetSize();k++) + if(CircName==thisDoc->circproplist[k].CircName) break; + + // get out of here if there's no matching circuit + if(k==thisDoc->circproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->circproplist[k].CircName.Format("%s",lua_tostring(L,3)); + break; + case 3: + thisDoc->circproplist[k].CircType=(int) lua_todouble(L,3); + break; + case 1: + thisDoc->circproplist[k].T=lua_todouble(L,3); + break; + case 2: + thisDoc->circproplist[k].q=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int ChdrawDoc::lua_delcircuitprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + ChdrawDoc * thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;icircproplist.GetSize();i++) + { + if (thisDoc->circproplist[i].CircName==name) + thisDoc->circproplist.RemoveAt(i); + + } + + return 0; +} + +int ChdrawDoc::lua_delmatprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;iblockproplist.GetSize();i++) + { + if (thisDoc->blockproplist[i].BlockName==name) + thisDoc->blockproplist.RemoveAt(i); + + } + + return 0; +} + + +int ChdrawDoc::lua_delboundprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;ilineproplist.GetSize();i++) + { + if (thisDoc->lineproplist[i].BdryName==name) + thisDoc->lineproplist.RemoveAt(i); + } + + + return 0; +} + +int ChdrawDoc::lua_delpointprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + ChdrawDoc *thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;inodeproplist.GetSize();i++) + { + if (thisDoc->nodeproplist[i].PointName==name) + thisDoc->nodeproplist.RemoveAt(i); + } + + return 0; +} + +int ChdrawDoc::lua_updatewindow(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CDC tempDC; + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // force redraw + theView->OnDraw(pDC); + + return 0; +} + + +int ChdrawDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + return 0; +} + + +PBITMAPINFO ChdrawDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy1"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits != 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void ChdrawDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy2"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy3"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy4"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy5"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy6"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy7"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy8"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + + +int ChdrawDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int ChdrawDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int ChdrawDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int ChdrawDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int ChdrawDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->InvalidateRect(NULL); + + return 0; +} + +int ChdrawDoc::lua_shownames(lua_State * L) +{ + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +void ChdrawView::lnuMakeMesh() +{ + OnMakeMesh(); +} + +void ChdrawView::lnu_purge_mesh() +{ + OnPurgemesh(); +} + +void ChdrawView::lnu_show_mesh() +{ + OnShowMesh(); +} + +void ChdrawView::lnu_analyze(int bShow) +{ + if (bShow>0) bLinehook=HiddenLua; + else bLinehook=NormalLua; + OnMenuAnalyze(); +} + +void ChdrawView::lua_zoomnatural() +{ + OnZoomNatural(); +} + +void ChdrawView::lua_zoomout() +{ + OnZoomOut(); +} + +void ChdrawView::lua_zoomin() +{ + OnZoomIn(); +} + +int ChdrawDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int ChdrawDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int ChdrawDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int ChdrawDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int ChdrawDoc::lua_defineouterspace(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + int n=lua_gettop(L); + if (n!=3) return 0; + + thisDoc->extZo = fabs(lua_todouble(L,1)); + thisDoc->extRo = fabs(lua_todouble(L,2)); + thisDoc->extRi = fabs(lua_todouble(L,3)); + + if((thisDoc->extRo==0) || (thisDoc->extRi==0)) + { + thisDoc->extZo = 0; + thisDoc->extRo = 0; + thisDoc->extRi = 0; + } + + return 0; +} + +int ChdrawDoc::lua_attachouterspace(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=TRUE; + + return 0; +} + +int ChdrawDoc::lua_detachouterspace(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=FALSE; + + return 0; +} + +int ChdrawDoc::lua_createradius(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n!=3) return 0; + + double x,y,r; + int k; + + x = lua_todouble(L,1); + y = lua_todouble(L,2); + r = fabs(lua_todouble(L,3)); + + if ((k=thisDoc->ClosestNode(x,y))<0) return 0; // catch case where no nodes have been drawn yet; + + if (thisDoc->CanCreateRadius(k)==FALSE) + { + CString msg; + msg.Format("The specified point is not suitable for conversion into a radius"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + if (thisDoc->CreateRadius(k,r)) + { + theView->InvalidateRect(NULL); + theView->MeshUpToDate=FALSE; + } + else{ + CString msg; + msg.Format("Could not make a radius of the prescribed dimension"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + return 0; +} + +int ChdrawDoc::lua_addtkpoint(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k; + + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return 0; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return 0; + + // now, add the tkpoint for the specified material; + thisDoc->blockproplist[k].Kn[thisDoc->blockproplist[k].npts]= + lua_todouble(L,2)+I*lua_todouble(L,3); + thisDoc->blockproplist[k].npts++; + + return 0; +} + +int ChdrawDoc::lua_cleartkpoints(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k; + + ChdrawDoc * thisDoc; + ChdrawView * theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return 0; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return 0; + + // now, zap the T-k points for the specified material; + thisDoc->blockproplist[k].npts=0; + + return 0; +} + +int ChdrawDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + + +int ChdrawDoc::lua_setgroup(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + int grp,i; + + int n=lua_gettop(L); + + if (n>0) grp =(int) lua_todouble(L,1); + else return 0; + + for(i=0;inodelist.GetSize();i++) + if(thisDoc->nodelist[i].IsSelected==TRUE) + thisDoc->nodelist[i].InGroup=grp; + + for(i=0;ilinelist.GetSize();i++) + if(thisDoc->linelist[i].IsSelected==TRUE) + thisDoc->linelist[i].InGroup=grp; + + for(i=0;iarclist.GetSize();i++) + if(thisDoc->arclist[i].IsSelected==TRUE) + thisDoc->arclist[i].InGroup=grp; + + for(i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].InGroup=grp; + + thisDoc->UnselectAll(); + + return 0; +} + +int ChdrawDoc::lua_getmaterial(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + CString matname; + int n=lua_gettop(L); + + if (n>0) matname=lua_tostring(L,1); + else return 0; + + CString LibName=thisDoc->BinDir+"heatlib.dat"; + + FILE *fp; + int i,j,k; + char s[1024],q[1024]; + char *v; + + CMaterialProp MProp; + + if ((fp=fopen(LibName,"rt"))==NULL){ + CString msg; + msg.Format("Couldn't open %s",LibName); + lua_error(L,msg.GetBuffer(1)); + return FALSE; + } + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + if (sscanf(s,"%s",q)==EOF) 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){ + if (MProp.BlockName==matname){ + thisDoc->blockproplist.Add(MProp); + fclose(fp); + return 0; + } + q[0]=NULL; + } + } + + fclose(fp); + + CString msg; + msg.Format("Couldn't load \"%s\" from the materials library",matname); + lua_error(L,msg.GetBuffer(1)); + return FALSE; +} + +int ChdrawDoc::lua_attachdefault(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0,j=0;iblocklist.GetSize();i++) + { + if ((thisDoc->blocklist[i].IsSelected==TRUE) && (j==0)) + { + thisDoc->blocklist[i].IsDefault=2; + j++; + } + else thisDoc->blocklist[i].IsDefault=FALSE; + } + + return 0; +} + +int ChdrawDoc::lua_detachdefault(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsDefault=FALSE; + + return 0; +} + +int ChdrawDoc::lua_getprobleminfo(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + thisDoc=(ChdrawDoc *)phdrawDoc; + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Depth); + switch (thisDoc->LengthUnits) + { + case 1: // mm + lua_pushnumber(L,0.001); + break; + case 2: // cm + lua_pushnumber(L,0.01); + break; + case 3: // m + lua_pushnumber(L,1.0); + break; + case 4: // mils + lua_pushnumber(L,2.54e-05); + break; + case 5: // um + lua_pushnumber(L,1.0e-06); + break; + default:// inches + lua_pushnumber(L,0.0254); + break; + } + return 3; +} + +int ChdrawDoc::lua_getboundingbox(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc *thisDoc; + ChdrawView *theView; + thisDoc=(ChdrawDoc *)phdrawDoc; + + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChdrawView *)thisDoc->GetNextView(pos); + + double x[2],y[2]; + if (theView->GetBoundingBox(x,y)) + { + lua_pushnumber(L,x[0]); + lua_pushnumber(L,x[1]); + lua_pushnumber(L,y[0]); + lua_pushnumber(L,y[1]); + return 4; + } + else return 0; +} + +int ChdrawDoc::lua_selectcircle(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * pDoc; + ChdrawView * theView; + + pDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(ChdrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double R; + CComplex c,q; + + n=lua_gettop(L); + if (n<3) return 0; + c=lua_tonumber(L,1)+I*lua_tonumber(L,2); + R=lua_todouble(L,3); + if (n>3) EditAction=(int) lua_todouble(L,4); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} + +int ChdrawDoc::lua_selectrectangle(lua_State *L) +{ + CatchNullDocument(); + ChdrawDoc * pDoc; + ChdrawView * theView; + + pDoc=(ChdrawDoc *)phdrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(ChdrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double mx,my,wzx,wzy,x,y,z; + + n=lua_gettop(L); + if (n<4) return 0; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + wzx=lua_todouble(L,3); + wzy=lua_todouble(L,4); + if (n>4) EditAction=(int) lua_todouble(L,5); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} \ No newline at end of file diff --git a/femm/HD_PREF.CPP b/femm/HD_PREF.CPP new file mode 100644 index 0000000..4b9398d --- /dev/null +++ b/femm/HD_PREF.CPP @@ -0,0 +1,413 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "hd_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define SelColor clist[0] +#define MeshColor clist[1] +#define BlockColor clist[2] +#define LineColor clist[3] +#define GridColor clist[4] +#define NodeColor clist[5] +#define BackColor clist[6] +#define NameColor clist[7] + +///////////////////////////////////////////////////////////////////////////// +// hdCPref dialog + + +hdCPref::hdCPref(CWnd* pParent /*=NULL*/) + : CDialog(hdCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCPref) + m_d_gridsize = 0.25; + m_d_pixels = 100.0; + m_d_prec = 1.e-8; + m_d_minangle = DEFAULT_MINIMUM_ANGLE; + m_d_depth = 1.0; + m_d_showgrid = TRUE; + m_d_snapgrid = FALSE; + m_d_showorigin = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + s_action=0; + s_coord=0; + s_length=0; + s_type=0; + + clist=(COLORREF *)calloc(16,sizeof(COLORREF)); + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; +} + +hdCPref::~hdCPref() +{ + free(clist); +} + +void hdCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCPref) + DDX_Control(pDX, IDC_HD_DCOLOR, m_d_color); + DDX_Control(pDX, IDC_HD_DTYPE, m_d_type); + DDX_Control(pDX, IDC_HD_DLENGTH, m_d_length); + DDX_Control(pDX, IDC_HD_DCOORD, m_d_coord); + DDX_Control(pDX, IDC_HD_DACTION, m_d_action); + DDX_Text(pDX, IDC_HD_DGRIDSIZE, m_d_gridsize); + DDX_Text(pDX, IDC_HD_DDEPTH, m_d_depth); + DDX_Text(pDX, IDC_HD_DPIXELS, m_d_pixels); + DDX_Text(pDX, IDC_HD_DPREC, m_d_prec); + DDV_MinMaxDouble(pDX, m_d_prec, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_HD_DMINANGLE, m_d_minangle); + DDV_MinMaxDouble(pDX, m_d_minangle, 1., MINANGLE_MAX); + DDX_Check(pDX, IDC_HD_DSHOWGRID, m_d_showgrid); + DDX_Check(pDX, IDC_HD_DSNAPGRID, m_d_snapgrid); + DDX_Check(pDX, IDC_HD_SHOW_ORIGIN, m_d_showorigin); + DDX_Check(pDX, IDC_HD_SHOW_NAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_DGRIDSIZE, m_IDC_d_gridsize); + DDX_Control(pDX, IDC_HD_DPIXELS, m_IDC_d_pixels); + DDX_Control(pDX, IDC_HD_DPREC, m_IDC_d_prec); + DDX_Control(pDX, IDC_HD_DDEPTH, m_IDC_d_depth); +} + + +BEGIN_MESSAGE_MAP(hdCPref, CDialog) + //{{AFX_MSG_MAP(hdCPref) + ON_BN_CLICKED(IDC_HD_MODBTN, OnModifyButton) + ON_BN_CLICKED(IDC_HD_RESTORE, OnRestoreColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCPref message handlers + +void hdCPref::OnModifyButton() +{ + CColorDialog dlg; + int i; + + UpdateData(); + i=m_d_color.GetCurSel(); + + dlg.m_cc.lpCustColors=clist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + else{ + } + +} + +BOOL hdCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_action.SetCurSel(s_action); + m_d_coord.SetCurSel(s_coord); + m_d_length.SetCurSel(s_length); + m_d_type.SetCurSel(s_type); + m_d_color.SetCurSel(0); + + UpdateData(FALSE); + + return TRUE; +} + + +void hdCPref::OnOK() +{ + UpdateData(); + + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + CDialog::OnOK(); +} + +void hdCPref::OnRestoreColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; + } +} + +BOOL hdCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +char* StripKey(char *c); + +void hdCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "hdraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_prec); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_minangle); + q[0]=NULL; + } + + if( _strnicmp(q,"",7)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_depth); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_coord); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_length); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_type); + q[0]=NULL; + } + + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_pixels); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_shownames); + q[0]=NULL; + } + } + fclose(fp); + } +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void hdCPref::WritePrefs() +{ + FILE *fp; + CString fname; + + UpdateData(); + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + fname=((CFemmApp *)AfxGetApp())->GetExecutablePath()+"hdraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",s_action); + fprintf(fp," = %g\n",m_d_pixels); + fprintf(fp," = %g\n",m_d_gridsize); + fprintf(fp," = %i\n",m_d_showgrid); + fprintf(fp," = %i\n",m_d_snapgrid); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_showorigin); + fprintf(fp," = %i\n",s_type); + fprintf(fp," = %i\n",s_length); + fprintf(fp," = %g\n",m_d_prec); + fprintf(fp," = %g\n",m_d_minangle); + fprintf(fp," = %g\n",m_d_depth); + fprintf(fp," = %i\n",s_coord); + + fclose(fp); + } +} diff --git a/femm/HD_PREF.H b/femm/HD_PREF.H new file mode 100644 index 0000000..09fbb26 --- /dev/null +++ b/femm/HD_PREF.H @@ -0,0 +1,68 @@ +// hd_Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hdCPref dialog + +class hdCPref : public CDialog +{ +// Construction +public: + + hdCPref(CWnd* pParent = NULL); // standard constructor + ~hdCPref(); + + COLORREF *clist; + int s_action; + int s_coord; + int s_length; + int s_type; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(hdCPref) + enum { IDD = IDD_HD_PREF }; + CComboBox m_d_color; + CComboBox m_d_type; + CComboBox m_d_length; + CComboBox m_d_coord; + CComboBox m_d_action; + double m_d_gridsize; + double m_d_pixels; + double m_d_prec; + double m_d_minangle; + double m_d_depth; + BOOL m_d_showgrid; + BOOL m_d_snapgrid; + BOOL m_d_showorigin; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCPref) + afx_msg void OnModifyButton(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnRestoreColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_d_gridsize, m_IDC_d_depth; + CLuaEdit m_IDC_d_pixels, m_IDC_d_prec, m_IDC_d_minangle; + +}; diff --git a/femm/HV_PREF.CPP b/femm/HV_PREF.CPP new file mode 100644 index 0000000..b767da6 --- /dev/null +++ b/femm/HV_PREF.CPP @@ -0,0 +1,982 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + #define SelColor clist[0] + #define BackColor clist[1] + #define MeshColor clist[2] + #define BlockColor clist[3] + #define LineColor clist[4] + #define GridColor clist[5] + #define NodeColor clist[6] + #define RegionColor clist[7] + #define TextColor clist[8] + #define RealFluxLineColor clist[9] + #define NameColor clist[10] + #define MaskLineColor clist[11] + #define VectorColor clist[12] + #define Color00 clist[13] + #define Color01 clist[14] + #define Color02 clist[15] + #define Color03 clist[16] + #define Color04 clist[17] + #define Color05 clist[18] + #define Color06 clist[19] + #define Color07 clist[20] + #define Color08 clist[21] + #define Color09 clist[22] + #define Color10 clist[23] + #define Color11 clist[24] + #define Color12 clist[25] + #define Color13 clist[26] + #define Color14 clist[27] + #define Color15 clist[28] + #define Color16 clist[29] + #define Color17 clist[30] + #define Color18 clist[31] + #define Color19 clist[32] + #define Grey00 clist[33] + #define Grey01 clist[34] + #define Grey02 clist[35] + #define Grey03 clist[36] + #define Grey04 clist[37] + #define Grey05 clist[38] + #define Grey06 clist[39] + #define Grey07 clist[40] + #define Grey08 clist[41] + #define Grey09 clist[42] + #define Grey10 clist[43] + #define Grey11 clist[44] + #define Grey12 clist[45] + #define Grey13 clist[46] + #define Grey14 clist[47] + #define Grey15 clist[48] + #define Grey16 clist[49] + #define Grey17 clist[50] + #define Grey18 clist[51] + #define Grey19 clist[52] + + + +///////////////////////////////////////////////////////////////////////////// +// hvCPref dialog + + +hvCPref::hvCPref(CWnd* pParent /*=NULL*/) + : CDialog(hvCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCPref) + m_d_GreyContours = FALSE; + m_d_LegendFlag = TRUE; + m_d_NumContours = 19; + m_d_ResetOnReload = FALSE; + m_d_GridFlag = FALSE; + m_d_ShowAr = FALSE; + m_d_PtsFlag = TRUE; + m_d_MeshFlag = FALSE; + m_d_SnapFlag = FALSE; + m_d_Smooth = TRUE; + m_d_LineIntegralPoints = 400; + m_d_PlotPoints = 1500; + m_d_ShowMask = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + m_d_DensityPlot=1; + m_d_EditAction=0; + m_d_VectorPlot=0; + + clist=(COLORREF *)calloc(64,sizeof(COLORREF)); + int i=0; + + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + +} + +hvCPref::~hvCPref() +{ + free(clist); +} + +void hvCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCPref) + DDX_Control(pDX, IDC_HV_VECTORPLOT, m_d_vplotlist); + DDX_Control(pDX, IDC_HV_DENSITYPLOT, m_d_dplotlist); + DDX_Control(pDX, IDC_HV_EDITACTION, m_d_editlist); + DDX_Control(pDX, IDC_HV_COLORS, m_d_color); + DDX_Check(pDX, IDC_HV_GREY, m_d_GreyContours); + DDX_Check(pDX, IDC_HV_LEGEND, m_d_LegendFlag); + DDX_Text(pDX, IDC_HV_NCONT, m_d_NumContours); + DDV_MinMaxInt(pDX, m_d_NumContours, 4, 999); + DDX_Check(pDX, IDC_HV_ONRELOAD, m_d_ResetOnReload); + DDX_Check(pDX, IDC_HV_SHOWGRID, m_d_GridFlag); + DDX_Check(pDX, IDC_HV_SHOWREAL, m_d_ShowAr); + DDX_Check(pDX, IDC_HV_SHOWPTS, m_d_PtsFlag); + DDX_Check(pDX, IDC_HV_SHOWMESH, m_d_MeshFlag); + DDX_Check(pDX, IDC_HV_SNAPGRID, m_d_SnapFlag); + DDX_Check(pDX, IDC_HV_SMOOTHING, m_d_Smooth); + DDX_Text(pDX, IDC_HV_LIPOINTS, m_d_LineIntegralPoints); + DDV_MinMaxInt(pDX, m_d_LineIntegralPoints, 10, 100000); + DDX_Text(pDX, IDC_HV_PLOTPOINTS, m_d_PlotPoints); + DDV_MinMaxInt(pDX, m_d_PlotPoints, 10, 100000); + DDX_Check(pDX, IDC_HV_SHOWMASK, m_d_ShowMask); + DDX_Check(pDX, IDC_HV_SHOWNAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HV_NCONT, m_IDC_d_NumContours); + DDX_Control(pDX, IDC_HV_LIPOINTS, m_IDC_d_LineIntegralPoints); + DDX_Control(pDX, IDC_HV_PLOTPOINTS, m_IDC_d_PlotPoints); + + +} + + +BEGIN_MESSAGE_MAP(hvCPref, CDialog) + //{{AFX_MSG_MAP(hvCPref) + ON_BN_CLICKED(IDC_HV_MODBTN, OnModBtn) + ON_BN_CLICKED(IDC_HV_RESET, OnResetColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCPref message handlers + +void hvCPref::OnModBtn() +{ + CColorDialog dlg; + COLORREF cclist[16]; + int i,k; + + UpdateData(); + i=m_d_color.GetCurSel(); + for(k=0;k<16;k++) cclist[k]=RGB(190,190,190); + + if(i<11) for(k=0;k<11;k++) cclist[k]=clist[k]; + if((i>10)&&(i<23)) for(k=11;k<23;k++) cclist[k-11]=clist[k]; + if(i>22) for(k=23;k<35;k++) cclist[k-23]=clist[k]; + + dlg.m_cc.lpCustColors=cclist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + +} + +BOOL hvCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_color.SetCurSel(0); + m_d_dplotlist.SetCurSel(m_d_DensityPlot); + m_d_editlist.SetCurSel(m_d_EditAction); + m_d_vplotlist.SetCurSel(m_d_VectorPlot); + + UpdateData(FALSE); + + return TRUE; +} + +void hvCPref::OnResetColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + int i=0; + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + } +} + +BOOL hvCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void hvCPref::WritePrefs() +{ + UpdateData(); + m_d_DensityPlot=m_d_dplotlist.GetCurSel(); + m_d_EditAction=m_d_editlist.GetCurSel(); + m_d_VectorPlot=m_d_vplotlist.GetCurSel(); + + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "hview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorColor", VectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",m_d_EditAction); + fprintf(fp," = %i\n",m_d_DensityPlot); + fprintf(fp," = %i\n",m_d_VectorPlot); + fprintf(fp," = %i\n",m_d_GridFlag); + fprintf(fp," = %i\n",m_d_SnapFlag); + fprintf(fp," = %i\n",m_d_MeshFlag); + fprintf(fp," = %i\n",m_d_LegendFlag); + fprintf(fp," = %i\n",m_d_NumContours); + fprintf(fp," = %i\n",m_d_ShowAr); + fprintf(fp," = %i\n",m_d_ShowMask); + fprintf(fp," = %i\n",m_d_GreyContours); + fprintf(fp," = %i\n",m_d_PtsFlag); + fprintf(fp," = %i\n",m_d_ResetOnReload); + fprintf(fp," = %i\n",m_d_Smooth); + fprintf(fp," = %i\n",m_d_PlotPoints); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_LineIntegralPoints); + + fclose(fp); + } +} + +char* StripKey(char *c); + +void hvCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "hview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LineIntegralPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + VectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + +} \ No newline at end of file diff --git a/femm/HV_PREF.H b/femm/HV_PREF.H new file mode 100644 index 0000000..0bf6d30 --- /dev/null +++ b/femm/HV_PREF.H @@ -0,0 +1,68 @@ +// Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCPref dialog + +class hvCPref : public CDialog +{ +// Construction +public: + hvCPref(CWnd* pParent = NULL); // standard constructor + ~hvCPref(); + + COLORREF *clist; + int m_d_EditAction; + int m_d_DensityPlot; + int m_d_VectorPlot; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(hvCPref) + enum { IDD = IDD_HV_PREF }; + CComboBox m_d_vplotlist; + CComboBox m_d_dplotlist; + CComboBox m_d_editlist; + CComboBox m_d_color; + BOOL m_d_GreyContours; + BOOL m_d_LegendFlag; + int m_d_NumContours; + BOOL m_d_ResetOnReload; + BOOL m_d_GridFlag; + BOOL m_d_ShowAr; + BOOL m_d_PtsFlag; + BOOL m_d_MeshFlag; + BOOL m_d_SnapFlag; + BOOL m_d_Smooth; + int m_d_LineIntegralPoints; + int m_d_PlotPoints; + BOOL m_d_ShowMask; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCPref) + afx_msg void OnModBtn(); + virtual BOOL OnInitDialog(); + afx_msg void OnResetColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_d_NumContours, m_IDC_d_LineIntegralPoints; + CLuaEdit m_IDC_d_PlotPoints; + +}; diff --git a/femm/KCurve.cpp b/femm/KCurve.cpp new file mode 100644 index 0000000..967cc04 --- /dev/null +++ b/femm/KCurve.cpp @@ -0,0 +1,329 @@ +// TKData.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "KCurve.h" +#include "BHPlot.h" +#include "TKDatafile.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTKData dialog + + +CTKData::CTKData(CWnd* pParent /*=NULL*/) + : CDialog(CTKData::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTKData) + m_Bdata = _T(""); + m_Hdata = _T(""); + //}}AFX_DATA_INIT + + logplot=FALSE; +} + + +void CTKData::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTKData) + DDX_Text(pDX, IDC_BDATA, m_Bdata); + DDX_Text(pDX, IDC_HDATA, m_Hdata); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BDATA, m_IDC_BDATA); + DDX_Control(pDX, IDC_HDATA, m_IDC_HDATA); +} + + +BEGIN_MESSAGE_MAP(CTKData, CDialog) + //{{AFX_MSG_MAP(CTKData) + ON_BN_CLICKED(IDC_PLOT_BHCURVE, OnPlotBHcurve) + ON_BN_CLICKED(IDC_LOGPLOT_BHCURVE, OnLogPlotBHcurve) + ON_BN_CLICKED(IDC_READ_BHCURVE, OnReadBhcurve) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTKData message handlers + +void CTKData::StripTKData() +{ + int k; + char *buff,*nptr,*endptr; + double z; + + T.RemoveAll(); + K.RemoveAll(); + npts=0; + + if((m_Bdata.GetLength()==0) || (m_Hdata.GetLength()==0)) return; + + k=m_Bdata.GetLength()*2; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,m_Bdata); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; //catch special case + else nptr=endptr; + T.Add(z); + } + free(buff); + + k=m_Hdata.GetLength()*2; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,m_Hdata); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; + else nptr=endptr; + K.Add(z); + } + + npts=(int) T.GetSize(); + if ((int) K.GetSize()=T[npts-1]) return K[npts-1]; + + for(i=0,j=1;j=T[i]) && (t<=T[j])) + { + return (K[i]+(K[j]-K[i])*(t-T[i])/(T[j]-T[i])); + } + } + + return 0; +} + +void CTKData::OnPlotBHcurve() +{ + CBHPlot xyplot; + int i; + double t,dt; + BOOL logscale=logplot; + logplot=FALSE; + + UpdateData(); + StripTKData(); + + if (npts<2){ + MsgBox("Must have at least 2 pairs of data points"); + return; + } + + // copy raw B-H data for plotting in comparison to interpolated curve + xyplot.NumPts=npts; + xyplot.Pts=(CComplex *)calloc(npts,sizeof(CComplex)); + for(i=0;iGetExecutablePath(); + + // Actually evaluate all the points on the line... + if(xyplot.Create(101,2)==FALSE) return; + + dt=(T[npts-1]-T[0])/100.; + + for(i=0,t=T[0];i<=100;i++,t+=dt) + { + xyplot.M[i][0]=t; + xyplot.M[i][1]=GetK(t); + } + + sprintf(xyplot.lbls[0],"T, K"); + sprintf(xyplot.lbls[1],"k, W/(m*K)"); + + // Create the plot, send it to the clipboard, spawn viewer... + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + xyplot.MakePlot(&Meta,logscale); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + { + MsgBox("Couldn't SetClipboardData"); + } + CloseClipboard(); + + // fire up plot viewer; +// ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + + // in this case call the external program rather than + // displaying in the window. Since dialog is running modal, + // it obscures the plotted BH curve--this is an annoying kludge. + char CommandLine[MAX_PATH]; + sprintf(CommandLine,"%sfemmplot.exe", (const char *) ((CFemmApp *)AfxGetApp())->GetExecutablePath()); + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,0, NULL, NULL, &StartupInfo2, &ProcessInfo2); + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } +} + +void CTKData::OnReadBhcurve() +{ + // TODO: Add your control notification handler code here + + CFileDialog *fname_dia; + CString infile; + + fname_dia=new CFileDialog( + TRUE, + "dat | * ", + infile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Two column text data file (*.dat) | *.dat; *.DAT | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + infile=fname_dia->GetPathName(); + delete[] fname_dia; + + CTKDatafile dlg; + if(dlg.DoModal()==IDCANCEL) return; + + // read in data from text file; + m_Bdata.Empty(); + m_Hdata.Empty(); + + char s[1024]; + double t,k; + + FILE *fp=fopen(infile,"rt"); + if (fp==NULL){ + MsgBox("problem opening data file"); + return; + } + while(fgets(s,1024,fp)!=NULL) + { + if(dlg.TKOrder==0) sscanf(s,"%lf %lf",&t,&k); + else sscanf(s,"%lf %lf",&k,&t); + + switch (dlg.TUnits) + { + case 1: // Celcius to Kelvin + t+=273.15; + break; + case 2: // Fahrenheit to Kelvin + t=5.*(t+459.67)/9.; + break; + case 3: // Rankine to Kelvin + t=5.*t/9.; + break; + default: // Kelvin + t*=1.; + break; + } + + switch (dlg.KUnits) + { + case 1: // Btu/(ft*hr*F) to W/(m*K) + k*=1.73073466637139; + break; + case 2: // kcal/(m*hr*K) to W/(m*K) + k*=1.163; + break; + default: // W/(m*K) + k*=1.; + break; + } + + sprintf(s,"%f\r\n",t); m_Bdata += s; + sprintf(s,"%f\r\n",k); m_Hdata += s; + } + + SetDlgItemText(IDC_BDATA,m_Bdata); + SetDlgItemText(IDC_HDATA,m_Hdata); + + fclose(fp); +} + +BOOL CTKData::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // build string representation of the data out of numerical data + int i; + CString c; + + m_Bdata.Empty(); + m_Hdata.Empty(); + + for(i=0;i +#include "afxwin.h" + +class CTKData : public CDialog +{ +// Construction +public: + CTKData(CWnd* pParent = NULL); // standard constructor + CArray T; + CArray K; + int npts; + + BOOL logplot; + + void StripTKData(); + double GetK(double T); + void SortCurve(); + +// Dialog Data + //{{AFX_DATA(CTKData) + enum { IDD = IDD_KCURVE }; + CString m_Bdata; + CString m_Hdata; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTKData) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTKData) + afx_msg void OnPlotBHcurve(); + afx_msg void OnLogPlotBHcurve(); + afx_msg void OnReadBhcurve(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_BDATA; + CLuaEdit m_IDC_HDATA; +}; diff --git a/femm/KbdZoom.cpp b/femm/KbdZoom.cpp new file mode 100644 index 0000000..c94d602 --- /dev/null +++ b/femm/KbdZoom.cpp @@ -0,0 +1,53 @@ +// KbdZoom.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "KbdZoom.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKbdZoom dialog + + +CKbdZoom::CKbdZoom(CWnd* pParent /*=NULL*/) + : CDialog(CKbdZoom::IDD, pParent) +{ + //{{AFX_DATA_INIT(CKbdZoom) + m_scr_bottom = 0.0; + m_scr_left = 0.0; + m_scr_right = 0.0; + m_scr_top = 0.0; + //}}AFX_DATA_INIT +} + + +void CKbdZoom::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKbdZoom) + DDX_Text(pDX, IDC_SCRBOTTOM, m_scr_bottom); + DDX_Text(pDX, IDC_SCRLEFT, m_scr_left); + DDX_Text(pDX, IDC_SCRRIGHT, m_scr_right); + DDX_Text(pDX, IDC_SCRTOP, m_scr_top); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_SCRBOTTOM, m_IDC_scr_bottom); + DDX_Control(pDX, IDC_SCRLEFT, m_IDC_scr_left); + DDX_Control(pDX, IDC_SCRRIGHT, m_IDC_scr_right); + DDX_Control(pDX, IDC_SCRTOP, m_IDC_scr_top); +} + + +BEGIN_MESSAGE_MAP(CKbdZoom, CDialog) + //{{AFX_MSG_MAP(CKbdZoom) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKbdZoom message handlers diff --git a/femm/KbdZoom.h b/femm/KbdZoom.h new file mode 100644 index 0000000..16b9018 --- /dev/null +++ b/femm/KbdZoom.h @@ -0,0 +1,41 @@ +// KbdZoom.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKbdZoom dialog + +class CKbdZoom : public CDialog +{ +// Construction +public: + CKbdZoom(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CKbdZoom) + enum { IDD = IDD_KBDZOOM }; + double m_scr_bottom; + double m_scr_left; + double m_scr_right; + double m_scr_top; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKbdZoom) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKbdZoom) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_scr_bottom, m_IDC_scr_left; + CLuaEdit m_IDC_scr_right, m_IDC_scr_top; +}; diff --git a/femm/LIntDlg.cpp b/femm/LIntDlg.cpp new file mode 100644 index 0000000..e3f1440 --- /dev/null +++ b/femm/LIntDlg.cpp @@ -0,0 +1,59 @@ +// LIntDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "LIntDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLIntDlg dialog + + +CLIntDlg::CLIntDlg(CWnd* pParent /*=NULL*/) + : CDialog(CLIntDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLIntDlg) + //}}AFX_DATA_INIT +} + + +void CLIntDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLIntDlg) + DDX_Control(pDX, IDC_LINTTYPE, m_inttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLIntDlg, CDialog) + //{{AFX_MSG_MAP(CLIntDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLIntDlg message handlers + +BOOL CLIntDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_inttype.SetCurSel(0); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CLIntDlg::OnOK() +{ + // TODO: Add extra validation here + linttype=m_inttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/LIntDlg.h b/femm/LIntDlg.h new file mode 100644 index 0000000..45d5200 --- /dev/null +++ b/femm/LIntDlg.h @@ -0,0 +1,38 @@ +// LIntDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLIntDlg dialog + +class CLIntDlg : public CDialog +{ +// Construction +public: + CLIntDlg(CWnd* pParent = NULL); // standard constructor + + int linttype; + +// Dialog Data + //{{AFX_DATA(CLIntDlg) + enum { IDD = IDD_LINEINT }; + CComboBox m_inttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLIntDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLIntDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/LUA.H b/femm/LUA.H new file mode 100644 index 0000000..6a841e1 --- /dev/null +++ b/femm/LUA.H @@ -0,0 +1,249 @@ +/* +** $Id: lua.h,v 1.79 2000/10/31 12:44:07 roberto Exp $ +** Lua - An Extensible Extension Language +** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil +** e-mail: lua@tecgraf.puc-rio.br +** www: http://www.tecgraf.puc-rio.br/lua/ +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include "complex.h" + +/* definition of `size_t' */ +#include + + +/* mark for all API functions */ +#ifndef LUA_API +#define LUA_API extern +#endif + + +#define LUA_VERSION "Lua 4.0" +#define LUA_COPYRIGHT "Copyright (C) 1994-2000 TeCGraf, PUC-Rio" +#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" + + +/* name of global variable with error handler */ +#define LUA_ERRORMESSAGE "_ERRORMESSAGE" + + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) +#define LUA_REFREGISTRY 0 + +/* pre-defined tags */ +#define LUA_ANYTAG (-1) +#define LUA_NOTAG (-2) + + +/* option for multiple returns in lua_call */ +#define LUA_MULTRET (-1) + + +/* minimum stack available for a C function */ +#define LUA_MINSTACK 20 + + +/* error codes for lua_do* */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + +/* +** types returned by `lua_type' +*/ +#define LUA_TNONE (-1) + +#define LUA_TUSERDATA 0 +#define LUA_TNIL 1 +#define LUA_TNUMBER 2 +#define LUA_TSTRING 3 +#define LUA_TTABLE 4 +#define LUA_TFUNCTION 5 + + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (int stacksize); +LUA_API void lua_close (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int index); +LUA_API void lua_pushvalue (lua_State *L, int index); +LUA_API void lua_remove (lua_State *L, int index); +LUA_API void lua_insert (lua_State *L, int index); +LUA_API int lua_stackspace (lua_State *L); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_type (lua_State *L, int index); +LUA_API const char *lua_typename (lua_State *L, int t); +LUA_API int lua_isnumber (lua_State *L, int index); +LUA_API int lua_isstring (lua_State *L, int index); +LUA_API int lua_iscfunction (lua_State *L, int index); +LUA_API int lua_tag (lua_State *L, int index); + +LUA_API int lua_equal (lua_State *L, int index1, int index2); +LUA_API int lua_lessthan (lua_State *L, int index1, int index2); + +LUA_API CComplex lua_tonumber (lua_State *L, int index); +LUA_API const char *lua_tostring (lua_State *L, int index); +LUA_API size_t lua_strlen (lua_State *L, int index); +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); +LUA_API void *lua_touserdata (lua_State *L, int index); +LUA_API const void *lua_topointer (lua_State *L, int index); + + +/* +** push functions (C -> stack) +*/ +LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushnumber (lua_State *L, CComplex n); +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); +LUA_API void lua_pushstring (lua_State *L, const char *s); +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushusertag (lua_State *L, void *u, int tag); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_getglobal (lua_State *L, const char *name); +LUA_API void lua_gettable (lua_State *L, int index); +LUA_API void lua_rawget (lua_State *L, int index); +LUA_API void lua_rawgeti (lua_State *L, int index, int n); +LUA_API void lua_getglobals (lua_State *L); +LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_getref (lua_State *L, int ref); +LUA_API void lua_newtable (lua_State *L); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_setglobal (lua_State *L, const char *name); +LUA_API void lua_settable (lua_State *L, int index); +LUA_API void lua_rawset (lua_State *L, int index); +LUA_API void lua_rawseti (lua_State *L, int index, int n); +LUA_API void lua_setglobals (lua_State *L); +LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_ref (lua_State *L, int lock); + + +/* +** "do" functions (run Lua code) +*/ +LUA_API int lua_call (lua_State *L, int nargs, int nresults); +LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults); +LUA_API int lua_dofile (lua_State *L, const char *filename); +LUA_API int lua_dostring (lua_State *L, const char *str); +LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name); + +/* +** Garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ +LUA_API int lua_newtag (lua_State *L); +LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); +LUA_API void lua_settag (lua_State *L, int tag); + +LUA_API void lua_error (lua_State *L, const char *s); + +LUA_API void lua_unref (lua_State *L, int ref); + +LUA_API int lua_next (lua_State *L, int index); +LUA_API int lua_getn (lua_State *L, int index); + +LUA_API void lua_concat (lua_State *L, int n); + +LUA_API void *lua_newuserdata (lua_State *L, size_t size); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) +#define lua_pushuserdata(L,u) lua_pushusertag(L, u, 0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) +#define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) + +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) + +#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) + +#endif + + + +/****************************************************************************** +* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, without written agreement and without license +* or royalty fees, to use, copy, modify, and distribute this software and its +* documentation for any purpose, including commercial applications, subject to +* the following conditions: +* +* - The above copyright notice and this permission notice shall appear in all +* copies or substantial portions of this software. +* +* - The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software in a +* product, an acknowledgment in the product documentation would be greatly +* appreciated (but it is not required). +* +* - Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* +* The authors specifically disclaim any warranties, including, but not limited +* to, the implied warranties of merchantability and fitness for a particular +* purpose. The software provided hereunder is on an "as is" basis, and the +* authors have no obligation to provide maintenance, support, updates, +* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the +* authors be held liable to any party for direct, indirect, special, +* incidental, or consequential damages arising out of the use of this software +* and its documentation. +* +* The Lua language and this implementation have been entirely designed and +* written by Waldemar Celes Filho, Roberto Ierusalimschy and +* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. +* +* This implementation contains no third-party code. +******************************************************************************/ + diff --git a/femm/LibFolderInfo.cpp b/femm/LibFolderInfo.cpp new file mode 100644 index 0000000..bc94e4b --- /dev/null +++ b/femm/LibFolderInfo.cpp @@ -0,0 +1,47 @@ +// LibFolderInfo.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "LibFolderInfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLibFolderInfo dialog + + +CLibFolderInfo::CLibFolderInfo(CWnd* pParent /*=NULL*/) + : CDialog(CLibFolderInfo::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLibFolderInfo) + m_foldername = _T(""); + m_folderurl = _T(""); + m_foldervendor = _T(""); + //}}AFX_DATA_INIT +} + + +void CLibFolderInfo::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLibFolderInfo) + DDX_Text(pDX, IDC_FOLDERNAME, m_foldername); + DDX_Text(pDX, IDC_FOLDERURL, m_folderurl); + DDX_Text(pDX, IDC_FOLDERVENDOR, m_foldervendor); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLibFolderInfo, CDialog) + //{{AFX_MSG_MAP(CLibFolderInfo) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLibFolderInfo message handlers diff --git a/femm/LibFolderInfo.h b/femm/LibFolderInfo.h new file mode 100644 index 0000000..b2e48a4 --- /dev/null +++ b/femm/LibFolderInfo.h @@ -0,0 +1,48 @@ +#if !defined(AFX_LIBFOLDERINFO_H__61112D57_5D5C_4920_945C_E87C037B8AC6__INCLUDED_) +#define AFX_LIBFOLDERINFO_H__61112D57_5D5C_4920_945C_E87C037B8AC6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LibFolderInfo.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLibFolderInfo dialog + +class CLibFolderInfo : public CDialog +{ +// Construction +public: + CLibFolderInfo(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLibFolderInfo) + enum { IDD = IDD_LIBFOLDERINFO }; + CString m_foldername; + CString m_folderurl; + CString m_foldervendor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLibFolderInfo) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLibFolderInfo) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LIBFOLDERINFO_H__61112D57_5D5C_4920_945C_E87C037B8AC6__INCLUDED_) diff --git a/femm/LuaConsoleDlg.cpp b/femm/LuaConsoleDlg.cpp new file mode 100644 index 0000000..a59ab89 --- /dev/null +++ b/femm/LuaConsoleDlg.cpp @@ -0,0 +1,199 @@ +// LuaConsoleDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "lua.h" +#include "LuaConsoleDlg.h" + +extern lua_State *lua; +extern BOOL bLinehook; +extern BOOL lua_byebye; + +CLuaConsoleDlg *pThis; + +// CLuaConsoleDlg dialog + +// IMPLEMENT_DYNAMIC(CLuaConsoleDlg, CResizableDialog) +CLuaConsoleDlg::CLuaConsoleDlg(CWnd* pParent /*=NULL*/) + : CResizableDialog(CLuaConsoleDlg::IDD, pParent) + , outbuffer(_T("")) + , inbuffer(_T("")) +{ +} + +CLuaConsoleDlg::~CLuaConsoleDlg() +{ +} + +void CLuaConsoleDlg::DoDataExchange(CDataExchange* pDX) +{ + CResizableDialog::DoDataExchange(pDX); +// DDX_Text(pDX, IDC_LUA_OUTPUT, outbuffer); + DDX_Text(pDX, IDC_LUA_INPUT, inbuffer); + DDX_Control(pDX, IDC_LUA_INPUT, inbufferctrl); + DDX_Control(pDX, IDC_LUA_OUTPUT, ConsoleOutput); +} + + +BEGIN_MESSAGE_MAP(CLuaConsoleDlg, CResizableDialog) + ON_BN_CLICKED(IDC_CLEAR_INPUT, OnBnClickedClearInput) + ON_BN_CLICKED(IDC_CLEAR_OUTPUT, OnBnClickedClearOutput) + ON_BN_CLICKED(IDC_EVALUATE, OnBnClickedEvaluate) +END_MESSAGE_MAP() + + +// CLuaConsoleDlg message handlers +BOOL CLuaConsoleDlg::OnInitDialog() +{ + CResizableDialog::OnInitDialog(); + + pThis=this; + + // register lua extensions + lua_register(lua,"print",lua_Print); + lua_register(lua,"showconsole",lua_showconsole); + lua_register(lua,"hideconsole",lua_hideconsole); + lua_register(lua,"show_console",lua_showconsole); + lua_register(lua,"hide_console",lua_hideconsole); + lua_register(lua,"clearconsole",lua_clearconsole); + lua_register(lua,"clear_console",lua_clearconsole); + + // preset layout + AddAnchor(IDC_EVALUATE, BOTTOM_RIGHT); + AddAnchor(IDC_CLEAR_INPUT, BOTTOM_LEFT); + AddAnchor(IDC_CLEAR_OUTPUT, BOTTOM_LEFT); + AddAnchor(IDC_LUA_OUTPUT, TOP_LEFT, MIDDLE_RIGHT); + AddAnchor(IDC_LUA_INPUT, MIDDLE_LEFT,BOTTOM_RIGHT); + + ConsoleOutput.LimitText(64000); + + return TRUE; +} + +void CLuaConsoleDlg::ToOutput(CString str) +{ + int Length; + int n = (int) ConsoleOutput.GetLimitText(); + + // check to see if string to be printed is bigger than the + // buffer size of the edit box. If so, trim the string. + if (str.GetLength()>n) str.Left(n-1); + + // trim info in edit box, if needed + Length = ConsoleOutput.GetWindowTextLength(); + if ((Length + str.GetLength()) >= n) + { + int k=20; + while (ConsoleOutput.LineIndex(k)1) pThis->ToOutput("\t"); + else pThis->ToOutput("--> "); + pThis->ToOutput(s); + lua_pop(L, 1); // pop result + } + pThis->ToOutput("\r\n"); + + return 0; +} + +void CLuaConsoleDlg::OnBnClickedClearInput() +{ + if (bLinehook!=FALSE) return; + + UpdateData(TRUE); + inbuffer=""; + UpdateData(FALSE); +} + +void CLuaConsoleDlg::OnBnClickedClearOutput() +{ + if (bLinehook!=FALSE) return; + + ConsoleOutput.SetWindowText(""); +} + +void CLuaConsoleDlg::OnBnClickedEvaluate() +{ + if (bLinehook!=FALSE) return; + + CString LuaCmd; + + UpdateData(); + ToOutput(inbuffer+"\r\n"); + LuaCmd=inbuffer; + inbuffer=""; + UpdateData(FALSE); + bLinehook=NormalLua; + + CStatusBar *StatBar=(CStatusBar *)((CFrameWnd *)GetTopLevelFrame())->GetMessageBar(); + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + int lua_error_code=lua_dostring(lua,LuaCmd); + + if(lua_error_code!=FALSE){ +// if (lua_error_code==LUA_ERRRUN) +// AfxMessageBox("Run Error"); +// if (lua_error_code==LUA_ERRSYNTAX) +// AfxMessageBox("Syntax Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + inbuffer=LuaCmd; + UpdateData(FALSE); + } + + bLinehook=FALSE; + inbufferctrl.SetFocus(); + StatBar->SetPaneText(0,"Ready",TRUE); + + if(lua_byebye==TRUE){ + ASSERT(AfxGetMainWnd() != NULL); + AfxGetMainWnd()->PostMessage(WM_CLOSE); + } + + +} + +int CLuaConsoleDlg::lua_showconsole(lua_State *L) +{ + pThis->ShowWindow(SW_SHOW); + return 0; +} + + +int CLuaConsoleDlg::lua_hideconsole(lua_State *L) +{ + pThis->ShowWindow(SW_HIDE); + return 0; +} + +int CLuaConsoleDlg::lua_clearconsole(lua_State *L) +{ + pThis->ConsoleOutput.SetWindowText(""); + return 0; +} \ No newline at end of file diff --git a/femm/LuaConsoleDlg.h b/femm/LuaConsoleDlg.h new file mode 100644 index 0000000..768d867 --- /dev/null +++ b/femm/LuaConsoleDlg.h @@ -0,0 +1,39 @@ +#pragma once + +#include "ResizableDialog.h" + +// CLuaConsoleDlg dialog + +class CLuaConsoleDlg : public CResizableDialog +{ +// DECLARE_DYNAMIC(CLuaConsoleDlg) + +public: + CLuaConsoleDlg(CWnd* pParent = NULL); // standard constructor + virtual ~CLuaConsoleDlg(); + +// Dialog Data + enum { IDD = IDD_LUACONSOLE }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + + DECLARE_MESSAGE_MAP() +public: + CString outbuffer; + CString inbuffer; + afx_msg void OnBnClickedClearInput(); + afx_msg void OnBnClickedClearOutput(); + + void ToOutput(CString str); + static int lua_Print(lua_State *L); + static int lua_showconsole(lua_State *L); + static int lua_hideconsole(lua_State *L); + static int lua_clearconsole(lua_State *L); + + CLuaEdit inbufferctrl; + CEdit ConsoleOutput; + + afx_msg void OnBnClickedEvaluate(); +}; diff --git a/femm/LuaEdit.cpp b/femm/LuaEdit.cpp new file mode 100644 index 0000000..7bdc8e4 --- /dev/null +++ b/femm/LuaEdit.cpp @@ -0,0 +1,172 @@ +// LuaEdit.cpp: C++ derived edit control parsing with lua + +#include "stdafx.h" +#include "lua.h" + +// COMMAND IDs used in the context menu +#define APSTUDIO_INVOKED +#undef APSTUDIO_READONLY_SYMBOLS +#include "resource.h" +#define ID_LUA_PARSE _APS_NEXT_COMMAND_VALUE+1 + + +extern lua_State * lua; + + +///////////////////////////////////////////////////////////////////////////// +// LuaEdit + +BEGIN_MESSAGE_MAP(CLuaEdit, CEdit) + //{{AFX_MSG_MAP(CLuaEdit) + ON_WM_CHAR() + ON_WM_RBUTTONUP() + //}}AFX_MSG_MAP + ON_COMMAND(ID_EDIT_CUT, Cut) + ON_COMMAND(ID_EDIT_COPY, Copy) + ON_COMMAND(ID_EDIT_PASTE, Paste) + ON_COMMAND(ID_EDIT_UNDO, Undo) + ON_COMMAND(ID_EDIT_CLEAR, Clear) + ON_COMMAND(ID_EDIT_SELECT_ALL, SelectAll) + ON_COMMAND(ID_LUA_PARSE, ParseWithLua) +END_MESSAGE_MAP() + + +void CLuaEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if (nChar == 12) ParseWithLua(); + + // hook that implements evaluation of Lua input via + // Shift+Enter in the Lua console + if ((nChar == 13) && (GetKeyState(VK_SHIFT) & 0x8000)) + GetParent()->PostMessage(WM_COMMAND,IDC_EVALUATE); + + else CEdit::OnChar(nChar, nRepCnt, nFlags); +} + +void CLuaEdit::Undo() +{ + CEdit::Undo(); +} + +void CLuaEdit::ParseWithLua() +{ + int nStart,nEnd,i,k; + CString tolua; + + GetSel(nStart,nEnd); + GetWindowText(tolua); + + if (nStart!=nEnd) + { + tolua="return " + tolua.Mid(nStart,nEnd-nStart) + "\n"; + i=lua_gettop(lua); + lua_dostring(lua,tolua); + k=lua_gettop(lua); + if (i!=k){ + tolua=lua_tostring(lua,-1); + if (tolua.GetLength()==0){ + AfxMessageBox("Input does not evaluate to a numerical value"); + } + else ReplaceSel(tolua,TRUE); + lua_pop(lua, 1); // pop result from Lua stack so we don't get an overflow. + } + } +} + +BOOL CLuaEdit::IsSelection() +{ + int nStart,nEnd; + + GetSel(nStart,nEnd); + if (nStart!=nEnd) return TRUE; + + return FALSE; +} + + +void CLuaEdit::OnRButtonUp(UINT nFlags, CPoint point) +{ + + HANDLE hClip = ::GetClipboardData(CF_TEXT); + + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + VERIFY(pMenu->CreatePopupMenu()); + + if (CanUndo()) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_UNDO, "Undo")); + else + VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_EDIT_UNDO, "Undo")); + + VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, "")); + if (IsSelection() || hClip) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Cut")); + else VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_EDIT_CUT, "Cut")); + + if (IsSelection()) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Copy")); + else + VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_EDIT_COPY, "Copy")); + + if (hClip) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Paste")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Paste")); + + if (IsSelection()) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CLEAR, "Delete")); + else + VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_EDIT_CLEAR, "Delete")); + + VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, "")); + + if (IsSelection()) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_LUA_PARSE, "Evaluate")); + else + VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_LUA_PARSE, "Evaluate")); + + VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, "")); + + int nStart,nEnd,nLength; + CString strText; + GetWindowText(strText); + GetSel(nStart,nEnd); + nLength=strText.GetLength(); + if ((nLength!=0) && (nLength-nEnd+nStart>0)) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_SELECT_ALL, "Select All")); + else VERIFY(pMenu->AppendMenu(MF_GRAYED, ID_EDIT_SELECT_ALL, "Select All")); + + if (!hClip) + ::CloseHandle(hClip); + ClientToScreen(&point); + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, + point.x, point.y, + this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("CLuaEdit::OnRButtonUp failed to destroy menu resource\n"); + pMenu = FALSE; + } +} + +void CLuaEdit::SelectAll() +{ + CString strText; + GetWindowText(strText); + SetSel(0, strText.GetLength()); +} \ No newline at end of file diff --git a/femm/LuaEdit.h b/femm/LuaEdit.h new file mode 100644 index 0000000..b92ea09 --- /dev/null +++ b/femm/LuaEdit.h @@ -0,0 +1,27 @@ +////////////////////////////////////////////////// +// CLuaEdit is a specialized CEdit control that +// allows the selection to be evaluated by Lua +////////////////////////////////////////////////// + +class CLuaEdit : public CEdit +{ +private: + using CEdit::Create; + +public: +// Implementation + BOOL IsSelection(); + void ParseWithLua(); + void Undo(); + void SelectAll(); + +protected: + + + //{{AFX_MSG(CLuaEdit) + afx_msg void OnChar(UINT, UINT, UINT); // check to see if we need to evaluate the selection + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; \ No newline at end of file diff --git a/femm/MDITabs.cpp b/femm/MDITabs.cpp new file mode 100644 index 0000000..b092f9d --- /dev/null +++ b/femm/MDITabs.cpp @@ -0,0 +1,533 @@ +/****************************************************************************\ +Datei : MDITabs.h +Projekt: MDITabs, a tabcontrol for switching between MDI-views +Inhalt : CMDITabs implementation +Datum : 03.10.2001 +Autor : Christian Rodemeyer +Hinweis: © 2001 by Christian Rodemeyer +\****************************************************************************/ + +/****************************************************************************\ +As described on http://www.codeproject.com/KB/tabs/mditabs.aspx, +MDITabls is distrbuted under the CPOL (http://www.codeproject.com/info/cpol10.aspx) +For convenience, the CPOL is reproduced here: + +** The Code Project Open License (CPOL) 1.02 ** + +Preamble + +This License governs Your use of the Work. This License is intended to +allow developers to use the Source Code and Executable Files provided as +part of the Work in any application in any form. + +The main points subject to the terms of the License are: + +* Source Code and Executable Files can be used in commercial applications; +* Source Code and Executable Files can be redistributed; and +* Source Code can be modified to create derivative works. +* No claim of suitability, guarantee, or any warranty whatsoever is provided. +* The software is provided "as-is". +* The Article accompanying the Work may not be distributed or republished + without the Author's consent + +This License is entered between You, the individual or other entity reading +or otherwise making use of the Work licensed pursuant to this License and +the individual or other entity which offers the Work under the terms of this +License ("Author"). + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT +OPEN LICENSE ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER +APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS +LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS +CONTAINED HEREIN IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. IF YOU DO NOT AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS +LICENSE, YOU CANNOT MAKE ANY USE OF THE WORK. + +1. Definitions. + a) "Articles" means, collectively, all articles written by Author which + describes how the Source Code and Executable Files for the Work may be + used by a user. + b) "Author" means the individual or entity that offers the Work under the + terms of this License. + c) "Derivative Work" means a work based upon the Work or upon the Work and + other pre-existing works. + d) "Executable Files" refer to the executables, binary files, configuration + and any required data files included in the Work. + e) "Publisher" means the provider of the website, magazine, CD-ROM, DVD or + other medium from or by which the Work is obtained by You. + f) "Source Code" refers to the collection of source code and configuration + files used to create the Executable Files. + g) "Standard Version" refers to such a Work if it has not been modified, + or has been modified in accordance with the consent of the Author, such consent being in the full discretion of the Author. + h) "Work" refers to the collection of files distributed by the Publisher, + including the Source Code, Executable Files, binaries, data files, + documentation, whitepapers and the Articles. + i) "You" is you, an individual or entity wishing to use the Work and exercise + your rights under this License. +2. Fair Use/Fair Use Rights. Nothing in this License is intended to reduce, limit, + or restrict any rights arising from fair use, fair dealing, first sale or other + limitations on the exclusive rights of the copyright owner under copyright law + or other applicable laws. +3. License Grant. Subject to the terms and conditions of this License, the Author + hereby grants You a worldwide, royalty-free, non-exclusive, perpetual + (for the duration of the applicable copyright) license to exercise the + rights in the Work as stated below: + a) You may use the standard version of the Source Code or Executable Files + in Your own applications. + b) You may apply bug fixes, portability fixes and other modifications obtained + from the Public Domain or from the Author. A Work modified in such a way + shall still be considered the standard version and will be subject to + this License. + c) You may otherwise modify Your copy of this Work (excluding the Articles) + in any way to create a Derivative Work, provided that You insert a + prominent notice in each changed file stating how, when and where You + changed that file. + d) You may distribute the standard version of the Executable Files and Source + Code or Derivative Work in aggregate with other (possibly commercial) + programs as part of a larger (possibly commercial) software distribution. + The Articles discussing the Work published in any form by the author may not be distributed or republished without the Author's consent. The author retains copyright to any such Articles. You may use the Executable Files and Source Code pursuant to this License but you may not repost or republish or otherwise distribute or make available the Articles, without the prior written consent of the Author. + Any subroutines or modules supplied by You and linked into the Source Code or + Executable Files of this Work shall not be considered part of this Work and + will not be subject to the terms of this License. +4. Patent License. Subject to the terms and conditions of this License, each + Author hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable (except as stated in this section) patent license to + make, have made, use, import, and otherwise transfer the Work. +5. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + a) You agree not to remove any of the original copyright, patent, trademark, + and attribution notices and associated disclaimers that may appear in the + Source Code or Executable Files. + b) You agree not to advertise or in any way imply that this Work is a product + of Your own. + c) The name of the Author may not be used to endorse or promote products + derived from the Work without the prior written consent of the Author. + d) You agree not to sell, lease, or rent any part of the Work. This does not + restrict you from including the Work or any part of the Work inside a + larger software distribution that itself is being sold. The Work by + itself, though, cannot be sold, leased or rented. + e) You may distribute the Executable Files and Source Code only under the + terms of this License, and You must include a copy of, or the Uniform + Resource Identifier for, this License with every copy of the Executable + Files or Source Code You distribute and ensure that anyone receiving + such Executable Files and Source Code agrees that the terms of this + License apply to such Executable Files and/or Source Code. You may not + offer or impose any terms on the Work that alter or restrict the terms + of this License or the recipients' exercise of the rights granted + hereunder. You may not sublicense the Work. You must keep intact all + notices that refer to this License and to the disclaimer of warranties. + You may not distribute the Executable Files or Source Code with any + technological measures that control access or use of the Work in a + manner inconsistent with the terms of this License. + f) You agree not to use the Work for illegal, immoral or improper purposes, + or on pages containing illegal, immoral or improper material. The Work + is subject to applicable export laws. You agree to comply with all such + laws and regulations that may apply to the Work after Your receipt of + the Work. +6. Representations, Warranties and Disclaimer. THIS WORK IS PROVIDED "AS IS", + "WHERE IS" AND "AS AVAILABLE", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OR + CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING + COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY + DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, INCLUDING + WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE + QUALITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR + NON-INFRINGEMENT, OR THAT THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, + BUG-FREE OR FREE OF VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU + DISTRIBUTE THE WORK OR DERIVATIVE WORKS. +7. Indemnity. You agree to defend, indemnify and hold harmless the Author and the + Publisher from and against any claims, suits, losses, damages, liabilities, + costs, and expenses (including reasonable legal or attorneys’ fees) resulting + from or relating to any use of the Work by You. +8. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, + IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON ANY LEGAL + THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY + DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR OTHERWISE, + EVEN IF THE AUTHOR OR THE PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. +9. Termination. + a) This License and the rights granted hereunder will terminate automatically + upon any breach by You of any term of this License. Individuals or entities + who have received Derivative Works from You under this License, however, + will not have their licenses terminated provided such individuals or + entities remain in full compliance with those licenses. Sections 1, 2, 6, 7, + 8, 9, 10 and 11 will survive any termination of this License. + b) If You bring a copyright, trademark, patent or any other infringement + claim against any contributor over infringements You claim are made by the + Work, your License from such contributor to the Work ends automatically. + c) Subject to the above terms and conditions, this License is perpetual + (for the duration of the applicable copyright in the Work). Notwithstanding + the above, the Author reserves the right to release the Work under different + license terms or to stop distributing the Work at any time; provided, + however that any such election will not serve to withdraw this License + (or any other license that has been, or is required to be, granted under + the terms of this License), and this License will continue in full force + and effect unless terminated as stated above. +10. Publisher. The parties hereby confirm that the Publisher shall not, under any + circumstances, be responsible for and shall not have any liability in respect + of the subject matter of this License. The Publisher makes no warranty + whatsoever in connection with the Work and shall not be liable to You or any + party on any legal theory for any damages whatsoever, including without + limitation any general, special, incidental or consequential damages arising + in connection to this license. The Publisher reserves the right to cease + making the Work available to You at any time without notice +11. Miscellaneous + a) This License shall be governed by the laws of the location of the head + office of the Author or if the Author is an individual, the laws of + location of the principal place of residence of the Author. + b) If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this License, such provision shall be reformed to the + minimum extent necessary to make such provision valid and enforceable. + c) No term or provision of this License shall be deemed waived and no breach + consented to unless such waiver or consent shall be in writing and signed + by the party to be charged with such waiver or consent. + d) This License constitutes the entire agreement between the parties with + respect to the Work licensed herein. There are no understandings, + agreements or representations with respect to the Work not specified + herein. The Author shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be modified + without the mutual written agreement of the Author and You. +\****************************************************************************/ + +#include "stdafx.h" +#include "MDITabs.h" +#include +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMDITabs + +CMDITabs::CMDITabs() +{ + m_mdiClient = NULL; + m_minViews = 0; + m_bImages = false; + m_bTop = false; +} + +BEGIN_MESSAGE_MAP(CMDITabs, CTabCtrl) + //{{AFX_MSG_MAP(CMDITabs) + ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelChange) + ON_WM_PAINT() + ON_WM_NCPAINT() + ON_WM_CONTEXTMENU() + ON_WM_LBUTTONDBLCLK() + //}}AFX_MSG_MAP + ON_MESSAGE(WM_SIZEPARENT, OnSizeParent) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMDITabs message handlers + +afx_msg LRESULT CMDITabs::OnSizeParent(WPARAM, LPARAM lParam) +{ + if (GetItemCount() < m_minViews) + { + ShowWindow(SW_HIDE); + } + else + { + AFX_SIZEPARENTPARAMS* pParams = reinterpret_cast(lParam); + + const int height = 26 + (m_bImages ? 1 : 0); + const int offset = 2; + + m_height = height + offset; + m_width = pParams->rect.right - pParams->rect.left; + + if (m_bTop) + { + pParams->rect.top += height; + MoveWindow(pParams->rect.left, pParams->rect.top - height, m_width, m_height, true); + } + else + { + pParams->rect.bottom -= height; + MoveWindow(pParams->rect.left, pParams->rect.bottom - offset, m_width, m_height, true); + } + ShowWindow(SW_NORMAL); + } + return 0; +} + +void CMDITabs::OnSelChange(NMHDR* pNMHDR, LRESULT* pResult) +{ + TCITEM item; + item.mask = TCIF_PARAM; + GetItem(GetCurSel(), &item); + ::BringWindowToTop(HWND(item.lParam)); + *pResult = 0; +} + +void CMDITabs::Update() +{ + SetRedraw(false); + + HWND active = ::GetTopWindow(m_mdiClient); // get active view window (actually the frame of the view) + + typedef std::vector TWndVec; + typedef TWndVec::iterator TWndIter; + + TWndVec vChild; // put all child windows in a list (actually a vector) + for (HWND child = active; child; child = ::GetNextWindow(child, GW_HWNDNEXT)) + { + vChild.push_back(child); + } + + TCITEM item; + char text[256]; + item.pszText = text; + + int i; + for (i = GetItemCount(); i--;) // for each tab + { + item.mask = TCIF_PARAM; + GetItem(i, &item); + + TWndIter it = std::find(vChild.begin(), vChild.end(), HWND(item.lParam)); + if (it == vChild.end()) // associatete view does no longer exist, so delete the tab + { + DeleteItem(i); + if (m_bImages) RemoveImage(i); + } + else // update the tab's text, image and selection state + { + item.mask = TCIF_TEXT; + ::GetWindowText(*it, text, 256); + if (m_bImages) m_images.Replace(i, (HICON)::GetClassLongPtr(*it, GCLP_HICON)); + SetItem(i, &item); + if (*it == active) SetCurSel(i); // associated view is active => make it the current selection + vChild.erase(it); // remove view from list + } + } + + // all remaining views in vChild have to be added as new tabs + i = GetItemCount(); + for (TWndIter it = vChild.begin(), end = vChild.end(); it != end; ++it) + { + item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE; + ::GetWindowText(*it, text, 256); + // a bug in wine makes us want to add some extra, spurious tabs. + // Since there's no text on these extra tabs, we can use this as + // a discriminator to root them out. + if(strlen(text)>1) + { + if (m_bImages) m_images.Add((HICON)::GetClassLongPtr(*it, GCLP_HICON)); + item.iImage = i; + item.lParam = LPARAM(*it); + InsertItem(i, &item); + if (*it == active) SetCurSel(i); + ++i; + } + } + + // this removes the control when there are no tabs and shows it when there is at least one tab + bool bShow = GetItemCount() >= m_minViews; + if ((!bShow && IsWindowVisible()) || (bShow && !IsWindowVisible())) + { + static_cast(FromHandlePermanent(::GetParent(m_mdiClient)))->RecalcLayout(); + } + + RedrawWindow(NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_ERASE); + SetRedraw(true); +} + +void CMDITabs::OnPaint() +{ + CPaintDC dc(this); + + if (GetItemCount() == 0) return; // do nothing + + // cache some system colors + DWORD shadow = ::GetSysColor(COLOR_3DSHADOW); + DWORD dark = ::GetSysColor(COLOR_3DDKSHADOW); + DWORD hilight = ::GetSysColor(COLOR_3DHILIGHT); + DWORD light = ::GetSysColor(COLOR_3DLIGHT); + + // Special preparations for spin-buttons (in case there are more tabs than fit into the window) + // extend borders and prevent system from overdrawing our new pixels + if (m_bTop) + { + ::SetPixel(dc, m_width - 5, m_height - 8, hilight); + ::SetPixel(dc, m_width - 5, m_height - 7, light); + ::SetPixel(dc, m_width - 6, m_height - 8, hilight); + ::SetPixel(dc, m_width - 6, m_height - 7, light); + ::ExcludeClipRect(dc, 0, m_height - 6, m_width, m_height - 2); + ::ExcludeClipRect(dc, m_width - 6, m_height - 8, m_width - 2, m_height - 6); + } + else + { + ::SetPixel(dc, m_width - 5, 2, shadow); + ::SetPixel(dc, m_width - 5, 3, dark); + ::SetPixel(dc, m_width - 6, 2, shadow); + ::SetPixel(dc, m_width - 6, 3, dark); + ::ExcludeClipRect(dc, 0, 0, m_width, 2); + ::ExcludeClipRect(dc, m_width - 6, 2, m_width - 2, 4); + } + + // windows should draw the control as usual + _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); + pThreadState->m_lastSentMsg.wParam = WPARAM(HDC(dc)); + Default(); + + // extend the horizontal border to the left margin + if (m_bTop) + { + ::SetPixel(dc, 0, m_height - 8, hilight); + ::SetPixel(dc, 0, m_height - 7, light); + } + else + { + ::SetPixel(dc, 0, 2, shadow); + } + + // special drawing if the leftmost tab is selected + CRect rect; + GetItemRect(GetCurSel(), rect); + if (rect.left == 2) // is at the leftmost position a tab selected? + { + // if yes, remove the leftmost white line and extend the bottom border of the tab + int j = m_bImages ? 1 : 0; + + HPEN pen = ::CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DFACE)); + HGDIOBJ old = ::SelectObject(dc, pen); + ::MoveToEx(dc, 0, 2, NULL); + ::LineTo(dc, 0, 22 + j); + ::MoveToEx(dc, 1, 2, NULL); + ::LineTo(dc, 1, 22 + j); + ::SelectObject(dc, old); + ::DeleteObject(pen); + + if (m_bTop) + { + ::SetPixel(dc, 0, 0, hilight); ::SetPixel(dc, 1, 0, hilight); + ::SetPixel(dc, 0, 1, light); ::SetPixel(dc, 1, 1, light); + } + else + { + ::SetPixel(dc, 0, 22 + j, shadow); ::SetPixel(dc, 1, 22 + j, shadow); + ::SetPixel(dc, 0, 23 + j, dark); ::SetPixel(dc, 1, 23 + j, dark); + } + } +} + +void CMDITabs::OnNcPaint() +{ + HDC hdc = ::GetWindowDC(m_hWnd); + + CRect rect; + rect.left = 0; + rect.top = m_bTop ? 0 : -2; + rect.right = m_width; + rect.bottom = m_height; + + HPEN pen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DFACE)); + HGDIOBJ old = ::SelectObject(hdc, pen); + if (m_bTop) + { + DrawEdge(hdc, rect, EDGE_SUNKEN, BF_LEFT|BF_RIGHT|BF_TOP); + ::MoveToEx(hdc, 2, m_height - 1, NULL); + ::LineTo(hdc, m_width - 2, m_height - 1); + ::MoveToEx(hdc, 2, m_height - 2, NULL); + ::LineTo(hdc, m_width - 2, m_height - 2); + } + else + { + DrawEdge(hdc, rect, EDGE_SUNKEN, BF_LEFT|BF_RIGHT|BF_BOTTOM); + ::MoveToEx(hdc, 2, 0, NULL); + ::LineTo(hdc, m_width - 2, 0); + ::MoveToEx(hdc, 2, 1, NULL); + ::LineTo(hdc, m_width - 2, 1); + } + ::SelectObject(hdc, old); + ::DeleteObject(pen); + ::ReleaseDC(m_hWnd, hdc); +} + +void CMDITabs::Create(CFrameWnd* pMainFrame, DWORD dwStyle) +{ + m_bTop = (dwStyle & MT_TOP); + m_minViews = (dwStyle & MT_HIDEWLT2VIEWS) ? 2 : 1; + + CTabCtrl::Create(WS_CHILD|WS_VISIBLE|(m_bTop?0:TCS_BOTTOM)|TCS_SINGLELINE|TCS_FOCUSNEVER|TCS_FORCEICONLEFT|WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), pMainFrame, 42); + ModifyStyleEx(0, WS_EX_CLIENTEDGE); + SendMessage(WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 0); + + HWND wnd; + for (wnd = ::GetTopWindow(*pMainFrame); wnd; wnd = ::GetNextWindow(wnd, GW_HWNDNEXT)) + { + char wndClass[32]; + ::GetClassName(wnd, wndClass, 32); + if (strncmp(wndClass, "MDIClient", 32) == 0) break; + } + m_mdiClient = wnd; + + ASSERT(m_mdiClient); // Ooops, no MDIClient window? + + // manipulate Z-order so, that our tabctrl is above the mdi client, but below any status bar + ::SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + ::SetWindowPos(m_mdiClient, m_hWnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + m_bImages = (dwStyle & MT_IMAGES) != 0; + if (m_bImages) + { + if (m_images.GetSafeHandle()) + { + m_images.SetImageCount(0); + } + else + { + m_images.Create(16, 16, ILC_COLORDDB|ILC_MASK, 1, 1); + } + SetImageList(&m_images); + } + + //SetItemSize(CSize(50, 0)); // Fixed Width Experiment +} + +void CMDITabs::OnContextMenu(CWnd* pWnd, CPoint point) +{ + TCHITTESTINFO hit; + hit.pt = point; + ScreenToClient(&hit.pt); + int i = HitTest(&hit); + if (i >= 0) + { + TCITEM item; + item.mask = TCIF_PARAM; + GetItem(i, &item); + + HWND hWnd = HWND(item.lParam); + SetCurSel(i); + ::BringWindowToTop(hWnd); + + HMENU menu = HMENU(::SendMessage(::GetTopWindow(hWnd), WM_GETTABSYSMENU, 0, 0)); + if (menu == 0) menu = ::GetSystemMenu(hWnd, FALSE); + UINT cmd = ::TrackPopupMenu(menu, TPM_RETURNCMD|TPM_RIGHTBUTTON|TPM_VCENTERALIGN, point.x, point.y, 0, m_hWnd, NULL); + ::SendMessage(hWnd, WM_SYSCOMMAND, cmd, 0); + } +} + +void CMDITabs::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + int i = GetCurSel(); + if (i >= 0) + { + TCITEM item; + item.mask = TCIF_PARAM; + GetItem(i, &item); + HWND hWnd = HWND(item.lParam); + ::ShowWindow(hWnd, SW_MAXIMIZE); + } +} diff --git a/femm/MDITabs.h b/femm/MDITabs.h new file mode 100644 index 0000000..09b36e1 --- /dev/null +++ b/femm/MDITabs.h @@ -0,0 +1,81 @@ +/****************************************************************************\ +Datei : MDITabs.h +Projekt: MDITabs, a tabcontrol for switching between MDI-views +Inhalt : EMDITabStyles, CMDITabs declaration +Datum : 03.10.2001 +Autor : Christian Rodemeyer +Hinweis: © 2001 by Christian Rodemeyer +\****************************************************************************/ +#pragma once + +#ifndef __MDITABS_H +#define __MDITABS_H + +/****************************************************************************\ + EMDITabStyles: Styles for customizing the appeareance of CMDITabs +\****************************************************************************/ +enum EMDITabStyles +{ + MT_BOTTOM = 0x0000, // places tabs at bottom (default) + MT_TOP = 0x0001, // place tabs at top + MT_IMAGES = 0x0002, // show images + MT_HIDEWLT2VIEWS = 0x0004, // Hide Tabs when less than two views are open (default is one view) + MT_TOOLTIPS = 0x0008, // not implemented (a tooltip can appear about a tab) + MT_BUTTONS = 0x0010, // not implemented (show tabs as buttons) + MT_AUTOSIZE = 0x0020, // not implemented (tabs are sized to fit the entire width of the control) + MT_TASKBAR = 0x0038 // MT_TOOLTIPS|MT_BUTTONS|MT_AUTOSIZE +}; + +enum EWMMTGetInfo +{ + WM_GETTABTIPTEXT = WM_APP + 0x0393, // send to associated view to get a tip text + WM_GETTABSYSMENU = WM_APP + 0x0394 // if neccessary, the view can provide a different systemmenu by answering this message +}; + +/****************************************************************************\ + CMdiTabs: Deklaration +\****************************************************************************/ +class CMDITabs : public CTabCtrl +{ +public: + CMDITabs(); + + void Create(CFrameWnd* pMainFrame, DWORD dwStyle = MT_BOTTOM|MT_IMAGES); + void Update(); // sync the tabctrl with all views + + void SetMinViews(int minViews) {m_minViews = minViews;} + +private: + HWND m_mdiClient; + int m_height; + int m_width; + CImageList m_images; + int m_minViews; // minimum number of views + bool m_bImages; + bool m_bTop; + +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMDITabs) + //}}AFX_VIRTUAL + +// Implementation +public: + + // Generated message map functions +protected: + //{{AFX_MSG(CMDITabs) + afx_msg void OnSelChange(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnPaint(); + afx_msg void OnNcPaint(); + afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + //}}AFX_MSG + afx_msg LRESULT OnSizeParent(WPARAM, LPARAM lParam); + + DECLARE_MESSAGE_MAP() +}; + +#endif diff --git a/femm/MOVECOPY.CPP b/femm/MOVECOPY.CPP new file mode 100644 index 0000000..bd9b238 --- /dev/null +++ b/femm/MOVECOPY.CPP @@ -0,0 +1,2294 @@ +// femmeDoc.cpp : implementation of the CFemmeDoc class (continued...) +// + +#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 "ArcDlg.h" +#include "DXFImport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern BOOL bLinehook; + +//----------------------------------------------------------------- + +BOOL CFemmeDoc::ReadDXF(CString fname, double DefTol) +{ + FILE *fp; + int j,k; + CArray layerlist; + CString myLayer; + + if( (fp=fopen(fname,"rt"))==NULL ) return FALSE; + NoDraw=TRUE; + + // clear out any old drawing that we might have; +// 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(); + + char s[256]; + char v[256]; + BOOL PolylineFlag=FALSE; + CNode n[4]; + CSegment segm; + CArcSegment asegm; + CComplex c,p,q; + double R,a0,a1; + int xx,PolyLineClosed,firstpoint; + double angle=0; + + while (fgets(s,256,fp)!=NULL) + { + if (strncmp(s,"LAYER",5)==0) + { + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==2){ + sscanf(v,"%s",s); + myLayer=s; + layerlist.Add(myLayer); + } + } while(1>0); + } + + if (strncmp(s,"POINT",5)==0) + { + xx=0; + n[0].InGroup=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==10) { n[0].x=atof(v); xx=xx | 1; } + if (k==20) { n[0].y=atof(v); xx=xx | 2; } + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + if (xx==3) nodelist.Add(n[0]); + } + + if (strncmp(s,"LWPOLYLINE",10)==0) + { + int segs=0; + PolyLineClosed=FALSE; + firstpoint=-1; + angle = 0; + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + int n0,n1; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) angle=360.; + } + if (k==70) PolyLineClosed=TRUE; + if (xx==3){ + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + xx=0; + if(segs==0) firstpoint=j; + else{ + if(angle==0) + { + segm.n0=j; + segm.n1=j-1; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j-1; n1=j; } + else{ n0=j; n1=j-1; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + if ((PolyLineClosed==TRUE) && (firstpoint>=0) && (segs>0)) + { + // take care of closing the contour, if required. + j=(int) nodelist.GetSize()-1; + if(angle==0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + angle=0; + } + } + } + + + if (strncmp(s,"POLYLINE",8)==0) + { + PolylineFlag=-1; + firstpoint=-1; + PolyLineClosed=FALSE; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==70) { + j=atoi(v); + if (j==1) PolyLineClosed=TRUE; + } + } while(1>0); + + } + + if (strncmp(s,"SEQEND",6)==0) + { + PolylineFlag=FALSE; + int j = ((int) nodelist.GetSize())-1; + if ((PolyLineClosed==TRUE) && (firstpoint>=0)) + { + if (angle == 0.0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else + { + int n0, n1; + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + } + } + PolyLineClosed=FALSE; + angle = 0.0; + } + + if (strncmp(s,"VERTEX",6)==0) + { + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + double next_angle = 0.0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) next_angle=360.; + } + } while(1>0); + + if(xx==3) + { + nodelist.Add(n[0]); + if (angle != 0.0) + { + j = (int)nodelist.GetSize(); + + int n0, n1; + if(angle>0) { n0=j-2; n1=j-1; } + else{ n0=j-1; n1=j-2; angle=fabs(angle); } + + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + + if (xx==15) + { + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + segm.n0=j; segm.n1=j+1; + linelist.Add(segm); + } + } + + // catch ARCALIGNEDTEXT, which derails the ARC code... + if (strncmp(s,"ARCA",4)==0) s[0]=NULL; + + if (strncmp(s,"ARC",3)==0) + { + n[0].InGroup=0; + n[1].InGroup=0; + asegm.InGroup=0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + + if(xx==31) + { + if (a10); + + if(xx==7) + { + n[0].x=c.re+R; n[1].x=c.re-R; + n[0].y=c.im; n[1].y=c.im; + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + asegm.n0=j; asegm.n1=j+1; + asegm.MaxSideLength=5.; + asegm.ArcLength=180.; + arclist.Add(asegm); + asegm.n1=j; asegm.n0=j+1; + arclist.Add(asegm); + } + } + + } + + fclose(fp); + + // could be that nothing actually got read. We want to + // catch this case and tell the user about it. + if(nodelist.GetSize()==0) return FALSE; + + // suggest the proper tolerance + CComplex p0,p1; + CDXFImport dlg; + int i; + + p0=nodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=nodelist[i].x; + if(nodelist[i].yp1.im) p1.im=nodelist[i].y; + } + + R=abs(p1-p0)*1.e-04; + dlg.m_dxftol=floor(R/pow(10.,floor(log10(R))))*pow(10.,floor(log10(R))); + + if(DefTol<0) + { + dlg.DoModal(); + FancyEnforcePSLG(dlg.m_dxftol); + } + else + { + if (DefTol==0) DefTol=dlg.m_dxftol; + FancyEnforcePSLG(DefTol); + } + + NoDraw=FALSE; + + return TRUE; +} + +void CFemmeDoc::RotateMove(CComplex c, double t, int EditAction) +{ + int i,j; + CComplex x,z; + + z=exp(I*t*PI/180); + + if(EditAction==0) + { + for(i=0;i newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i; + CComplex p0,p1; + double d; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; +; + // put in all of the nodes; + for(i=0;i newnodes; + + newnodes.RemoveAll(); + + n0=ClosestNode(p0.re,p0.im); + n1=ClosestNode(p1.re,p1.im); + + // 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;i 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;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;iextmaxx) extmaxx=nodelist[i].x; + if(nodelist[i].yextmaxy) extmaxy=nodelist[i].y; + } + + } + + for(i=0;iextmaxx) extmaxx=p.re; + if(p.imextmaxy) 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 newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i,k; + CComplex p0,p1; + double d; + + bLinehook=ImportDXF; // kludge to stop the program from giving a crash if + // the user tries to exit during a dxf import. + + CFemmeView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + pView=(CFemmeView *)GetNextView(pos); + + FirstDraw=TRUE; +// pView->lua_zoomnatural(); + dxf_line_hook(); + pView->EditAction=4; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;iInvalidateRect(NULL); + dxf_line_hook(); + + // find out what tolerance is so that there are not nodes right on + // top of each other; + if(tol==0){ + if (newnodelist.GetSize()<2) d=1.e-08; + else{ + p0=newnodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the lines; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + // put in all of the arcs; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + UnselectAll(); + + // do one last check to eliminate shallow arcs that + // link up the same two points as a line segment; + for(i=0;i + if (!m_wndToolBar1.Create(this) || + !m_wndToolBar1.LoadToolBar(IDR_MAIN1)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_wndToolBar1.SetBarStyle(m_wndToolBar1.GetBarStyle() | + CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); + + if (!m_wndToolBar2.Create(this, WS_CHILD | WS_VISIBLE | CBRS_LEFT + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI |CBRS_SIZE_DYNAMIC) || + !m_wndToolBar2.LoadToolBar(IDR_MAIN2)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + // + + if (!m_FV_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_FV_toolBar1.LoadToolBar(IDR_FEMMVIEWTYPE)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_FV_toolBar1.SetWindowText("Femmview Toolbar"); + + if (!m_leftbar.Create(this, WS_CHILD | CBRS_LEFT + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_leftbar.LoadToolBar(IDR_LEFTBAR)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_leftbar.SetWindowText("Zoom/Pan Toolbar"); + + + if (!m_FE_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_FE_toolBar1.LoadToolBar(IDR_FEMMETYPE) ) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_FE_toolBar1.SetWindowText("Femme Mode/View Commands"); + + if (!m_BD_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_BD_toolBar1.LoadToolBar(IDR_BELADRAWTYPE) ) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_BD_toolBar1.SetWindowText("Beladraw Mode/View Commands"); + + if (!m_BV_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_BV_toolBar1.LoadToolBar(IDR_BELAVIEWTYPE)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_BV_toolBar1.SetWindowText("Belaview Toolbar"); + + if (!m_HD_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_HD_toolBar1.LoadToolBar(IDR_HDRAWTYPE) ) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_HD_toolBar1.SetWindowText("hdraw Mode/View Commands"); + + if (!m_HV_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_HV_toolBar1.LoadToolBar(IDR_HVIEWTYPE)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_HV_toolBar1.SetWindowText("hview Toolbar"); + + if (!m_CD_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_CD_toolBar1.LoadToolBar(IDR_HDRAWTYPE) ) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_CD_toolBar1.SetWindowText("hdraw Mode/View Commands"); + + if (!m_CV_toolBar1.Create(this, WS_CHILD | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_FLOAT_MULTI | CBRS_SIZE_DYNAMIC) || + !m_CV_toolBar1.LoadToolBar(IDR_CVIEWTYPE)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + m_CV_toolBar1.SetWindowText("hview Toolbar"); + + // Make toolbars dockable + m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY); // + m_wndToolBar2.EnableDocking(CBRS_ALIGN_ANY); // + m_BD_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_HD_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_CD_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_FE_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_FV_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_BV_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_HV_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_CV_toolBar1.EnableDocking(CBRS_ALIGN_ANY); + m_leftbar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + + DockControlBar( &m_wndToolBar1); + DockControlBar( &m_wndToolBar2); + + DockControlBarLeftOf(&m_FE_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_BD_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_HD_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_CD_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_FV_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_BV_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_HV_toolBar1, &m_wndToolBar1); + DockControlBarLeftOf(&m_CV_toolBar1, &m_wndToolBar1); + + DockControlBarLeftOf(&m_leftbar, &m_wndToolBar2); + + m_LuaConsole.Create(IDD_LUACONSOLE); + + if ((m_luaWindowStatus==SW_SHOW) && (theApp.d_luaconsole)) + m_LuaConsole.ShowWindow(SW_SHOW); + LuaConsole=&m_LuaConsole; + + lua_register(lua,"main_minimize",luaMinimize); + lua_register(lua,"main_maximize",luaMaximize); + lua_register(lua,"main_restore", luaRestore); + lua_register(lua,"main_resize",luaResize); + +#ifdef MDITAB + // CMDITabs must be created last to ensure correct layout + // ------------------------------------------------------ + bool m_bTop = false; + bool m_bImages = true; + DWORD dwStyle = (m_bTop ? MT_TOP : 0) | (m_bImages ? MT_IMAGES : 0); + m_wndMDITabs.Create(this, dwStyle); +#endif + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CMDIFrameWnd::PreCreateWindow(cs) ) + return FALSE; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CMDIFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CMDIFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + +void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle) +{ + CMDIFrameWnd::OnUpdateFrameTitle(bAddToTitle); + +#ifdef MDITAB + m_wndMDITabs.Update(); // sync the mditabctrl with all views +#endif + +} + + +void CMainFrame::OnPtProp() +{ + if( (m_dlgBar.GetStyle() & WS_VISIBLE) != 0 ){ + m_dlgBar.ShowWindow(SW_HIDE); + theApp.bShowOutputWindow=FALSE; + } + else{ + m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + theApp.bShowOutputWindow=TRUE; + } +} + +void CMainFrame::OnInitMenu(CMenu* pMenu) +{ + CMDIFrameWnd::OnInitMenu(pMenu); + +/* + if( (m_toolBar.GetStyle() & WS_VISIBLE) != 0 ){ + // make sure that toolbar entry is checked + pMenu->CheckMenuItem(ID_SHOW_TBAR, MF_CHECKED); + } + else{ + // make sure that toolbar entry is not checked + pMenu->CheckMenuItem(ID_SHOW_TBAR, MF_UNCHECKED); + } +*/ + if( (m_dlgBar.GetStyle() & WS_VISIBLE) != 0 ) + pMenu->CheckMenuItem(ID_PT_PROP, MF_CHECKED); + else pMenu->CheckMenuItem(ID_PT_PROP, MF_UNCHECKED); + + if((LuaConsole->GetStyle() & WS_VISIBLE) != 0 ) + pMenu->CheckMenuItem(ID_VIEW_LUACONSOLE, MF_CHECKED); + else pMenu->CheckMenuItem(ID_VIEW_LUACONSOLE, MF_UNCHECKED); +} + +void CMainFrame::OnViewLuaConsole() +{ + if( (m_LuaConsole.GetStyle() & WS_VISIBLE) != 0 ) + m_LuaConsole.ShowWindow(SW_HIDE); + else m_LuaConsole.ShowWindow(SW_SHOW); +} + +void CMainFrame::SetBar(int n) +{ + // Displays the requested toolbar configuration + switch(n) + { + // Note--the toolbars that are being turned on + // need to be last in the list, or bad things + // will happen. + case 1: // Show Femme toolbar(s) + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 2: // Show Femmview toolbar + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 3: // Show Beladraw toolbar(s) + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BD_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 4: // Show Belaview toolbar + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BV_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + +case 5: // Show hdraw toolbar(s) + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 6: // Show hview toolbar + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 7: // Show cdraw toolbar(s) + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + case 8: // Show cview toolbar + ShowControlBar(&m_BD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_FE_toolBar1,FALSE,TRUE); + ShowControlBar(&m_BV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_HV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,TRUE,FALSE); + ShowControlBar(&m_leftbar,TRUE,FALSE); + break; + + default: // Show no toolbar + ShowControlBar(&m_BV_toolBar1,FALSE,FALSE); + ShowControlBar(&m_BD_toolBar1,FALSE,FALSE); + ShowControlBar(&m_FV_toolBar1,FALSE,FALSE); + ShowControlBar(&m_FE_toolBar1,FALSE,FALSE); + ShowControlBar(&m_HV_toolBar1,FALSE,FALSE); + ShowControlBar(&m_HD_toolBar1,FALSE,FALSE); + ShowControlBar(&m_CD_toolBar1,FALSE,TRUE); + ShowControlBar(&m_CV_toolBar1,FALSE,TRUE); + ShowControlBar(&m_leftbar,FALSE,FALSE); + m_dlgBar.ShowWindow(SW_HIDE); + break; + } +} + +void CMainFrame::OnClose() +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)){ + bLinehook=FALSE; + if (hProc!=NULL) TerminateProcess(hProc,NULL); + hProc=NULL; + PostMessage(WM_CLOSE); + lua_error(lua,NULL); + } + + if (bLinehook!=ImportDXF) CFrameWnd::OnClose(); +} + + +void CMainFrame::OnPreferences() +{ + CPreferences dlg; + + if(dlg.DoModal()==IDOK) + { + // do a really ugly kludge to get the views + // to reload the color mappingsjust in case + // they have been changed. + theApp.ForceViewPrefReload(); + } +} + +void CMainFrame::OnHelpFinder() +{ + CString manualname=theApp.GetExecutablePath()+"manual.pdf"; + if (((int) ShellExecute(m_hWnd,"open",manualname,"","",SW_SHOWMAXIMIZED))<=32) + { + CString mymsg; + mymsg.Format("Couldn't open %s\n",manualname); + mymsg+="The most likely cause is that no viewer is registered\n"; + mymsg+="for PDF files. If you have a PDF viewer such as Acrobat\n"; + mymsg+="Reader or Ghostview installed, you can open this file manually."; + MsgBox(mymsg); + } +} + +void CMainFrame::OnHelpLicense() +{ + + CString licensename=theApp.GetExecutablePath()+"license.txt"; + if(((int) ShellExecute(m_hWnd,"open",licensename,"","",SW_SHOWNORMAL))<=32) + { + CString mymsg; + mymsg.Format("Couldn't open %s\n",licensename); + mymsg+="The most likely cause is that no viewer is registered\n"; + mymsg+="for RTF files. If you have an RTF viewer such as Wordpad,\n"; + mymsg+="Word, or OpenOffice installed, you can open this file manually."; + MsgBox(mymsg); + } + +} + +int CMainFrame::luaMinimize(lua_State *L) +{ +// theApp.GetMainWnd()->ShowWindow(SW_MINIMIZE); + theApp.GetMainWnd()->ShowWindow(SW_SHOWMINNOACTIVE); + m_luaWindowStatus=SW_SHOWMINNOACTIVE; + return 0; +} + +int CMainFrame::luaMaximize(lua_State *L) +{ + theApp.GetMainWnd()->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CMainFrame::luaRestore(lua_State *L) +{ + theApp.GetMainWnd()->ShowWindow(SW_RESTORE); + + return 0; +} + +int CMainFrame::luaResize(lua_State *L) +{ + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + CMainFrame *pMainFrame = (CMainFrame *)theApp.GetMainWnd(); + pMainFrame->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +BOOL CMainFrame::ResizeClient(int nWidth, int nHeight, BOOL bRedraw) +{ + RECT rcWnd; + GetClientRect (&rcWnd); + + if(nWidth != -1) rcWnd.right = nWidth; + if(nHeight != -1) rcWnd.bottom = nHeight; + if(!::AdjustWindowRectEx(&rcWnd,GetStyle(),(GetMenu()!=NULL), GetExStyle())) return FALSE; + + UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; + + if(!bRedraw) uFlags |= SWP_NOREDRAW; + + return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags); +} + +void CMainFrame::DockControlBarLeftOf(CToolBar* Bar, CToolBar* LeftOf) +{ + CRect rect; + DWORD dw; + UINT n; + + // get MFC to adjust the dimensions of all docked ToolBars + // so that GetWindowRect will be accurate + RecalcLayout(TRUE); + + LeftOf->GetWindowRect(&rect); + rect.OffsetRect(1,1); + dw=LeftOf->GetBarStyle(); + n = 0; + n = (dw&CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n; + n = (dw&CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n; + n = (dw&CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n; + n = (dw&CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n; + + // When we take the default parameters on rect, DockControlBar will dock + // each Toolbar on a seperate line. By calculating a rectangle, we + // are simulating a Toolbar being dragged to that location and docked. + DockControlBar(Bar,n,&rect); +} diff --git a/femm/MainFrm.h b/femm/MainFrm.h new file mode 100644 index 0000000..616fabc --- /dev/null +++ b/femm/MainFrm.h @@ -0,0 +1,91 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__50FDBCE8_9046_4FD7_907E_2A9DAEC8F0B6__INCLUDED_) +#define AFX_MAINFRM_H__50FDBCE8_9046_4FD7_907E_2A9DAEC8F0B6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "MDITabs.h" + +class CMainFrame : public CMDIFrameWnd +{ + DECLARE_DYNAMIC(CMainFrame) +public: + CMainFrame(); + +// Attributes +public: + COutBox m_dlgBar; + CToolBar m_FE_toolBar1; + CToolBar m_BD_toolBar1; + CToolBar m_HD_toolBar1; + CToolBar m_CD_toolBar1; + CToolBar m_FV_toolBar1; + CToolBar m_BV_toolBar1; + CToolBar m_HV_toolBar1; + CToolBar m_CV_toolBar1; + CToolBar m_leftbar; + CToolBar m_wndToolBar1,m_wndToolBar2; + CFont m_StatusBarFont; + CLuaConsoleDlg m_LuaConsole; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + + virtual void OnUpdateFrameTitle(BOOL bAddToTitle); + +// Implementation +public: + virtual ~CMainFrame(); + + void SetBar(int n); + BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw=FALSE); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int luaResize(lua_State *L); + void DockControlBarLeftOf(CToolBar* Bar, CToolBar* LeftOf); + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CMDITabs m_wndMDITabs; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnPtProp(); + afx_msg void OnInitMenu(CMenu* pMenu); + afx_msg void OnViewLuaConsole(); + afx_msg void OnClose(); + afx_msg void OnPreferences(); + afx_msg void OnHelpFinder(); + afx_msg void OnHelpLicense(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__50FDBCE8_9046_4FD7_907E_2A9DAEC8F0B6__INCLUDED_) diff --git a/femm/MakeABCDlg.cpp b/femm/MakeABCDlg.cpp new file mode 100644 index 0000000..dc74f09 --- /dev/null +++ b/femm/MakeABCDlg.cpp @@ -0,0 +1,76 @@ +// MakeABCDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "MakeABCDlg.h" + + +// CMakeABCDlg dialog + +IMPLEMENT_DYNAMIC(CMakeABCDlg, CDialog) + +CMakeABCDlg::CMakeABCDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMakeABCDlg::IDD, pParent) + , abcn(0) + , abcr(0) + , abcx(0) + , abcy(0) +{ + +} + +CMakeABCDlg::~CMakeABCDlg() +{ +} + +void CMakeABCDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Text(pDX, IDC_ABCN, abcn); + DDV_MinMaxInt(pDX, abcn, 1, 12); + DDX_Text(pDX, IDC_ABCR, abcr); + DDX_Text(pDX, IDC_ABCX, abcx); + DDX_Text(pDX, IDC_ABCY, abcy); + + DDX_Control(pDX, IDC_ABCN, m_IDC_ABCN); + DDX_Control(pDX, IDC_ABCR, m_IDC_ABCR); + DDX_Control(pDX, IDC_ABCX, m_IDC_ABCX); + DDX_Control(pDX, IDC_ABCY, m_IDC_ABCY); + DDX_Control(pDX, IDC_COMBO1, m_edgetype); +} + +BEGIN_MESSAGE_MAP(CMakeABCDlg, CDialog) + ON_CBN_SELCHANGE(IDC_COMBO1, &CMakeABCDlg::OnCbnSelchangeCombo1) +END_MESSAGE_MAP() + + +// CMakeABCDlg message handlers + +void CMakeABCDlg::OnCbnSelchangeCombo1() +{ + // TODO: Add your control notification handler code here +} + +BOOL CMakeABCDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_edgetype.AddString("Dirichlet"); + m_edgetype.AddString("Neumann"); + if (n<0) + { m_edgetype.SetCurSel(0); + m_edgetype.EnableWindow(0); + } + else m_edgetype.SetCurSel(n); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CMakeABCDlg::OnOK() +{ + n=m_edgetype.GetCurSel(); + CDialog::OnOK(); +} \ No newline at end of file diff --git a/femm/MakeABCDlg.h b/femm/MakeABCDlg.h new file mode 100644 index 0000000..3f197d7 --- /dev/null +++ b/femm/MakeABCDlg.h @@ -0,0 +1,36 @@ +#pragma once +#include "afxwin.h" + + +// CMakeABCDlg dialog + +class CMakeABCDlg : public CDialog +{ + DECLARE_DYNAMIC(CMakeABCDlg) + +public: + CMakeABCDlg(CWnd* pParent = NULL); // standard constructor + virtual ~CMakeABCDlg(); + +// Dialog Data + enum { IDD = IDD_MAKE_ABC }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + virtual void OnOK(); + DECLARE_MESSAGE_MAP() +public: + int abcn; + int n; + double abcr; + double abcx; + double abcy; + + CLuaEdit m_IDC_ABCN; + CLuaEdit m_IDC_ABCR; + CLuaEdit m_IDC_ABCX; + CLuaEdit m_IDC_ABCY; + afx_msg void OnCbnSelchangeCombo1(); + CComboBox m_edgetype; +}; diff --git a/femm/MaskProgress.cpp b/femm/MaskProgress.cpp new file mode 100644 index 0000000..b98dbf8 --- /dev/null +++ b/femm/MaskProgress.cpp @@ -0,0 +1,43 @@ +// MaskProgress.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "MaskProgress.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMaskProgress dialog + + +CMaskProgress::CMaskProgress(CWnd* pParent /*=NULL*/) + : CDialog(CMaskProgress::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMaskProgress) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CMaskProgress::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMaskProgress) + DDX_Control(pDX, IDC_PROGRESS1, m_mask_progress_status); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMaskProgress, CDialog) + //{{AFX_MSG_MAP(CMaskProgress) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMaskProgress message handlers diff --git a/femm/MaskProgress.h b/femm/MaskProgress.h new file mode 100644 index 0000000..1be7284 --- /dev/null +++ b/femm/MaskProgress.h @@ -0,0 +1,46 @@ +#if !defined(AFX_MASKPROGRESS_H__C617543A_0490_40D7_BF6F_DD1C35A4A4C0__INCLUDED_) +#define AFX_MASKPROGRESS_H__C617543A_0490_40D7_BF6F_DD1C35A4A4C0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MaskProgress.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMaskProgress dialog + +class CMaskProgress : public CDialog +{ +// Construction +public: + CMaskProgress(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMaskProgress) + enum { IDD = IDD_MASKPROGRESS }; + CProgressCtrl m_mask_progress_status; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMaskProgress) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMaskProgress) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MASKPROGRESS_H__C617543A_0490_40D7_BF6F_DD1C35A4A4C0__INCLUDED_) diff --git a/femm/MatDlg.cpp b/femm/MatDlg.cpp new file mode 100644 index 0000000..343e46f --- /dev/null +++ b/femm/MatDlg.cpp @@ -0,0 +1,322 @@ +// MatDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "MatDlg.h" +#include "BHData.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMatDlg dialog + + +CMatDlg::CMatDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMatDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMatDlg) + m_Cduct = 0.0; + m_BlockName = _T(""); + m_H_c = 0.0; + m_Jsrc = 0; + m_Lam_d = 0.0; + m_mu_x = 0.0; + m_mu_y = 0.0; + m_lam_fill = 0.0; + m_mu1label = _T(""); + m_mu2label = _T(""); + m_Theta_hn = 0.0; + m_Theta_hx = 0.0; + m_Theta_hy = 0.0; + m_NStrands = 0; + m_WireD = 0.0; + m_h1label = _T(""); + m_h2label = _T(""); + //}}AFX_DATA_INIT +} + + +void CMatDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMatDlg) + DDX_Control(pDX, IDC_STATIC_SYMBOL6, m_static6); + DDX_Control(pDX, IDC_STATIC_SYMBOL5, m_static5); + DDX_Control(pDX, IDC_STATIC_SYMBOL4, m_static4); + DDX_Control(pDX, IDC_STATIC_SYMBOL3, m_static3); + DDX_Control(pDX, IDC_STATIC_SYMBOL2, m_static2); + DDX_Control(pDX, IDC_STATIC_SYMBOL1, m_static1); + DDX_Control(pDX, IDC_BHEDIT, m_IDC_bhedit); + DDX_Control(pDX, IDC_NLCOMBO, m_nlcombo); + DDX_Control(pDX, IDC_LAM_DIR, m_lam_dir); + DDX_Text(pDX, IDC_CDUCT, m_Cduct); + DDX_Text(pDX, IDC_BLOCKNAME, m_BlockName); + DDX_Text(pDX, IDC_H_C, m_H_c); + DDX_Text(pDX, IDC_JR, m_Jsrc); + DDX_Text(pDX, IDC_LAM_D, m_Lam_d); + DDX_Text(pDX, IDC_MU_X, m_mu_x); + DDX_Text(pDX, IDC_MU_Y, m_mu_y); + DDX_Text(pDX, IDC_LAM_FILL, m_lam_fill); + DDV_MinMaxDouble(pDX, m_lam_fill, 0., 1.); + DDX_Text(pDX, IDC_MU1LABEL, m_mu1label); + DDX_Text(pDX, IDC_MU2LABEL, m_mu2label); + DDX_Text(pDX, IDC_THETA_H, m_Theta_hn); + DDV_MinMaxDouble(pDX, m_Theta_hn, 0., 90.); + DDX_Text(pDX, IDC_THETA_HX, m_Theta_hx); + DDV_MinMaxDouble(pDX, m_Theta_hx, 0., 90.); + DDX_Text(pDX, IDC_THETA_HY, m_Theta_hy); + DDV_MinMaxDouble(pDX, m_Theta_hy, 0., 90.); + DDX_Text(pDX, IDC_H1LABEL, m_h1label); + DDX_Text(pDX, IDC_H2LABEL, m_h2label); + DDX_Text(pDX, IDC_NSTRANDS, m_NStrands); + DDX_Text(pDX, IDC_WIRED, m_WireD); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CDUCT, m_IDC_Cduct); + DDX_Control(pDX, IDC_BLOCKNAME, m_IDC_BlockName); + DDX_Control(pDX, IDC_H_C, m_IDC_H_c); + DDX_Control(pDX, IDC_JR, m_IDC_Jr); + DDX_Control(pDX, IDC_LAM_D, m_IDC_Lam_d); + DDX_Control(pDX, IDC_MU_X, m_IDC_mu_x); + DDX_Control(pDX, IDC_MU_Y, m_IDC_mu_y); + DDX_Control(pDX, IDC_THETA_H, m_IDC_Theta_h); + DDX_Control(pDX, IDC_LAM_FILL, m_IDC_lam_fill); + DDX_Control(pDX, IDC_THETA_HX, m_IDC_Theta_hx); + DDX_Control(pDX, IDC_THETA_HY, m_IDC_Theta_hy); + DDX_Control(pDX, IDC_NSTRANDS, m_IDC_NStrands); + DDX_Control(pDX, IDC_WIRED, m_IDC_WireD); +} + + +BEGIN_MESSAGE_MAP(CMatDlg, CDialog) + //{{AFX_MSG_MAP(CMatDlg) + ON_BN_CLICKED(IDC_BHEDIT, OnBhedit) + ON_CBN_SELCHANGE(IDC_LAM_DIR, OnSelchangeLamDir) + ON_CBN_SELCHANGE(IDC_NLCOMBO, OnSelchangeNlcombo) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMatDlg message handlers + +BOOL CMatDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if(LamType!=0) LamType++; + else{ + if( (m_Lam_d!=0) || (m_lam_fill!=1) ) LamType=1; + } + m_lam_dir.SetCurSel(LamType); + OnSelchangeLamDir(); + + m_nlcombo.SetCurSel(m_nlflag); + OnSelchangeNlcombo(); + + symbfont.CreateFont(0, 0, 0, 0, FW_BOLD, TRUE, 0, 0, + SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, DEFAULT_PITCH | FF_DECORATIVE, "Symbol"); + m_static1.SetFont(&symbfont); + m_static2.SetFont(&symbfont); + m_static3.SetFont(&symbfont); + m_static4.SetFont(&symbfont); + m_static5.SetFont(&symbfont); + m_static6.SetFont(&symbfont); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CMatDlg::OnOK() +{ + if (!UpdateData()) return; + + for(int nn=0;nn3){ + IsWire(); + if(m_WireD<=0) + { + // catch case where zero wire diameter + // is erroneously specified + m_WireD=0; + m_lam_dir.SetCurSel(0); + LamType=0; + } + } + + UpdateData(FALSE); + CDialog::OnOK(); +} + +void CMatDlg::OnBhedit() +{ + // TODO: Add your control notification handler code here + CBHData dlg; + + if(m_nlflag==FALSE) + { + m_nlflag=TRUE; + m_nlcombo.SetCurSel(m_nlflag); + OnSelchangeNlcombo(); + } + + UpdateData(); + dlg.m_Bdata=BData; + dlg.m_Hdata=HData; + dlg.m_BHname=m_BlockName; + if(dlg.DoModal()==IDOK){ + BData=dlg.m_Bdata; + HData=dlg.m_Hdata; + return; + } + + return; +} + +void CMatDlg::OnSelchangeLamDir() +{ + switch(m_lam_dir.GetCurSel()) + { + case 1: + m_IDC_Lam_d.EnableWindow( TRUE ); + m_IDC_lam_fill.EnableWindow( TRUE ); + m_IDC_NStrands.EnableWindow(FALSE); + m_IDC_WireD.EnableWindow(FALSE); + m_IDC_H_c.EnableWindow(FALSE); + m_H_c=0; UpdateData(FALSE); + break; + + case 2: + m_IDC_Lam_d.EnableWindow( TRUE ); + m_IDC_lam_fill.EnableWindow( TRUE ); + m_IDC_NStrands.EnableWindow(FALSE); + m_IDC_WireD.EnableWindow(FALSE); + m_IDC_H_c.EnableWindow(FALSE); + m_H_c=0; UpdateData(FALSE); + break; + + case 3: + m_IDC_Lam_d.EnableWindow( TRUE ); + m_IDC_lam_fill.EnableWindow( TRUE ); + m_IDC_NStrands.EnableWindow(FALSE); + m_IDC_WireD.EnableWindow(FALSE); + m_IDC_H_c.EnableWindow(FALSE); + m_H_c=0; UpdateData(FALSE); + break; + + case 4: // round magnet wire + case 7: // square magnet wire + m_IDC_NStrands.SetWindowText("1"); m_NStrands=1; + m_IDC_NStrands.EnableWindow(FALSE); + m_IDC_WireD.EnableWindow(TRUE); + IsWire(); + break; + + case 5: // plain stranded + case 6: // litz + case 8: // 10% CCA + case 9: // 15% CCA + m_IDC_NStrands.EnableWindow(TRUE); + m_IDC_WireD.EnableWindow(TRUE); + IsWire(); + break; + + default: + m_IDC_Lam_d.EnableWindow( FALSE ); + m_IDC_lam_fill.EnableWindow( FALSE ); + m_IDC_NStrands.EnableWindow(FALSE); + m_IDC_WireD.EnableWindow(FALSE); + m_IDC_H_c.EnableWindow(TRUE); + break; + } + +} + +void CMatDlg::OnSelchangeNlcombo() +{ + m_nlflag=m_nlcombo.GetCurSel(); + UpdateData(TRUE); + if(m_nlflag==TRUE) + { + m_IDC_Theta_hx.EnableWindow( FALSE ); + m_IDC_Theta_hy.EnableWindow( FALSE ); + m_IDC_mu_x.EnableWindow( FALSE ); + m_IDC_mu_y.EnableWindow( FALSE ); + + m_IDC_bhedit.EnableWindow( TRUE ); + m_IDC_Theta_h.EnableWindow( TRUE ); + + if(m_lam_dir.GetCurSel()>3){ + m_lam_dir.SetCurSel(0); + OnSelchangeLamDir(); + } + } + else{ + m_IDC_Theta_hx.EnableWindow( TRUE ); + m_IDC_Theta_hy.EnableWindow( TRUE ); + m_IDC_mu_x.EnableWindow( TRUE ); + m_IDC_mu_y.EnableWindow( TRUE ); + + m_IDC_bhedit.EnableWindow( FALSE ); + m_IDC_Theta_h.EnableWindow( FALSE ); + } + UpdateData(FALSE); + +} + +void CMatDlg::IsWire() +{ + // if the material is specified to be a wire, + // make sure the permeability and other properties + // are consistent with a wire. + UpdateData(TRUE); + m_mu_x=1; + m_mu_y=1; + m_H_c=0; + m_Jsrc=0; + m_Lam_d=0; + m_lam_fill=1; + m_Theta_hn=0; + m_Theta_hx=0; + m_Theta_hy = 0.0; + BData.Empty(); + HData.Empty(); + m_nlflag=FALSE; + m_nlcombo.SetCurSel(m_nlflag); + m_IDC_Lam_d.EnableWindow(FALSE); + m_IDC_lam_fill.EnableWindow(FALSE); + m_IDC_Theta_hx.EnableWindow( TRUE ); + m_IDC_Theta_hy.EnableWindow( TRUE ); + m_IDC_mu_x.EnableWindow( TRUE ); + m_IDC_mu_y.EnableWindow( TRUE ); + m_IDC_H_c.EnableWindow( FALSE ); + m_IDC_bhedit.EnableWindow( FALSE ); + m_IDC_Theta_h.EnableWindow( FALSE ); + UpdateData(FALSE); +} diff --git a/femm/MatDlg.h b/femm/MatDlg.h new file mode 100644 index 0000000..11837ac --- /dev/null +++ b/femm/MatDlg.h @@ -0,0 +1,77 @@ +// MatDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMatDlg dialog + +class CMatDlg : public CDialog +{ +// Construction +public: + CMatDlg(CWnd* pParent = NULL); // standard constructor + CString BData,HData; + int LamType; + BOOL m_nlflag; + CArray namelist; + + CFont symbfont; + CFont bfont; + void IsWire(); +// Dialog Data + //{{AFX_DATA(CMatDlg) + enum { IDD = IDD_MATDLG }; + CStatic m_static6; + CStatic m_static5; + CStatic m_static4; + CStatic m_static3; + CStatic m_static2; + CStatic m_static1; + CButton m_IDC_bhedit; + CComboBox m_nlcombo; + CComboBox m_lam_dir; + double m_Cduct; + CString m_BlockName; + double m_H_c; + CComplex m_Jsrc; + double m_Lam_d; + double m_mu_x; + double m_mu_y; + double m_lam_fill; + CString m_mu1label; + CString m_mu2label; + double m_Theta_hn; + double m_Theta_hx; + double m_Theta_hy; + double m_WireD; + int m_NStrands; + CString m_h1label; + CString m_h2label; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMatDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMatDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnBhedit(); + afx_msg void OnSelchangeLamDir(); + afx_msg void OnSelchangeNlcombo(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_Cduct, m_IDC_BlockName, m_IDC_H_c; + CLuaEdit m_IDC_Jr, m_IDC_Lam_d; + CLuaEdit m_IDC_mu_x, m_IDC_mu_y, m_IDC_Theta_h, m_IDC_lam_fill; + CLuaEdit m_IDC_Theta_hx, m_IDC_Theta_hy; + CLuaEdit m_IDC_NStrands, m_IDC_WireD; +}; diff --git a/femm/MirrorDlg.cpp b/femm/MirrorDlg.cpp new file mode 100644 index 0000000..a1ac576 --- /dev/null +++ b/femm/MirrorDlg.cpp @@ -0,0 +1,53 @@ +// MirrorDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "MirrorDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMirrorDlg dialog + + +CMirrorDlg::CMirrorDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMirrorDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMirrorDlg) + m_pax = 0.0; + m_pay = 0.0; + m_pbx = 0.0; + m_pby = 0.0; + //}}AFX_DATA_INIT +} + + +void CMirrorDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMirrorDlg) + DDX_Text(pDX, IDC_PAX, m_pax); + DDX_Text(pDX, IDC_PAY, m_pay); + DDX_Text(pDX, IDC_PBX, m_pbx); + DDX_Text(pDX, IDC_PBY, m_pby); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_PAX, m_IDC_PAX); + DDX_Control(pDX, IDC_PAY, m_IDC_PAY); + DDX_Control(pDX, IDC_PBX, m_IDC_PBX); + DDX_Control(pDX, IDC_PBY, m_IDC_PBY); +} + + +BEGIN_MESSAGE_MAP(CMirrorDlg, CDialog) + //{{AFX_MSG_MAP(CMirrorDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMirrorDlg message handlers diff --git a/femm/MirrorDlg.h b/femm/MirrorDlg.h new file mode 100644 index 0000000..c60e42c --- /dev/null +++ b/femm/MirrorDlg.h @@ -0,0 +1,42 @@ +// MirrorDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMirrorDlg dialog + +#include "afxwin.h" +class CMirrorDlg : public CDialog +{ +// Construction +public: + CMirrorDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMirrorDlg) + enum { IDD = IDD_MIRRORDLG }; + double m_pax; + double m_pay; + double m_pbx; + double m_pby; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMirrorDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMirrorDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_PAX, m_IDC_PAY; + CLuaEdit m_IDC_PBX, m_IDC_PBY; +}; diff --git a/femm/MyCommandLineInfo.cpp b/femm/MyCommandLineInfo.cpp new file mode 100644 index 0000000..1f458ad --- /dev/null +++ b/femm/MyCommandLineInfo.cpp @@ -0,0 +1,71 @@ +// MyCommandLineInfo.cpp: implementation of the CMyCommandLineInfo class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "femm.h" +#include "MyCommandLineInfo.h" +#include "afxwin.h" +#include "lua.h" + +extern lua_State * lua; +extern int m_luaWindowStatus; + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +extern CString luascriptname; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CMyCommandLineInfo::CMyCommandLineInfo() +{ +// m_luaWindowStatus=SW_SHOW; // default unless otherwise +} + +CMyCommandLineInfo::~CMyCommandLineInfo() +{ + +} + +void CMyCommandLineInfo::ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast ) +{ + CString theparam; + theparam.Format("%s",lpszParam); + theparam.MakeLower(); + + if(theparam.Left(11)=="lua-script=" && bFlag==1) + luascriptname=theparam.Mid(11); + + if (theparam=="windowhide" && bFlag==1) m_luaWindowStatus=SW_SHOWMINNOACTIVE; + if (theparam=="hidewindow" && bFlag==1) m_luaWindowStatus=SW_SHOWMINNOACTIVE; + + if (theparam=="filelink") ((CFemmApp *)AfxGetApp())->bFileLink=TRUE; + + if (theparam.Left(8)=="lua-var=" && bFlag==1) + { + CString varname; + CString vardata; + for (int pos=8;pos 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMyCommandLineInfo : public CCommandLineInfo +{ +public: +// int luavarstart; +// bool parseluastack; +// CString lastparameter; +// int parameterno; +// bool luafilenameready; + CMyCommandLineInfo(); + virtual ~CMyCommandLineInfo(); + virtual void ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast ); + + + + +}; + +#endif // !defined(AFX_MYCOMMANDLINEINFO_H__9571FF44_5FF5_11D5_98F9_005004B84D6A__INCLUDED_) diff --git a/femm/MyMsgBox.cpp b/femm/MyMsgBox.cpp new file mode 100644 index 0000000..9614d6a --- /dev/null +++ b/femm/MyMsgBox.cpp @@ -0,0 +1,43 @@ +// MyMsgBox.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "MyMsgBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMyMsgBox dialog + + +CMyMsgBox::CMyMsgBox(CWnd* pParent /*=NULL*/) + : CDialog(CMyMsgBox::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMyMsgBox) + m_mymsg = _T(""); + //}}AFX_DATA_INIT +} + + +void CMyMsgBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMyMsgBox) + DDX_Text(pDX, IDC_MYMSGBOXOUTPUT, m_mymsg); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMyMsgBox, CDialog) + //{{AFX_MSG_MAP(CMyMsgBox) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMyMsgBox message handlers diff --git a/femm/MyMsgBox.h b/femm/MyMsgBox.h new file mode 100644 index 0000000..8dcaf45 --- /dev/null +++ b/femm/MyMsgBox.h @@ -0,0 +1,35 @@ +// MyMsgBox.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMyMsgBox dialog + +class CMyMsgBox : public CDialog +{ +// Construction +public: + CMyMsgBox(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMyMsgBox) + enum { IDD = IDD_MYMSGBOX }; + CString m_mymsg; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMyMsgBox) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMyMsgBox) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/MyRecentFileList.cpp b/femm/MyRecentFileList.cpp new file mode 100644 index 0000000..8c5c312 --- /dev/null +++ b/femm/MyRecentFileList.cpp @@ -0,0 +1,181 @@ +#include "stdafx.h" +#include "MyRecentFileList.h" + +// Header information required to use obscure MFC functions +UINT AFXAPI AfxGetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax); + +// extra function cribbed from FILELIST.CPP in the MFC source +AFX_STATIC void AFXAPI _AfxAbbreviateName(LPTSTR lpszCanon, int cchMax, BOOL bAtLeastName) +{ + int cchFullPath, cchFileName, cchVolName; + const TCHAR* lpszCur; + const TCHAR* lpszBase; + const TCHAR* lpszFileName; + + lpszBase = lpszCanon; + cchFullPath = lstrlen(lpszCanon); + + cchFileName = AfxGetFileName(lpszCanon, NULL, 0) - 1; + lpszFileName = lpszBase + (cchFullPath-cchFileName); + + // If cchMax is more than enough to hold the full path name, we're done. + // This is probably a pretty common case, so we'll put it first. + if (cchMax >= cchFullPath) + return; + + // If cchMax isn't enough to hold at least the basename, we're done + if (cchMax < cchFileName) + { + lstrcpy(lpszCanon, (bAtLeastName) ? lpszFileName : ""); + return; + } + + // Calculate the length of the volume name. Normally, this is two characters + // (e.g., "C:", "D:", etc.), but for a UNC name, it could be more (e.g., + // "\\server\share"). + // + // If cchMax isn't enough to hold at least \...\, the + // result is the base filename. + + lpszCur = lpszBase + 2; // Skip "C:" or leading "\\" + + if (lpszBase[0] == '\\' && lpszBase[1] == '\\') // UNC pathname + { + // First skip to the '\' between the server name and the share name, + while (*lpszCur != '\\') + { + lpszCur = _tcsinc(lpszCur); + ASSERT(*lpszCur != '\0'); + } + } + // if a UNC get the share name, if a drive get at least one directory + ASSERT(*lpszCur == '\\'); + // make sure there is another directory, not just c:\filename.ext + if (cchFullPath - cchFileName > 3) + { + lpszCur = _tcsinc(lpszCur); + while (*lpszCur != '\\') + { + lpszCur = _tcsinc(lpszCur); + ASSERT(*lpszCur != '\0'); + } + } + ASSERT(*lpszCur == '\\'); + + cchVolName = (int) lpszCur - (int) lpszBase; + if (cchMax < cchVolName + 5 + cchFileName) + { + lstrcpy(lpszCanon, lpszFileName); + return; + } + + // Now loop through the remaining directory components until something + // of the form \...\\ fits. + // + // Assert that the whole filename doesn't fit -- this should have been + // handled earlier. + + ASSERT(cchVolName + (int)lstrlen(lpszCur) > cchMax); + while (cchVolName + 4 + (int)lstrlen(lpszCur) > cchMax) + { + do + { + lpszCur = _tcsinc(lpszCur); + ASSERT(*lpszCur != '\0'); + } + while (*lpszCur != '\\'); + } + + // Form the resultant string and we're done. + lpszCanon[cchVolName] = '\0'; + lstrcat(lpszCanon, _T("\\...")); + lstrcat(lpszCanon, lpszCur); +} + +BOOL MyCRecentFileList::GetDisplayName(CString& strName, int nIndex, + LPCTSTR lpszCurDir, int nCurDir, BOOL bAtLeastName) +{ + ASSERT(lpszCurDir == NULL || AfxIsValidString(lpszCurDir, nCurDir)); + + ASSERT(m_arrNames != NULL); + ASSERT(nIndex < m_nSize); + if (m_arrNames[nIndex].IsEmpty()) + return FALSE; + + LPTSTR lpch = strName.GetBuffer(_MAX_PATH); + lstrcpy(lpch, m_arrNames[nIndex]); + + // abbreviate name based on what will fit in limited space + _AfxAbbreviateName(lpch, m_nMaxDisplayLength, bAtLeastName); + + strName.ReleaseBuffer(); + + return TRUE; +} + +void MyCRecentFileList::UpdateMenu(CCmdUI* pCmdUI) +{ + ASSERT(m_arrNames != NULL); + + CMenu* pMenu = pCmdUI->m_pMenu; + if (m_strOriginal.IsEmpty() && pMenu != NULL) + pMenu->GetMenuString(pCmdUI->m_nID, m_strOriginal, MF_BYCOMMAND); + + if (m_arrNames[0].IsEmpty()) + { + // no MRU files + if (!m_strOriginal.IsEmpty()) + pCmdUI->SetText(m_strOriginal); + pCmdUI->Enable(FALSE); + return; + } + + if (pCmdUI->m_pMenu == NULL) + return; + + int iMRU; + for (iMRU = 0; iMRU < m_nSize; iMRU++) + pCmdUI->m_pMenu->DeleteMenu(pCmdUI->m_nID + iMRU, MF_BYCOMMAND); + + TCHAR szCurDir[_MAX_PATH]; + GetCurrentDirectory(_MAX_PATH, szCurDir); + int nCurDir = lstrlen(szCurDir); + ASSERT(nCurDir >= 0); + szCurDir[nCurDir] = '\\'; + szCurDir[++nCurDir] = '\0'; + + CString strName; + CString strTemp; + for (iMRU = 0; iMRU < m_nSize; iMRU++) + { + if (!GetDisplayName(strName, iMRU, szCurDir, nCurDir)) + break; + + // double up any '&' characters so they are not underlined + LPCTSTR lpszSrc = strName; + LPTSTR lpszDest = strTemp.GetBuffer(strName.GetLength()*2); + while (*lpszSrc != 0) + { + if (*lpszSrc == '&') + *lpszDest++ = '&'; + if (_istlead(*lpszSrc)) + *lpszDest++ = *lpszSrc++; + *lpszDest++ = *lpszSrc++; + } + *lpszDest = 0; + strTemp.ReleaseBuffer(); + + // insert mnemonic + the file name + TCHAR buf[10]; + wsprintf(buf, _T("&%d "), (iMRU+1+m_nStart) % 10); + pCmdUI->m_pMenu->InsertMenu(pCmdUI->m_nIndex++, + MF_STRING | MF_BYPOSITION, pCmdUI->m_nID++, + CString(buf) + strTemp); + } + + // update end menu count + pCmdUI->m_nIndex--; // point to last menu added + pCmdUI->m_nIndexMax = pCmdUI->m_pMenu->GetMenuItemCount(); + + pCmdUI->m_bEnableChanged = TRUE; // all the added items are enabled +} diff --git a/femm/MyRecentFileList.h b/femm/MyRecentFileList.h new file mode 100644 index 0000000..3ec5ffe --- /dev/null +++ b/femm/MyRecentFileList.h @@ -0,0 +1,18 @@ +#ifndef _MYRECENTFILELIST_H_ +#define _MYRECENTFILELIST_H_ + +#include < afxadv.h> // for CRecentFileList + +class MyCRecentFileList : public CRecentFileList { +public: + MyCRecentFileList(UINT nStart, LPCTSTR lpszSection, + LPCTSTR lpszEntryFormat, int nSize, + int nMaxDispLen = AFX_ABBREV_FILENAME_LEN) + : CRecentFileList(nStart, lpszSection,lpszEntryFormat, nSize, + nMaxDispLen) {} + virtual BOOL MyCRecentFileList::GetDisplayName(CString& strName, int nIndex, + LPCTSTR lpszCurDir, int nCurDir, BOOL bAtLeastName= TRUE); + virtual void UpdateMenu(CCmdUI* pCmdUI); +}; // class VIRecentFileList + +#endif // _MYRECENTFILELIST_H_ \ No newline at end of file diff --git a/femm/MyTabCtrl.cpp b/femm/MyTabCtrl.cpp new file mode 100644 index 0000000..0ba9a1c --- /dev/null +++ b/femm/MyTabCtrl.cpp @@ -0,0 +1,145 @@ +// MyTabCtrl.cpp : implementation file +// +///////////////////////////////////////////////////// +// This class is provided as is and Ben Hill takes no +// responsibility for any loss of any kind in connection +// to this code. +///////////////////////////////////////////////////// +// Is is meant purely as a educational tool and may +// contain bugs. +///////////////////////////////////////////////////// +// ben@shido.fsnet.co.uk +// http://www.shido.fsnet.co.uk +///////////////////////////////////////////////////// +// Thanks to a mystery poster in the C++ forum on +// www.codeguru.com I can't find your name to say thanks +// for your Control drawing code. If you are that person +// thank you very much. I have been able to use some of +// you ideas to produce this sample application. +///////////////////////////////////////////////////// + +#include "stdafx.h" +#include "femm.h" +#include "MyTabCtrl.h" + +#include "Pref.h" +#include "viewpref.h" +#include "bd_Pref.h" +#include "bv_Pref.h" +#include "hd_Pref.h" +#include "hv_Pref.h" +#include "cd_Pref.h" +#include "cv_Pref.h" +#include "GeneralPrefs.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMyTabCtrl + +CMyTabCtrl::CMyTabCtrl() +{ + m_tabPages[0]=new CPref; + m_tabPages[1]=new CViewPref; + m_tabPages[2]=new bdCPref; + m_tabPages[3]=new bvCPref; + m_tabPages[4]=new hdCPref; + m_tabPages[5]=new hvCPref; + m_tabPages[6]=new cdCPref; + m_tabPages[7]=new cvCPref; + m_tabPages[8]=new CGeneralPrefs; + + m_nNumberOfPages=9; +} + +CMyTabCtrl::~CMyTabCtrl() +{ + for(int nCount=0; nCount < m_nNumberOfPages; nCount++){ + delete m_tabPages[nCount]; + } +} + +void CMyTabCtrl::Init() +{ + m_tabCurrent=0; + + m_tabPages[0]->Create(IDD_EDITPREF, this); + m_tabPages[1]->Create(IDD_VIEWPREF, this); + m_tabPages[2]->Create(IDD_BD_PREF, this); + m_tabPages[3]->Create(IDD_BV_PREF, this); + m_tabPages[4]->Create(IDD_HD_PREF, this); + m_tabPages[5]->Create(IDD_HV_PREF, this); + m_tabPages[6]->Create(IDD_CD_PREF, this); + m_tabPages[7]->Create(IDD_CV_PREF, this); + m_tabPages[8]->Create(IDD_GENPREFS, this); + + + m_tabPages[0]->ShowWindow(SW_SHOW); + m_tabPages[1]->ShowWindow(SW_HIDE); + m_tabPages[2]->ShowWindow(SW_HIDE); + m_tabPages[3]->ShowWindow(SW_HIDE); + m_tabPages[4]->ShowWindow(SW_HIDE); + m_tabPages[5]->ShowWindow(SW_HIDE); + m_tabPages[6]->ShowWindow(SW_HIDE); + m_tabPages[7]->ShowWindow(SW_HIDE); + m_tabPages[8]->ShowWindow(SW_HIDE); + + SetRectangle(); +} + +void CMyTabCtrl::SetRectangle() +{ + CRect tabRect, itemRect; + int nX, nY, nXc, nYc; + + GetClientRect(&tabRect); + GetItemRect(0, &itemRect); + + nX=itemRect.left; + nY=itemRect.bottom+1; + nXc=tabRect.right-itemRect.left-1; + nYc=tabRect.bottom-nY-1; + + m_tabPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW); + for(int nCount=1; nCount < m_nNumberOfPages; nCount++){ + m_tabPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW); + } +} + +void CMyTabCtrl::WritePrefs() +{ + ((CPref *) m_tabPages[0])->WritePrefs(); + ((CViewPref *) m_tabPages[1])->WritePrefs(); + ((bdCPref *) m_tabPages[2])->WritePrefs(); + ((bvCPref *) m_tabPages[3])->WritePrefs(); + ((hdCPref *) m_tabPages[4])->WritePrefs(); + ((hvCPref *) m_tabPages[5])->WritePrefs(); + ((cdCPref *) m_tabPages[6])->WritePrefs(); + ((cvCPref *) m_tabPages[7])->WritePrefs(); + ((CGeneralPrefs *) m_tabPages[8])->WritePrefs(); +} + +BEGIN_MESSAGE_MAP(CMyTabCtrl, CTabCtrl) + //{{AFX_MSG_MAP(CMyTabCtrl) + ON_WM_LBUTTONDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMyTabCtrl message handlers + +void CMyTabCtrl::OnLButtonDown(UINT nFlags, CPoint point) +{ + CTabCtrl::OnLButtonDown(nFlags, point); + + if(m_tabCurrent != GetCurFocus()){ + m_tabPages[m_tabCurrent]->ShowWindow(SW_HIDE); + m_tabCurrent=GetCurFocus(); + m_tabPages[m_tabCurrent]->ShowWindow(SW_SHOW); + m_tabPages[m_tabCurrent]->SetFocus(); + } +} diff --git a/femm/MyTabCtrl.h b/femm/MyTabCtrl.h new file mode 100644 index 0000000..fd2fdf3 --- /dev/null +++ b/femm/MyTabCtrl.h @@ -0,0 +1,54 @@ +#if !defined(AFX_MYTABCTRL_H__F3E8650F_019C_479F_9E0F_60FE1181F49F__INCLUDED_) +#define AFX_MYTABCTRL_H__F3E8650F_019C_479F_9E0F_60FE1181F49F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MyTabCtrl.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMyTabCtrl window + +class CMyTabCtrl : public CTabCtrl +{ +// Construction +public: + CMyTabCtrl(); + CDialog *m_tabPages[12]; + int m_tabCurrent; + int m_nNumberOfPages; + +// Attributes +public: + +// Operations +public: + void Init(); + void SetRectangle(); + void WritePrefs(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMyTabCtrl) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMyTabCtrl(); + + // Generated message map functions +protected: + //{{AFX_MSG(CMyTabCtrl) + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MYTABCTRL_H__F3E8650F_019C_479F_9E0F_60FE1181F49F__INCLUDED_) diff --git a/femm/NOSEBL.CPP b/femm/NOSEBL.CPP new file mode 100644 index 0000000..6b93113 --- /dev/null +++ b/femm/NOSEBL.CPP @@ -0,0 +1,298 @@ +#include "stdafx.h" +#include +#include +#include "nosebl.h" +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + InGroup=0; + BoundaryMarker=""; +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CComplex CNode::CC() +{ + return CComplex(x,y); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + MaxSideLength=-1; + BoundaryMarker=""; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + ArcLength=90.; + MaxSideLength=10.; + mySideLength=1; + BoundaryMarker=""; + InGroup=0; + NormalDirection=TRUE; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + MagDir=0.; + Turns=1; + IsSelected=FALSE; + BlockType=""; + InCircuit=""; + InGroup=0; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + mu_x=1.; + mu_y=1.; // permeabilities, relative + H_c=0.; // magnetization, A/m + Jsrc=0; // applied current density, MA/m^2 + Cduct=0.; // conductivity of the material, MS/m + Lam_d=0.; // lamination thickness, mm + Theta_hn=0.; // hysteresis angle, degrees + Theta_hx=0.; // hysteresis angle, degrees + Theta_hy=0.; // hysteresis angle, degrees + Theta_m=0.; // magnetization direction, degrees; + LamFill=1.; // lamination fill factor; + LamType=0; // type of lamination; + WireD=0; // strand diameter, mm + NStrands=0; // number of strands per wire + + BHpoints=0; +} + +CMaterialProp::~CMaterialProp() +{ + if(BHpoints>0) free(BHdata); +} + +void CMaterialProp::StripBHData(CString &b, CString &h) +{ + int i,k; + char *buff,*nptr,*endptr; + double z; + CArray B; + CArray H; + + if (BHpoints>0) free(BHdata); + B.RemoveAll(); + H.RemoveAll(); + + k=b.GetLength()+10; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,b); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; //catch special case + else nptr=endptr; + if(B.GetSize()>0){ // enforce monotonicity + if (z<=B[B.GetSize()-1]) + break; + } + else if(z!=0) B.Add(0); + B.Add(z); + } + free(buff); + + k=h.GetLength()+10; + buff=(char *)calloc(k,sizeof(char)); + strcpy(buff,h); + nptr=buff; + while (sscanf(nptr,"%lf",&z)!=EOF){ + z=strtod(nptr,&endptr ); + if(nptr==endptr) nptr++; + else nptr=endptr; + if(H.GetSize()>0){ + if (z<=H[H.GetSize()-1]) + break; + } + else if(z!=0) H.Add(0); + H.Add(z); + } + + k=(int) B.GetSize(); + if ((int) H.GetSize()1){ + BHpoints=k; + { + BHdata=(CComplex *)calloc(k,sizeof(CComplex)); + for(i=0;iy){ + z=y; + y=x; + x=z; + } +} + +CQuadPoint::CQuadPoint() +{ + n0=n1=-1; + w0=w1=0; +} \ No newline at end of file diff --git a/femm/NOSEBL.H b/femm/NOSEBL.H new file mode 100644 index 0000000..9db8d73 --- /dev/null +++ b/femm/NOSEBL.H @@ -0,0 +1,248 @@ +namespace femmedata +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + CString BoundaryMarker; + int InGroup; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength; + CString BoundaryMarker; + int InGroup; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL NormalDirection; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength,mySideLength; + CString BoundaryMarker; + int InGroup; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + double MagDir; + int Turns; + BOOL IsSelected; + CString BlockType; + CString InCircuit; + CString MagDirFctn; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CMaterialProp(); + ~CMaterialProp(); + void StripBHData(CString &b, CString &h); + void BHDataToCString(CString &b, CString &h); + + CString BlockName; + double mu_x,mu_y; // permeabilities, relative + + int BHpoints; // number of B-H datapoints; + CComplex *BHdata; // array of B-H pairs; + + int LamType; // flag that tells how block is laminated; + // 0 = not laminated or laminated in plane; + // 1 = laminated in the x-direction; + // 2 = laminated in the y-direction; + double LamFill; // lamination fill factor, dimensionless; + double Theta_m; // direction of the magnetization, degrees + double H_c; // magnetization, A/m + CComplex Jsrc; // applied current density, MA/m^2 + double Cduct; // conductivity of the material, MS/m + double Lam_d; // lamination thickness, mm + double Theta_hn; // max hysteresis angle, degrees, for nonlinear problems + double Theta_hx; // hysteresis angle, degrees, x-direction + double Theta_hy; // and y-direction, for anisotropic linear problems. + int NStrands; // number of strands per wire + double WireD; // strand diameter, mm + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + int BdryFormat; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + // 3 = SDI + // 4 = Periodic + // 5 = Antiperiodic + // 6 = Periodic air gap element + // 7 = Antiperiodic air gap element + + double A0,A1,A2,phi; // set value of A for BdryFormat=0; + + double Mu,Sig; // material properties necessary to apply + // eddy current BC + + CComplex c0,c1; // coefficients for mixed BC + + double InnerAngle; // rotation of inner bdry for air gap element + double OuterAngle; // rotation of outer bdry for air gap element + + // TO DO: ``flux pipe?'' and ''line currents'' + // Line currents might be redundant, since we already have magnetization. + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + CComplex Jp; // applied point current, Amps + CComplex Ap; // prescribed nodal value of vector potential; + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + CComplex Amps; + int CircType; + + private: + +}; + +class CPeriodicBoundary +{ + public: + + CPeriodicBoundary(); + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + int nseg; // number of segs with this bc + int narc; // number of arcs with this bc + int seg[2]; // (arc)segments to which is applied + + private: +}; + +class CCommonPoint +{ + public: + + CCommonPoint(); + void Order(); + + int x,y,t; + + private: +}; + +class CAirGapElement +{ + public: + + CAirGapElement(); + ~CAirGapElement(); + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + + int totalArcElements; // total elements in the initial meshing + double totalArcLength; // sum of the angles of all constituent arcs + double ri,ro; // inner and outer radii of the air gap element + double InnerAngle; + double OuterAngle; + CComplex agc; // center of the air gap element + int *node; // node numbers that are part of the air gap element + + private: +}; + +class CQuadPoint +{ + public: + + CQuadPoint(); + + int n0,n1; + double w0,w1; +}; + +} + +using namespace femmedata; \ No newline at end of file diff --git a/femm/NewDocDlg.cpp b/femm/NewDocDlg.cpp new file mode 100644 index 0000000..a0bd125 --- /dev/null +++ b/femm/NewDocDlg.cpp @@ -0,0 +1,59 @@ +// NewDocDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "NewDocDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CNewDocDlg dialog + + +CNewDocDlg::CNewDocDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewDocDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewDocDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CNewDocDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewDocDlg) + DDX_Control(pDX, IDC_DOCTYPES, m_doctypes); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewDocDlg, CDialog) + //{{AFX_MSG_MAP(CNewDocDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNewDocDlg message handlers + +BOOL CNewDocDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_doctypes.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CNewDocDlg::OnOK() +{ + doctype=m_doctypes.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/NewDocDlg.h b/femm/NewDocDlg.h new file mode 100644 index 0000000..8e0f3a6 --- /dev/null +++ b/femm/NewDocDlg.h @@ -0,0 +1,48 @@ +#if !defined(AFX_NEWDOCDLG_H__986FD914_D49F_418D_9D0F_56936AB0744B__INCLUDED_) +#define AFX_NEWDOCDLG_H__986FD914_D49F_418D_9D0F_56936AB0744B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewDocDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CNewDocDlg dialog + +class CNewDocDlg : public CDialog +{ +// Construction +public: + CNewDocDlg(CWnd* pParent = NULL); // standard constructor + int doctype; + +// Dialog Data + //{{AFX_DATA(CNewDocDlg) + enum { IDD = IDD_NEWDOC }; + CComboBox m_doctypes; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNewDocDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CNewDocDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_NEWDOCDLG_H__986FD914_D49F_418D_9D0F_56936AB0744B__INCLUDED_) diff --git a/femm/NodeProp.cpp b/femm/NodeProp.cpp new file mode 100644 index 0000000..1d43051 --- /dev/null +++ b/femm/NodeProp.cpp @@ -0,0 +1,109 @@ +// NodeProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "NodeProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CNodeProp dialog + + +CNodeProp::CNodeProp(CWnd* pParent /*=NULL*/) + : CDialog(CNodeProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNodeProp) + m_ap = 0; + m_jp = 0; + m_nodename = _T(""); + //}}AFX_DATA_INIT +} + + +void CNodeProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNodeProp) + DDX_Text(pDX, IDC_A_RE, m_ap); + DDX_Text(pDX, IDC_J_RE, m_jp); + DDX_Text(pDX, IDC_NODENAME, m_nodename); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_A_RE, m_IDC_a_re); + DDX_Control(pDX, IDC_J_RE, m_IDC_j_re); + DDX_Control(pDX, IDC_NODENAME, m_IDC_nodename); +} + + +BEGIN_MESSAGE_MAP(CNodeProp, CDialog) + //{{AFX_MSG_MAP(CNodeProp) + ON_BN_CLICKED(IDC_SETA, OnSetA) + ON_BN_CLICKED(IDC_SETI, OnSetI) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNodeProp message handlers + +void CNodeProp::OnSetA() +{ + // TODO: Add your control notification handler code here + m_IDC_j_re.EnableWindow(FALSE); + m_IDC_a_re.EnableWindow(TRUE); + SetDlgItemText(IDC_J_RE,"0"); m_jp=0; +} + +void CNodeProp::OnSetI() +{ + // TODO: Add your control notification handler code here + m_IDC_a_re.EnableWindow(FALSE); + m_IDC_j_re.EnableWindow(TRUE); + SetDlgItemText(IDC_A_RE,"0"); m_ap=0; +} + +BOOL CNodeProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + if(abs(m_jp)>0){ + SetEm=IDC_SETI; + m_IDC_a_re.EnableWindow(FALSE); + m_IDC_j_re.EnableWindow(TRUE); + } + else{ + SetEm=IDC_SETA; + m_IDC_j_re.EnableWindow(FALSE); + m_IDC_a_re.EnableWindow(TRUE); + } + + + CheckRadioButton( + IDC_SETA,// identifier of first radio button in group + IDC_SETI, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CNodeProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(CNodeProp) + enum { IDD = IDD_NODEPROP }; + CComplex m_ap; + CComplex m_jp; + CString m_nodename; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNodeProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CNodeProp) + afx_msg void OnSetA(); + afx_msg void OnSetI(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_a_re, m_IDC_j_re, m_IDC_nodename; +}; diff --git a/femm/OpArcSegDlg.cpp b/femm/OpArcSegDlg.cpp new file mode 100644 index 0000000..e44fbe2 --- /dev/null +++ b/femm/OpArcSegDlg.cpp @@ -0,0 +1,80 @@ +// OpArcSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "OpArcSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpArcSegDlg dialog + + +COpArcSegDlg::COpArcSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(COpArcSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(COpArcSegDlg) + m_MaxSeg = 0.0; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void COpArcSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COpArcSegDlg) + DDX_Control(pDX, IDC_ARCSEGBDRY2, m_ArcSegBdry); + DDX_Check(pDX, IDC_ARCHIDE, m_hide); + DDX_Text(pDX, IDC_ARCGRP, m_ingroup); + DDX_Text(pDX, IDC_MAXSEG2, m_MaxSeg); + DDX_Control(pDX, IDC_ARCGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_MAXSEG2, m_IDC_MaxSeg); + DDV_MinMaxDouble(pDX, m_MaxSeg, 1.e-002, 10.); + //}}AFX_DATA_MAP + +} + + +BEGIN_MESSAGE_MAP(COpArcSegDlg, CDialog) + //{{AFX_MSG_MAP(COpArcSegDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COpArcSegDlg message handlers + +BOOL COpArcSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ArcSegBdry.AddString(""); + for(i=0;i *plineproplist; + +// Dialog Data + //{{AFX_DATA(COpArcSegDlg) + enum { IDD = IDD_OPARCSEGDLG }; + CComboBox m_ArcSegBdry; + double m_MaxSeg; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COpArcSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COpArcSegDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_MaxSeg; +}; diff --git a/femm/OpBlkDlg.cpp b/femm/OpBlkDlg.cpp new file mode 100644 index 0000000..1824aec --- /dev/null +++ b/femm/OpBlkDlg.cpp @@ -0,0 +1,165 @@ +// OpBlkDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "OpBlkDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpBlkDlg dialog + + +COpBlkDlg::COpBlkDlg(CWnd* pParent /*=NULL*/) + : CDialog(COpBlkDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(COpBlkDlg) + m_sidelength = 0.0; + m_magdir = 0.0; + m_turns = 1; + m_ingroup = 0; + m_isexternal = FALSE; + m_isdefault = FALSE; + //}}AFX_DATA_INIT + ProblemType=0; +} + + +void COpBlkDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COpBlkDlg) + DDX_Control(pDX, IDC_AUTOMESHCHECK, m_automesh); + DDX_Control(pDX, IDC_CIRCBLK, m_circblk); + DDX_Control(pDX, IDC_ACKBLK, m_ackblk); + DDX_Check(pDX, IDC_FE_EXTERNAL, m_isexternal); + DDX_Check(pDX, IDC_FE_ISDEFAULT, m_isdefault); + DDX_Text(pDX, IDC_SIDELENGTH, m_sidelength); + DDX_Text(pDX, IDC_MAGDIR, m_magdir,m_magdirfctn); + DDX_Text(pDX, IDC_TURNS, m_turns); + DDX_Text(pDX, IDC_BLKGROUP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_SIDELENGTH, m_IDC_sidelength); + DDX_Control(pDX, IDC_MAGDIR, m_IDC_magdir); + DDX_Control(pDX, IDC_TURNS, m_IDC_turns); + DDX_Control(pDX, IDC_BLKGROUP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(COpBlkDlg, CDialog) + //{{AFX_MSG_MAP(COpBlkDlg) + ON_CBN_SELCHANGE(IDC_ACKBLK, OnSelchangeAckblk) + ON_CBN_SELCHANGE(IDC_CIRCBLK, OnSelchangeCircblk) + ON_BN_CLICKED(IDC_AUTOMESHCHECK, OnAutomeshcheck) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COpBlkDlg message handlers + +void COpBlkDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackblk.GetCurSel(); + circsel=m_circblk.GetCurSel(); + CDialog::OnOK(); +} + +BOOL COpBlkDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CArray &blockproplist=*pblockproplist; + CArray &circproplist=*pcircproplist; + + int i; + + // TODO: Add extra initialization here + m_ackblk.AddString(""); + m_ackblk.AddString(""); + for(i=0;i"); + for(i=0;iEnableWindow(ProblemType); + + if(m_magdirfctn.GetLength()>0) + { + SetDlgItemText(IDC_MAGDIR,m_magdirfctn); + } + else{ + CString s; + s.Format("%.17g",m_magdir); + SetDlgItemText(IDC_MAGDIR,s); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void COpBlkDlg::OnSelchangeAckblk() +{ + CArray &blockproplist=*pblockproplist; + BOOL bEnable=FALSE; + + cursel=m_ackblk.GetCurSel(); + if (cursel>1) + if (blockproplist[cursel-2].H_c !=0.) bEnable=TRUE; + + m_IDC_magdir.EnableWindow(bEnable); +} + +void COpBlkDlg::OnSelchangeCircblk() +{ + CArray &circproplist = *pcircproplist; + BOOL bEnable=FALSE; + + cursel=m_circblk.GetCurSel(); + if (cursel>0) + if (circproplist[cursel-1].CircType !=0) bEnable=TRUE; + + m_IDC_turns.EnableWindow(bEnable); + + if (!bEnable){ + m_turns=1; + SetDlgItemText(IDC_TURNS, "1" ); + } + +} + +void COpBlkDlg::OnAutomeshcheck() +{ + // TODO: Add your control notification handler code here + int k=m_automesh.GetCheck(); + if (k==TRUE) k=FALSE; + else k=TRUE; + + SendDlgItemMessage( + IDC_SIDELENGTH, // identifier of control + WM_ENABLE, // message to send + (WPARAM) k, // first message parameter + (LPARAM) 0 // second message parameter + ); + if (k==FALSE){ + m_sidelength=0; + SetDlgItemText(IDC_SIDELENGTH, "0" ); + } +} diff --git a/femm/OpBlkDlg.h b/femm/OpBlkDlg.h new file mode 100644 index 0000000..caa4d6a --- /dev/null +++ b/femm/OpBlkDlg.h @@ -0,0 +1,57 @@ +// OpBlkDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// COpBlkDlg dialog + +class COpBlkDlg : public CDialog +{ +// Construction +public: + COpBlkDlg(CWnd* pParent = NULL); // standard constructor + int cursel,circsel; + int ProblemType; + CString m_magdirfctn; + CArray *pblockproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(COpBlkDlg) + enum { IDD = IDD_OPBLKDLG }; + CButton m_automesh; + CComboBox m_circblk; + CComboBox m_ackblk; + BOOL m_isexternal; + BOOL m_isdefault; + double m_sidelength; + double m_magdir; + int m_turns; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COpBlkDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COpBlkDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAckblk(); + afx_msg void OnSelchangeCircblk(); + afx_msg void OnAutomeshcheck(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_sidelength; + CLuaEdit m_IDC_magdir; + CLuaEdit m_IDC_turns; + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/OpGrp.cpp b/femm/OpGrp.cpp new file mode 100644 index 0000000..7c44cd2 --- /dev/null +++ b/femm/OpGrp.cpp @@ -0,0 +1,44 @@ +// OpGrp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "OpGrp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpGrp dialog + + +COpGrp::COpGrp(CWnd* pParent /*=NULL*/) + : CDialog(COpGrp::IDD, pParent) +{ + //{{AFX_DATA_INIT(COpGrp) + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void COpGrp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COpGrp) + DDX_Text(pDX, IDC_INGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_INGRP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(COpGrp, CDialog) + //{{AFX_MSG_MAP(COpGrp) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COpGrp message handlers diff --git a/femm/OpGrp.h b/femm/OpGrp.h new file mode 100644 index 0000000..53e80c3 --- /dev/null +++ b/femm/OpGrp.h @@ -0,0 +1,38 @@ +// OpGrp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// COpGrp dialog + +class COpGrp : public CDialog +{ +// Construction +public: + COpGrp(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(COpGrp) + enum { IDD = IDD_OPGRPDLG }; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COpGrp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COpGrp) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup; + +}; diff --git a/femm/OpNodeDlg.cpp b/femm/OpNodeDlg.cpp new file mode 100644 index 0000000..4acdafb --- /dev/null +++ b/femm/OpNodeDlg.cpp @@ -0,0 +1,72 @@ +// OpNodeDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "OpNodeDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpNodeDlg dialog + + +COpNodeDlg::COpNodeDlg(CWnd* pParent /*=NULL*/) + : CDialog(COpNodeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(COpNodeDlg) + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void COpNodeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COpNodeDlg) + DDX_Control(pDX, IDC_ACKNODE, m_acknode); + DDX_Text(pDX, IDC_PTGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_PTGRP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(COpNodeDlg, CDialog) + //{{AFX_MSG_MAP(COpNodeDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COpNodeDlg message handlers + +BOOL COpNodeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &nodeproplist=*pnodeproplist; + int i; + + // TODO: Add extra initialization here + m_acknode.AddString(""); + for(i=0;i *pnodeproplist; + +// Dialog Data + //{{AFX_DATA(COpNodeDlg) + enum { IDD = IDD_OPNODEDLG }; + CComboBox m_acknode; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COpNodeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COpNodeDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/OpSegDlg.cpp b/femm/OpSegDlg.cpp new file mode 100644 index 0000000..180896a --- /dev/null +++ b/femm/OpSegDlg.cpp @@ -0,0 +1,101 @@ +// OpSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "OpSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpSegDlg dialog + + +COpSegDlg::COpSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(COpSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(COpSegDlg) + m_linemeshsize = 0.0; + m_automesh = FALSE; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void COpSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COpSegDlg) + DDX_Control(pDX, IDC_ACKSEG, m_ackseg); + DDX_Text(pDX, IDC_SEGGRP, m_ingroup); + DDX_Text(pDX, IDC_LINEMESHSIZE, m_linemeshsize); + DDX_Check(pDX, IDC_AUTOMESH, m_automesh); + DDX_Check(pDX, IDC_SEGHIDE, m_hide); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_SEGGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_LINEMESHSIZE, m_IDC_linemeshsize); +} + + +BEGIN_MESSAGE_MAP(COpSegDlg, CDialog) + //{{AFX_MSG_MAP(COpSegDlg) + ON_BN_CLICKED(IDC_AUTOMESH, OnAutomesh) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COpSegDlg message handlers + +void COpSegDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackseg.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL COpSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ackseg.AddString(""); + for(i=0;i *plineproplist; + +// Dialog Data + //{{AFX_DATA(COpSegDlg) + enum { IDD = IDD_OPSEGDLG }; + CComboBox m_ackseg; + double m_linemeshsize; + BOOL m_automesh; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COpSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COpSegDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnAutomesh(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_linemeshsize; +}; diff --git a/femm/OutBox.cpp b/femm/OutBox.cpp new file mode 100644 index 0000000..a03f45a --- /dev/null +++ b/femm/OutBox.cpp @@ -0,0 +1,53 @@ +// OutBox.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "OutBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern CFemmApp theApp; +///////////////////////////////////////////////////////////////////////////// +// COutBox dialog + + +COutBox::COutBox(CWnd* pParent /*=NULL*/) + : CDialog(COutBox::IDD, pParent) +{ + //{{AFX_DATA_INIT(COutBox) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void COutBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(COutBox) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(COutBox, CDialog) + //{{AFX_MSG_MAP(COutBox) + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// COutBox message handlers + +void COutBox::OnClose() +{ + // TODO: Add your message handler code here and/or call default + theApp.bShowOutputWindow=FALSE; + CDialog::OnClose(); +} + + diff --git a/femm/OutBox.h b/femm/OutBox.h new file mode 100644 index 0000000..fd94f1c --- /dev/null +++ b/femm/OutBox.h @@ -0,0 +1,46 @@ +#if !defined(AFX_OUTBOX_H__77718BBB_F827_4C67_935E_6C6AD331D19C__INCLUDED_) +#define AFX_OUTBOX_H__77718BBB_F827_4C67_935E_6C6AD331D19C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// OutBox.h : header file +// +#include "resource.h" +///////////////////////////////////////////////////////////////////////////// +// COutBox dialog + +class COutBox : public CDialog +{ +// Construction +public: + COutBox(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(COutBox) + enum { IDD = IDD_OUTBOX }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(COutBox) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(COutBox) + afx_msg void OnClose(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_OUTBOX_H__77718BBB_F827_4C67_935E_6C6AD331D19C__INCLUDED_) diff --git a/femm/Pref.cpp b/femm/Pref.cpp new file mode 100644 index 0000000..4f7b978 --- /dev/null +++ b/femm/Pref.cpp @@ -0,0 +1,424 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define SelColor clist[0] +#define MeshColor clist[1] +#define BlockColor clist[2] +#define LineColor clist[3] +#define GridColor clist[4] +#define NodeColor clist[5] +#define BackColor clist[6] +#define NameColor clist[7] + +///////////////////////////////////////////////////////////////////////////// +// CPref dialog + + +CPref::CPref(CWnd* pParent /*=NULL*/) + : CDialog(CPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPref) + m_d_freq = 0.0; + m_d_gridsize = 0.25; + m_d_pixels = 100.0; + m_d_prec = 1.e-8; + m_d_minangle = DEFAULT_MINIMUM_ANGLE; + m_d_depth = 1.0; + m_d_showgrid = TRUE; + m_d_snapgrid = FALSE; + m_d_showorigin = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + s_action=0; + s_coord=0; + s_length=0; + s_type=0; + s_solver=0; + + clist=(COLORREF *)calloc(16,sizeof(COLORREF)); + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; +} + +CPref::~CPref() +{ + free(clist); +} + + +void CPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPref) + DDX_Control(pDX, IDC_DSOLVER, m_d_solver); + DDX_Control(pDX, IDC_DCOLOR, m_d_color); + DDX_Control(pDX, IDC_DTYPE, m_d_type); + DDX_Control(pDX, IDC_DLENGTH, m_d_length); + DDX_Control(pDX, IDC_DCOORD, m_d_coord); + DDX_Control(pDX, IDC_DACTION, m_d_action); + DDX_Text(pDX, IDC_DFREQ, m_d_freq); + DDX_Text(pDX, IDC_DGRIDSIZE, m_d_gridsize); + DDX_Text(pDX, IDC_DPIXELS, m_d_pixels); + DDX_Text(pDX, IDC_DDEPTH, m_d_depth); + DDX_Text(pDX, IDC_DPREC, m_d_prec); + DDV_MinMaxDouble(pDX, m_d_prec, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_DMINANGLE, m_d_minangle); + DDV_MinMaxDouble(pDX, m_d_minangle, 1., MINANGLE_MAX); + DDX_Check(pDX, IDC_DSHOWGRID, m_d_showgrid); + DDX_Check(pDX, IDC_DSNAPGRID, m_d_snapgrid); + DDX_Check(pDX, IDC_SHOW_ORIGIN, m_d_showorigin); + DDX_Check(pDX, IDC_SHOWNAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_DFREQ, m_IDC_d_freq); + DDX_Control(pDX, IDC_DGRIDSIZE, m_IDC_d_gridsize); + DDX_Control(pDX, IDC_DPIXELS, m_IDC_d_pixels); + DDX_Control(pDX, IDC_DDEPTH, m_IDC_d_depth); + DDX_Control(pDX, IDC_DPREC, m_IDC_d_prec); + DDX_Control(pDX, IDC_DMINANGLE, m_IDC_d_minangle); +} + + +BEGIN_MESSAGE_MAP(CPref, CDialog) + //{{AFX_MSG_MAP(CPref) + ON_BN_CLICKED(IDC_MODBTN, OnModifyButton) + ON_BN_CLICKED(IDC_RESTORE, OnRestoreColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPref message handlers + +void CPref::OnModifyButton() +{ + CColorDialog dlg; + int i; + + UpdateData(); + i=m_d_color.GetCurSel(); + + dlg.m_cc.lpCustColors=clist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + else{ + } + +} + +BOOL CPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_action.SetCurSel(s_action); + m_d_coord.SetCurSel(s_coord); + m_d_length.SetCurSel(s_length); + m_d_type.SetCurSel(s_type); + m_d_solver.SetCurSel(s_solver); + m_d_color.SetCurSel(0); + + UpdateData(FALSE); + + return TRUE; +} + +void CPref::OnRestoreColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; + } +} + +BOOL CPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +char* StripKey(char *c); + +void CPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "femme.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_prec); + q[0]=NULL; + } + + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_minangle); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_freq); + q[0]=NULL; + } + + if( _strnicmp(q,"",7)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_depth); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_coord); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_length); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_type); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_solver); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_pixels); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_shownames); + q[0]=NULL; + } + } + fclose(fp); + } +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void CPref::WritePrefs() +{ + FILE *fp; + CString fname; + + UpdateData(); + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + s_solver=m_d_solver.GetCurSel(); + fname=((CFemmApp *)AfxGetApp())->GetExecutablePath()+"femme.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",s_action); + fprintf(fp," = %g\n",m_d_pixels); + fprintf(fp," = %g\n",m_d_gridsize); + fprintf(fp," = %i\n",m_d_showgrid); + fprintf(fp," = %i\n",m_d_snapgrid); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_showorigin); + fprintf(fp," = %i\n",s_type); + fprintf(fp," = %i\n",s_solver); + fprintf(fp," = %i\n",s_length); + fprintf(fp," = %g\n",m_d_freq); + fprintf(fp," = %g\n",m_d_prec); + fprintf(fp," = %g\n",m_d_minangle); + fprintf(fp," = %g\n",m_d_depth); + fprintf(fp," = %i\n",s_coord); + + fclose(fp); + } + +} diff --git a/femm/Pref.h b/femm/Pref.h new file mode 100644 index 0000000..e69c811 --- /dev/null +++ b/femm/Pref.h @@ -0,0 +1,69 @@ +// Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPref dialog + +class CPref : public CDialog +{ +// Construction +public: + CPref(CWnd* pParent = NULL); // standard constructor + ~CPref(); + COLORREF *clist; + int s_action; + int s_coord; + int s_length; + int s_type; + int s_solver; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(CPref) + enum { IDD = IDD_EDITPREF }; + CComboBox m_d_solver; + CComboBox m_d_color; + CComboBox m_d_type; + CComboBox m_d_length; + CComboBox m_d_coord; + CComboBox m_d_action; + double m_d_freq; + double m_d_gridsize; + double m_d_pixels; + double m_d_depth; + double m_d_prec; + double m_d_minangle; + BOOL m_d_showgrid; + BOOL m_d_snapgrid; + BOOL m_d_showorigin; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPref) + afx_msg void OnModifyButton(); + virtual BOOL OnInitDialog(); + afx_msg void OnRestoreColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_d_freq, m_IDC_d_gridsize; + CLuaEdit m_IDC_d_pixels, m_IDC_d_prec; + CLuaEdit m_IDC_d_depth; + CLuaEdit m_IDC_d_minangle; +}; diff --git a/femm/Preferences.cpp b/femm/Preferences.cpp new file mode 100644 index 0000000..0a12427 --- /dev/null +++ b/femm/Preferences.cpp @@ -0,0 +1,69 @@ +// Preferences.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "Preferences.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPreferences dialog + + +CPreferences::CPreferences(CWnd* pParent /*=NULL*/) + : CDialog(CPreferences::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPreferences) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CPreferences::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPreferences) + DDX_Control(pDX, IDC_TAB1, m_tab1); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPreferences, CDialog) + //{{AFX_MSG_MAP(CPreferences) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPreferences message handlers + +BOOL CPreferences::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_tab1.InsertItem(0, _T("Magnetics Input")); + m_tab1.InsertItem(1, _T("Magnetics Output")); + m_tab1.InsertItem(2, _T("Electrostatics Input")); + m_tab1.InsertItem(3, _T("Electrostatics Output")); + m_tab1.InsertItem(4, _T("Heat Flow Input")); + m_tab1.InsertItem(5, _T("Heat Flow Output")); + m_tab1.InsertItem(6, _T("Current Flow Input")); + m_tab1.InsertItem(7, _T("Current Flow Output")); + m_tab1.InsertItem(8, _T("General Attributes")); + + m_tab1.Init(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CPreferences::OnOK() +{ + m_tab1.WritePrefs(); + + CDialog::OnOK(); +} diff --git a/femm/Preferences.h b/femm/Preferences.h new file mode 100644 index 0000000..875152d --- /dev/null +++ b/femm/Preferences.h @@ -0,0 +1,47 @@ +#if !defined(AFX_PREFERENCES_H__E2A6565B_5037_409B_A0BB_46A79DC7BF17__INCLUDED_) +#define AFX_PREFERENCES_H__E2A6565B_5037_409B_A0BB_46A79DC7BF17__INCLUDED_ +#include "MyTabCtrl.h" +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Preferences.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPreferences dialog + +class CPreferences : public CDialog +{ +// Construction +public: + CPreferences(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CPreferences) + enum { IDD = IDD_PREFERENCES }; + CMyTabCtrl m_tab1; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPreferences) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPreferences) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PREFERENCES_H__E2A6565B_5037_409B_A0BB_46A79DC7BF17__INCLUDED_) diff --git a/femm/Problem.cpp b/femm/Problem.cpp new file mode 100644 index 0000000..5bd7d10 --- /dev/null +++ b/femm/Problem.cpp @@ -0,0 +1,986 @@ +#include "stdafx.h" +#include "problem.h" +#include "fullmatrix.h" + +#define ElementsPerSkinDepth 10 + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + BoundaryMarker=-1; +} + +CComplex CNode::CC() +{ + return (x+I*y); +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMeshNode construction + +CMeshNode::CMeshNode() +{ + x=0.; y=0.; + A.re=0; A.im=0; + msk=0; +} + +CComplex CMeshNode::CC() +{ + return (x+I*y); +} + +double CMeshNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + BoundaryMarker=-1; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + MaxSideLength=-1; + ArcLength=90.; + BoundaryMarker=-1; + InGroup=0; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + InGroup=0; + InCircuit=0; + BlockType=-1; + IsExternal=FALSE; + IsDefault=FALSE; + + Case=0; + dVolts=0.; + J=0.; + FillFactor=1; + o=0; + mu=0; + LocalEnergy=0; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + mu_x=1.; + mu_y=1.; // permeabilities, relative + BHpoints=0; + Bdata=NULL; + Hdata=NULL; + slope=NULL; + H_c=0.; // magnetization, A/m + Nrg=0.; + Jr=0.; + Ji=0.; // applied current density, MA/m^2 + Cduct=0.; // conductivity of the material, MS/m + Lam_d=0.; // lamination thickness, mm + Theta_hn=0.; // hysteresis angle, degrees + Theta_hx=0.; // hysteresis angle, degrees + Theta_hy=0.; // hysteresis angle, degrees + NStrands=0; // number of strands per wire + WireD=0; + LamFill=1.; // lamination fill factor; + LamType=0; // type of lamination; + MuMax=0.; // maximum permeability (used for incremental permeability problems + Frequency=0; // problem frequency in Hz (needed for incremental permeability problems +} + +CMaterialProp::~CMaterialProp() +{ + if (Bdata!=NULL) free(Bdata); + if (Hdata!=NULL) free(Hdata); + if (slope!=NULL) free(slope); +} + +void CMaterialProp::GetSlopes(double omega) +{ + if (BHpoints==0) return; // catch trivial case; + if (slope!=NULL){ + return; // already have computed the slopes; + } + + int i,k; + BOOL CurveOK=FALSE; + BOOL ProcessedLams=FALSE; + CComplexFullMatrix L; + double l1,l2; + CComplex *hn; + double *bn; + CComplex mu; + + L.Create(BHpoints); + bn =(double *) calloc(BHpoints,sizeof(double)); + hn =(CComplex *)calloc(BHpoints,sizeof(CComplex)); + slope=(CComplex *)calloc(BHpoints,sizeof(CComplex)); + + + // strip off some info that we can use during the first + // nonlinear iteration; + mu_x = Bdata[1]/(muo*abs(Hdata[1])); + mu_y = mu_x; + Theta_hx=Theta_hn; + Theta_hy=Theta_hn; + + // first, we need to doctor the curve if the problem is + // being evaluated at a nonzero frequency. + if(omega!=0) + { + // Make an effective B-H curve for harmonic problems. + // this one convolves B(H) where H is sinusoidal with + // a sine at the same frequency to get the effective + // amplitude of B + double munow,mumax=0; + for(i=1;imumax) mumax=munow; + } + + // apply complex permeability to approximate the + // effects of hysteresis. We will follow a kludge + // suggested by O'Kelly where hysteresis angle + // is proportional to permeability. This implies + // that loss goes with B^2 + for(i=1;i0) + { + u0=sqrt(u0); + X0=-(c1 + u0)/(2.*c2); + X1=(-c1 + u0)/(2.*c2); + } + + //now, see if we've struck gold! + if (((X0>=0.)&&(X0<=L))||((X1>=0.)&&(X1<=L))) + CurveOK=FALSE; + } + + if(CurveOK!=TRUE) //remedial action + { + // Smooth out input points + // to get rid of rapid transitions; + // Uses a 3-point moving average + for(i=1;i= 0; k--) + b[k] = (b[k] - m1[k]*b[k + 1])/m0[k]; + + iter++; + + lastres=res; + res=abs(b[n]-x[n])/d; + + if (res<1.e-8) Converged=TRUE; + + // Do the same relaxation scheme as is implemented + // in the solver to make sure that this effective + // lamination permeability calculation converges + if(iter>5) + { + if ((res>lastres) && (Relax>0.1)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + } + + for(k=0;k<=n;k++) x[k]=Relax*b[k]+(1.0-Relax)*x[k]; + + }while(Converged!=TRUE); + + + mu = x[n]/(Hdata[i]*d); + + free(x ); + free(b ); + free(m0); + free(m1); + + return mu; +} + +CComplex CMaterialProp::GetdHdB(double B) +{ + double b,z,l; + CComplex h; + int i; + + b=fabs(B); + + if(BHpoints==0) return CComplex(b/(mu_x*muo)); + + if(b>Bdata[BHpoints-1]) + return slope[BHpoints-1]; + + for(i=0;i=Bdata[i]) && (b<=Bdata[i+1])){ + l=(Bdata[i+1]-Bdata[i]); + z=(b-Bdata[i])/l; + h=6.*z*(z-1.)*Hdata[i]/l + + (1.-4.*z+3.*z*z)*slope[i] + + 6.*z*(1.-z)*Hdata[i+1]/l + + z*(3.*z-2.)*slope[i+1]; + return h; + } + + return CComplex(0); +} + +double CMaterialProp::GetH(double x) +{ + return Re(GetH(CComplex(x))); +} + +CComplex CMaterialProp::GetH(CComplex x) +{ + double b,z,z2,l; + CComplex p,h; + int i; + + b=abs(x); + if((BHpoints==0) || (b==0)) return 0; + p=x/b; + + if(b>Bdata[BHpoints-1]) + return p*(Hdata[BHpoints-1] + slope[BHpoints-1]*(b-Bdata[BHpoints-1])); + + for(i=0;i=Bdata[i]) && (b<=Bdata[i+1])){ + l=Bdata[i+1]-Bdata[i]; + z=(b-Bdata[i])/l; + z2=z*z; + h=(1.-3.*z2+2.*z2*z)*Hdata[i] + + z*(1.-2.*z+z2)*l*slope[i] + + z2*(3.-2.*z)*Hdata[i+1] + + z2*(z-1.)*l*slope[i+1]; + return p*h; + } + + return 0; +} + +double CMaterialProp::GetB(double hc) +{ + if (BHpoints==0) return muo*mu_x*hc; + + double b,bo; + + b=0; + do{ + bo = b; + b = bo + (hc-GetH(bo))/Re(GetdHdB(bo)); + }while (fabs(b-bo)>1.e-8); + + return b; +} + +// GetEnergy for the magnetostatic case +double CMaterialProp::GetEnergy(double x) +{ + double b,z,z2,l,nrg; + double b0,b1,h0,h1,dh0,dh1; + int i; + + b=fabs(x); + nrg=0.; + + if(BHpoints==0) return 0; + + for(i=0;i=b0) && (b<=b1)){ + l=b1-b0; + z=(b-b0)/l; + z2=z*z; + + nrg += (dh0*l*l*(6. + z*(-8. + 3.*z))*z2)/12. + + (h0*l*z*(2. + (-2. + z)*z2))/2. - + (h1*l*(-2. + z)*z2*z)/2. + + (dh1*l*l*(-4. + 3.*z)*z2*z)/12; + + return nrg; + } + else{ + // point isn't in this section, but add in the + // energy required to pass through it. + b0=Bdata[i]; h0=Re(Hdata[i]); + b1=Bdata[i+1]; h1=Re(Hdata[i+1]); + dh0=Re(slope[i]); + dh1=Re(slope[i+1]); + nrg += ((b0 - b1)*((b0 - b1)*(dh0 - dh1) - + 6.*(h0 + h1)))/12.; + } + } + + // if we've gotten to this point, the point is off the scale, + // so we have to extrapolate the rest of the way... + + h0=Re(Hdata[BHpoints-1]); + dh0=Re(slope[BHpoints-1]); + b0=Bdata[BHpoints-1]; + + nrg += ((b - b0)*(b*dh0 - b0*dh0 + 2*h0))/2.; + + return nrg; +} + +double CMaterialProp::GetCoEnergy(double b) +{ + return (fabs(b)*GetH(b) - GetEnergy(b)); +} + +double CMaterialProp::DoEnergy(double b1, double b2) +{ + // calls the raw routine to get point energy, + // but deals with the load of special cases that + // arise because I insisted on trying to deal with + // laminations on a continuum basis. + + double nrg,biron,bair; + + // easiest case: the material is linear! + if (BHpoints==0) + { + double h1,h2; + + if(LamType==0){ // laminated in-plane + h1=b1/((1.+LamFill*(mu_x-1.))*muo); + h2=b2/((1.+LamFill*(mu_y-1.))*muo); + } + + if(LamType==1){ // laminated parallel to x; + h1=b1/((1.+LamFill*(mu_x-1.))*muo); + h2=b1*(LamFill/(mu_y*muo) + (1. - LamFill)/muo); + } + + if(LamType==2){ // laminated parallel to x; + h2=b1/((1.+LamFill*(mu_y-1.))*muo); + h1=b1*(LamFill/(mu_x*muo) + (1. - LamFill)/muo); + } + + if(LamType>2){ + h1=b1/muo; + h2=b2/muo; + } + + return ((h1*b1+h2*b2)/2.); + } + + // Rats! The material is nonlinear. Now, we have to do + // a bit of work to get the energy. + if(LamType==0) nrg = GetEnergy(sqrt(b1*b1+b2*b2)); + + if(LamType==1){ + biron=sqrt((b1/LamFill)*(b1/LamFill) + b2*b2); + bair=b2; + nrg = LamFill*GetEnergy(biron)+(1-LamFill)*bair*bair/(2.*muo); + } + + if(LamType==2){ + biron=sqrt((b2/LamFill)*(b2/LamFill) + b1*b1); + bair=b1; + nrg = LamFill*GetEnergy(biron)+(1-LamFill)*bair*bair/(2.*muo); + } + + return nrg; +} + +double CMaterialProp::DoCoEnergy(double b1, double b2) +{ + double nrg,biron,bair; + + // easiest case: the material is linear! + // in this case, energy and coenergy are the same! + if (BHpoints==0) return DoEnergy(b1,b2); + + if(LamType==0) nrg = GetCoEnergy(sqrt(b1*b1+b2*b2)); + + if(LamType==1){ + biron=sqrt((b1/LamFill)*(b1/LamFill) + b2*b2); + bair=b2; + nrg = LamFill*GetCoEnergy(biron)+(1-LamFill)*bair*bair/(2.*muo); + } + + if(LamType==2){ + biron=sqrt((b2/LamFill)*(b2/LamFill) + b1*b1); + bair=b1; + nrg = LamFill*GetCoEnergy(biron)+(1-LamFill)*bair*bair/(2.*muo); + } + + return nrg; +} + + +double CMaterialProp::DoEnergy(CComplex b1, CComplex b2) +{ + // This one is meant for the frequency!=0 case. + // Fortunately, there's not so much effort in this case. + CComplex mu1,mu2,h1,h2; + + GetMu(b1,b2,mu1,mu2); + h1=b1/(mu1*muo); + h2=b2/(mu2*muo); + return (Re(h1*conj(b1)+h2*conj(b2))/4.); + +} + +double CMaterialProp::DoCoEnergy(CComplex b1, CComplex b2) +{ + return DoEnergy(b1,b2); +} + +void CMaterialProp::GetMu(CComplex b1, CComplex b2, + CComplex &mu1, CComplex &mu2) +{ + // gets the permeability, given a flux density + // version for frequency!=0 + + CComplex biron; + + // easiest case: the material is linear! + if (BHpoints==0) + { + mu1=mu_fdx; + mu2=mu_fdy; + return; + } + + // Rats! The material is nonlinear. + if(MuMax>0) // incremental solution case... + { + // Arrgh!!! need incremental permeability about flux density from + // DC solution, not flux density of AC solution here. + // we're assuming that, in this case, b1 and b2 _do_ contain the DC operating point + IncrementalPermeability(sqrt(Re(b1*conj(b1)+b2*conj(b2))),mu1,mu2); + // MsgBox("mu=%g %g; b=%g",Re(mu1),Im(mu1),sqrt(Re(b1*conj(b1)+b2*conj(b2)))); + return; + } + + CComplex muiron; + + if(LamType==0){ + biron=sqrt(b1*conj(b1)+b2*conj(b2)); + if(abs(biron)<1.e-08) mu1=1./slope[0]; //catch degenerate case + else mu1=biron/GetH(biron); + mu2=mu1; + } + + if(LamType==1){ + biron=sqrt((b1/LamFill)*(b1/LamFill) + b2*b2); + if(abs(biron)<1.e-08) muiron=1./slope[0]; + else muiron=biron/GetH(biron); + mu1=muiron*LamFill; + mu2=1./(LamFill/muiron + (1. - LamFill)/muo); + } + + if(LamType==2){ + biron=sqrt((b2/LamFill)*(b2/LamFill) + b1*b1); + if(abs(biron)<1.e-08) muiron=1./slope[0]; + else muiron=biron/GetH(biron); + mu2=muiron*LamFill; + mu1=1./(LamFill/muiron + (1. - LamFill)/muo); + } + + // convert to relative permeability + mu1/=muo; + mu2/=muo; + + return; +} + + +void CMaterialProp::GetMu(double b1, double b2, + double &mu1, double &mu2) +{ + // gets the permeability, given a flux density + // + + double biron; + + mu1=mu2=muo; // default + + // catch the incremental permeability case + if (MuMax>0) // for DC problems, MuMax is sleazily used as a flag to tell that it's incremental + { + IncrementalPermeability(sqrt(b1*b1 + b2*b2), mu1, mu2); + return; + } + + // easiest case: the material is linear! + if (BHpoints==0) + { + if(LamType==0){ // laminated in-plane + mu1=((1.+LamFill*(mu_x-1.))*muo); + mu2=((1.+LamFill*(mu_y-1.))*muo); + } + + if(LamType==1){ // laminated parallel to x; + mu1=((1.+LamFill*(mu_x-1.))*muo); + mu2=1./(LamFill/(mu_y*muo) + (1. - LamFill)/muo); + } + + if(LamType==2){ // laminated parallel to x; + mu2=((1.+LamFill*(mu_y-1.))*muo); + mu1=1./(LamFill/(mu_x*muo) + (1. - LamFill)/muo); + } + } + + // Rats! The material is nonlinear. + else{ + double muiron; + + if(LamType==0){ + biron=sqrt(b1*b1+b2*b2); + if(biron<1.e-08) mu1=1./Re(slope[0]); //catch degenerate case + else mu1=biron/GetH(biron); + mu2=mu1; + } + + if(LamType==1){ + biron=sqrt((b1/LamFill)*(b1/LamFill) + b2*b2); + if(biron<1.e-08) muiron=1./Re(slope[0]); + else muiron=biron/GetH(biron); + mu1=muiron*LamFill; + mu2=1./(LamFill/muiron + (1. - LamFill)/muo); + } + + if(LamType==2){ + biron=sqrt((b2/LamFill)*(b2/LamFill) + b1*b1); + if(biron<1.e-08) muiron=1./Re(slope[0]); + else muiron=biron/GetH(biron); + mu2=muiron*LamFill; + mu1=1./(LamFill/muiron + (1. - LamFill)/muo); + } + + } + + // convert to relative permeability + mu1/=muo; + mu2/=muo; + + return; +} + + +// get incremental permeability of a nonlinear material for use in +// incremental permeability formulation about DC offset +void CMaterialProp::IncrementalPermeability(double B, CComplex &mu1, CComplex &mu2) +{ + // B == flux density in Tesla + // w == frequency in rad/s + + double muinc,murel; + CComplex k; + double mu,w; + + w=Frequency*2.*PI; + + // get incremental permeability of the DC material + // (i.e. incremental permeability at the offset) + muinc=1./(muo*Re(GetdHdB(B))); + if (B==0) murel = (1./(muo*Re(slope[0]))); + else murel=B/(muo*GetH(B)); + + // if material is not laminated, just apply hysteresis lag... + if ((Lam_d==0) || (LamFill==0)) + { + mu1=muinc*exp(-I*Theta_hn*DEG*muinc/MuMax); + mu2=murel*exp(-I*Theta_hn*DEG*murel/MuMax); + return; + } + + // crap. Need to make an equivalent permeability that rolls in the effects of laminated + // eddy currents, using the incremental permeability as the basis for creating the impedance. + // this can get annoying because we need to back out the iron portion of the permeability + // in the lamfill<1 case... + + + if (Cduct!=0) + { + CComplex deg45; deg45=1+I; + CComplex K,halflag; + double ds; + + // incremental permeability direction + mu = (muinc - (1.-LamFill))/LamFill; + halflag=exp(-I*Theta_hn*DEG*mu/(2.*MuMax)); + ds=sqrt(2./(0.4*PI*w*Cduct*mu)); + K=halflag*deg45*Lam_d*0.001/(2.*ds); + mu1=(LamFill*mu*tanh(K)/K + (1.- LamFill)); + + // normal permeability direction + mu = (murel - (1.-LamFill))/LamFill; + halflag=exp(-I*Theta_hn*DEG*mu/(2.*MuMax)); + ds=sqrt(2./(0.4*PI*w*Cduct*mu)); + K=halflag*deg45*Lam_d*0.001/(2.*ds); + mu2=(LamFill*mu*tanh(K)/K + (1.- LamFill)); + return; + } + else{ + // incremental permeability direction + mu = (muinc - (1.-LamFill))/LamFill; + mu1=(mu*exp(-I*Theta_hn*DEG*mu/MuMax)*LamFill + (1.-LamFill)); + + // normal permeability direction + mu = (murel - (1.-LamFill))/LamFill; + mu2=(mu*exp(-I*Theta_hn*DEG*mu/MuMax)*LamFill + (1.-LamFill)); + return; + } +} + +// get incremental permeability of a nonlinear material for use in +// incremental permeability formulation about DC offset +void CMaterialProp::IncrementalPermeability(double B, double &mu1, double &mu2) +{ + // B == flux density in Tesla + + double muinc, murel; + + // get incremental permeability of the DC material + // (i.e. incremental permeability at the offset) + muinc = 1. / (muo*Re(GetdHdB(B))); + if (B == 0) murel = (1. / (muo*Re(slope[0]))); + else murel = B / (muo*GetH(B)); + + // if material is not laminated, just return + if ((Lam_d == 0) || (LamFill == 0)) { + mu1 = muinc; + mu2 = murel; + return; + } + + // incremental permeability direction + mu1 = (muinc*LamFill + (1. - LamFill)); + + // normal permeability direction + mu2 = (murel*LamFill + (1. - LamFill)); + + return; +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + + A0=0.; A1=0.; + A2=0.; phi=0.; // set value of A for BdryFormat=0; + + Mu=0.; Sig=0.; // material properties necessary to apply + // eddy current BC + + c0=0.; c1=0.; // coefficients for mixed BC + +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + Jr=0.; Ji=0.; // applied point current, A + Ar=0.; Ai=0.; // prescribed nodal value; +} + +CCircuit::CCircuit() +{ + CircName="New Circuit"; + CircType=0; + Amps=0.; +} diff --git a/femm/Problem.h b/femm/Problem.h new file mode 100644 index 0000000..0eb0fea --- /dev/null +++ b/femm/Problem.h @@ -0,0 +1,305 @@ +namespace femmviewdata{ +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + int BoundaryMarker; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +class CMeshNode +{ + public: + CMeshNode(); + + double x,y; // coordinates of the node + CComplex A; // vector potential + double msk; // mask value, used for creating weighted stress tensor integrals + int xs,ys; // screen coordinates of the node + double Aprev; // previous solution for incremental permeability problems + + double GetDistance(double xo, double yo); + CComplex CC(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + double MaxSideLength; + BOOL IsSelected; + BOOL Hidden; + int BoundaryMarker; + int InGroup; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength; + int BoundaryMarker; + int InGroup; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + double MagDir; + CString MagDirFctn; + int Turns; + BOOL IsSelected; + int InCircuit; + int BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + int Case; + CComplex J,dVolts; + + // attributes used to keep track of wound coil properties... + double FillFactor; + CComplex o,mu; + double LocalEnergy; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CMaterialProp(); + ~CMaterialProp(); + + void GetSlopes(double omega); + CComplex LaminatedBH(double w, int i); + + double GetH(double b); + CComplex GetH(CComplex b); // ``raw'' results + CComplex GetdHdB(double B); + double GetB(double h); + + void GetMu(double b1,double b2,double &mu1, double &mu2); + void GetMu(CComplex b1,CComplex b2,CComplex &mu1, CComplex &mu2); + void IncrementalPermeability(double B, CComplex &mu1, CComplex &mu2); + void IncrementalPermeability(double B, double &mu1, double &mu2); + double GetEnergy(double b); // straight from the + double GetCoEnergy(double b); // BH curve data + + // routines that are actually called to get + // energy and coenergy. These catch and take + // care of all of the weird special cases + // that arise with laminated materials. + double DoEnergy(double bx, double by); + double DoCoEnergy(double bx, double by); + double DoEnergy(CComplex bx, CComplex by); + double DoCoEnergy(CComplex b1, CComplex b2); + + CString BlockName; + double mu_x,mu_y; // permeabilities, relative + int BHpoints; // number of points in the BH curve... + double *Bdata; + CComplex *Hdata; // entries in B-H curve; + CComplex *slope; // slopes used in interpolation + // of BHdata + int LamType; // flag that tells how block is laminated; + // 0 = not laminated or laminated in plane; + // 1 = laminated in the x-direction; + // 2 = laminated in the y-direction; + double LamFill; // lamination fill factor, dimensionless; + double H_c; // magnetization, A/m + double Nrg; + double Jr,Ji; // applied current density, MA/m^2 + double Cduct; // conductivity of the material, MS/m + double Lam_d; // lamination thickness, mm + double Theta_hn; // hysteresis angle, degrees + double Theta_hx; // hysteresis angle, degrees + double Theta_hy; // hysteresis angle, degrees + int NStrands; // number of strands per wire + double WireD; // strand diameter, mm + + CComplex mu_fdx,mu_fdy; // complex permeability for harmonic problems; + double MuMax; // maximum effective permeability, needed for incremental permeability problems + double Frequency; // problem frequency in Hz, needed for incremental permeability problems + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + int BdryFormat; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + + double A0,A1,A2,phi; // set value of A for BdryFormat=0; + + double Mu,Sig; // material properties necessary to apply + // eddy current BC + + CComplex c0,c1; // coefficients for mixed BC + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + double Jr,Ji; // applied point current, A + double Ar,Ai; // prescribed nodal value; + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + CComplex Amps; + int CircType; + + private: + +}; + +class CElement +{ + public: + + int p[3]; + int blk,lbl; + CComplex B1,B2; + CComplex b1[3],b2[3]; + double magdir; + CComplex ctr; + double rsqr; + int n[3]; // Add 3 ints to store elem's neigh. + + double B1p,B2p; // previous solution elemental flux density for incremental permeability problems + double Jp; // previous solution elemental current density for incremental permeability problems + + private: +}; + +class CPointVals +{ + public: + + CComplex A; // vector potential + CComplex B1,B2; // flux density + CComplex mu1,mu2; // permeability + CComplex mu12; // permeability cross-term, needed for incremental permeability problems + CComplex H1,H2; // field intensity + CComplex Je,Js; // eddy current and source current densities + CComplex Hc; // Magnetization for regions with a PM. + double c; // conductivity + double E; // energy stored in the magnetic field + double Ph; // power dissipated by hysteresis + double Pe; // power dissipated by eddy currents + double ff; // winding fill factor + + CPointVals(); + + private: +}; + +class CQuadPoint +{ + public: + int n0,n1,n2,n3; + double w0,w1,w2,w3; +}; + +class CAirGapElement +{ + public: + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + + int totalArcElements; // total elements in the initial meshing + double totalArcLength; // sum of the angles of all constituent arcs + double ri,ro; // inner and outer radii of the air gap element + double InnerAngle; + double OuterAngle; + double InnerShift; + double OuterShift; + CComplex agc; // center of the air gap element + + CQuadPoint *qp; + + int nn; + CComplex aco; + CComplex *brc, *brs; // harmonic components of air gap centerline flux density + CComplex *btc, *bts; + CComplex *br, *bt; + double *brcPrev, *brsPrev; // harmonic components of air gap centerline flux density + double *btcPrev, *btsPrev; + double *brPrev,*btPrev; + int *nh; // list of number associated with each harmonic + + + private: +}; + +} + +using namespace femmviewdata; \ No newline at end of file diff --git a/femm/PromptBox.cpp b/femm/PromptBox.cpp new file mode 100644 index 0000000..26c9edd --- /dev/null +++ b/femm/PromptBox.cpp @@ -0,0 +1,66 @@ +// PromptBox.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "PromptBox.h" +#include "lua.h" + +extern lua_State *lua; + +// CPromptBox dialog + +IMPLEMENT_DYNAMIC(CPromptBox, CDialog) +CPromptBox::CPromptBox(CWnd* pParent /*=NULL*/) + : CDialog(CPromptBox::IDD, pParent) + , instring(_T("")) +{ +} + +CPromptBox::~CPromptBox() +{ +} + +double CPromptBox::ParseDouble() +{ + // parse the contents of the edit box and return a double; + + CString tolua; + int i,k; + double x=0; + + tolua="return " + instring; + i=lua_gettop(lua); + lua_dostring(lua,tolua); + k=lua_gettop(lua); + if (i!=k){ + tolua=lua_tostring(lua,-1); + if (tolua.GetLength()==0) AfxMessageBox("Input does not evaluate to a numerical value"); + else x=lua_todouble(lua,-1); + } + return x; +} + +void CPromptBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Text(pDX, IDC_EDIT1, instring); + DDX_Control(pDX, IDC_EDIT1, lua_instring); +} + + +BEGIN_MESSAGE_MAP(CPromptBox, CDialog) +END_MESSAGE_MAP() + + +// CPromptBox message handlers + +BOOL CPromptBox::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetWindowText(mytitle); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/PromptBox.h b/femm/PromptBox.h new file mode 100644 index 0000000..1591e03 --- /dev/null +++ b/femm/PromptBox.h @@ -0,0 +1,28 @@ +#pragma once +#include "afxwin.h" + + +// CPromptBox dialog + +class CPromptBox : public CDialog +{ + DECLARE_DYNAMIC(CPromptBox) + +public: + CPromptBox(CWnd* pParent = NULL); // standard constructor + virtual ~CPromptBox(); + double ParseDouble(); + +// Dialog Data + enum { IDD = IDD_PROMPTBOX }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + CString instring; + CString mytitle; + CLuaEdit lua_instring; + virtual BOOL OnInitDialog(); +}; diff --git a/femm/PtProp.cpp b/femm/PtProp.cpp new file mode 100644 index 0000000..d535e26 --- /dev/null +++ b/femm/PtProp.cpp @@ -0,0 +1,483 @@ +// PtProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "PtProp.h" +#include "NodeProp.h" +#include "MatDlg.h" +#include "BdryDlg.h" +#include "CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPtProp dialog + + +CPtProp::CPtProp(CWnd* pParent /*=NULL*/) + : CDialog(CPtProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPtProp) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CPtProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPtProp) + DDX_Control(pDX, IDC_NAME_LIST, m_namelist); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPtProp, CDialog) + //{{AFX_MSG_MAP(CPtProp) + ON_BN_CLICKED(IDC_ADD_PROP, OnAddProp) + ON_BN_CLICKED(IDC_DEL_PROP, OnDelProp) + ON_BN_CLICKED(IDC_MOD_PROP, OnModProp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPtProp message handlers + +void CPtProp::OnAddProp() +{ + + // Code to deal with adding a Point Property. + if (PropType==0){ + CPointProp PProp; + CNodeProp zDlg; + CArray &nodeproplist=*pnodeproplist; + + for(int nn=0;nn &circproplist=*pcircproplist; + CCircProp zDlg; + for(int nn=0;nn &lineproplist=*plineproplist; + CBdryDlg zDlg; + for(int nn=0;nn &blockproplist=*pblockproplist; + CMatDlg zDlg; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (nodeproplist.GetSize()!=0)) + { + nodeproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (circproplist.GetSize()!=0)) + { + circproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (lineproplist.GetSize()!=0)) + { + lineproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (blockproplist.GetSize()!=0)) + { + blockproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } +} + +void CPtProp::OnModProp() +{ + // TODO: Add your control notification handler code here + if (PropType==0){ + CArray &nodeproplist=*pnodeproplist; + CNodeProp zDlg; + + if (nodeproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_ap=nodeproplist[k].Ap; + zDlg.m_jp=nodeproplist[k].Jp; + zDlg.m_nodename=nodeproplist[k].PointName; + + for(int nn=0;nn &circproplist=*pcircproplist; + + if (circproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + CCircProp zDlg; + + zDlg.m_circname = circproplist[k].CircName; + zDlg.m_circtype = circproplist[k].CircType; + zDlg.m_totcurrent = circproplist[k].Amps; + for(int nn=0;nn &lineproplist=*plineproplist; + CBdryDlg zDlg; + + if (lineproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_A0 =lineproplist[k].A0; + zDlg.m_A1 =lineproplist[k].A1; + zDlg.m_A2 =lineproplist[k].A2; + zDlg.m_Phi=lineproplist[k].phi; + zDlg.m_Mu =lineproplist[k].Mu; + zDlg.m_Sig=lineproplist[k].Sig; + zDlg.m_c0 =lineproplist[k].c0; + zDlg.m_c1 =lineproplist[k].c1; + zDlg.BdryFormat=lineproplist[k].BdryFormat; + zDlg.m_BdryName=lineproplist[k].BdryName; + zDlg.m_innerangle=lineproplist[k].InnerAngle; + zDlg.m_outerangle=lineproplist[k].OuterAngle; + for(int nn=0;nn &blockproplist=*pblockproplist; + CMatDlg zDlg; + + if (blockproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_mu_x=blockproplist[k].mu_x; + zDlg.m_mu_y=blockproplist[k].mu_y; + zDlg.m_H_c=blockproplist[k].H_c; + zDlg.m_Jsrc=blockproplist[k].Jsrc; + zDlg.m_Cduct=blockproplist[k].Cduct; + zDlg.m_Lam_d=blockproplist[k].Lam_d; + zDlg.m_Theta_hn=blockproplist[k].Theta_hn; + zDlg.m_Theta_hx=blockproplist[k].Theta_hx; + zDlg.m_Theta_hy=blockproplist[k].Theta_hy; + zDlg.m_WireD=blockproplist[k].WireD; + zDlg.m_NStrands=blockproplist[k].NStrands; + zDlg.m_BlockName=blockproplist[k].BlockName; + zDlg.LamType=blockproplist[k].LamType; + zDlg.m_lam_fill=blockproplist[k].LamFill; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/PtProp.h b/femm/PtProp.h new file mode 100644 index 0000000..5e606c8 --- /dev/null +++ b/femm/PtProp.h @@ -0,0 +1,48 @@ +// PtProp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPtProp dialog + +class CPtProp : public CDialog +{ +// Construction +public: + CPtProp(CWnd* pParent = NULL); // standard constructor + + // variables CPrProp needs; + int PropType; + int ProblemType; + CArray *pnodeproplist; + CArray *plineproplist; + CArray *pblockproplist; + CArray *pcircproplist; + + +// Dialog Data + //{{AFX_DATA(CPtProp) + enum { IDD = IDD_PTPROP }; + CComboBox m_namelist; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPtProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPtProp) + afx_msg void OnAddProp(); + afx_msg void OnDelProp(); + afx_msg void OnModProp(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/ScaleDlg.cpp b/femm/ScaleDlg.cpp new file mode 100644 index 0000000..31dbc2a --- /dev/null +++ b/femm/ScaleDlg.cpp @@ -0,0 +1,50 @@ +// ScaleDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "ScaleDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CScaleDlg dialog + + +CScaleDlg::CScaleDlg(CWnd* pParent /*=NULL*/) + : CDialog(CScaleDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CScaleDlg) + m_basex = 0.0; + m_basey = 0.0; + m_scalefactor = 0.0; + //}}AFX_DATA_INIT +} + + +void CScaleDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CScaleDlg) + DDX_Text(pDX, IDC_BASEX, m_basex); + DDX_Text(pDX, IDC_BASEY, m_basey); + DDX_Text(pDX, IDC_SCALEFACTOR, m_scalefactor); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BASEX, m_IDC_basex); + DDX_Control(pDX, IDC_BASEY, m_IDC_basey); + DDX_Control(pDX, IDC_SCALEFACTOR, m_IDC_scalefactor); +} + + +BEGIN_MESSAGE_MAP(CScaleDlg, CDialog) + //{{AFX_MSG_MAP(CScaleDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CScaleDlg message handlers diff --git a/femm/ScaleDlg.h b/femm/ScaleDlg.h new file mode 100644 index 0000000..f1114af --- /dev/null +++ b/femm/ScaleDlg.h @@ -0,0 +1,39 @@ +// ScaleDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CScaleDlg dialog + +class CScaleDlg : public CDialog +{ +// Construction +public: + CScaleDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CScaleDlg) + enum { IDD = IDD_SCALE }; + double m_basex; + double m_basey; + double m_scalefactor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CScaleDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CScaleDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_basex, m_IDC_basey, m_IDC_scalefactor; +}; diff --git a/femm/StdAfx.h b/femm/StdAfx.h new file mode 100644 index 0000000..c8a23c0 --- /dev/null +++ b/femm/StdAfx.h @@ -0,0 +1,189 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__744766B7_69F6_473E_A1A8_F1100DCD5ECC__INCLUDED_) +#define AFX_STDAFX_H__744766B7_69F6_473E_A1A8_F1100DCD5ECC__INCLUDED_ + +#define _CRT_SECURE_NO_WARNINGS + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// This macro is the same as IMPLEMENT_OLECREATE, except it passes TRUE +// for the bMultiInstance parameter to the COleObjectFactory constructor. +// We want a separate instance of this application to be launched for +// each automation proxy object requested by automation controllers. +#ifndef IMPLEMENT_OLECREATE2 +#define IMPLEMENT_OLECREATE2(class_name, external_name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + AFX_DATADEF COleObjectFactory class_name::factory(class_name::guid, \ + RUNTIME_CLASS(class_name), TRUE, _T(external_name)); \ + const AFX_DATADEF GUID class_name::guid = \ + { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; +#endif // IMPLEMENT_OLECREATE2 + +// need this for CArray support +#include +#include + +#include +#include +#define PI 3.141592653589793238462643383 +#define muo 1.2566370614359173e-6 +#define eo 8.85418781762e-12 +#define DEGREE 0.017453292519943295 +#define round(x) floor(x+0.5) + +#define PLANAR 0 +#define AXISYMMETRIC 1 + +// uncomment the following if you want to compile with MathLink support. +// #define MATHLINK + +// commend the following line if you don't want a tabbed MDI interface. +#define MDITAB + +#include "complex.h" + +// kludge to put lua support into all edit boxes +#include "luaDDX.h" +#define DDX_Text Lua_DDX_Text +#include "LuaEdit.h" +#include "OutBox.h" +class CZPix +{ + public: + int x,y; + COLORREF c; +}; + +class CPixel +{ + public: + int z; + COLORREF c; +}; + +class CFolderProp +{ + public: + + CString FolderName; + CString FolderURL; + CString FolderVendor; + + private: +}; + +int MsgBox(PSTR sz,...); +int MsgBox(CString s); + +double sq(double x); +CString ToString(CComplex x); +CString ToString(CComplex x, int n); + +// preprocessor tolerance +#define CLOSE_ENOUGH 1.e-06 + +// Default mesh size is the diagonal of the geometry's +// bounding box divided by BoundingBoxFraction +#define BoundingBoxFraction 100.0 +#define LineFraction 500.0 +#define DEFAULT_MINIMUM_ANGLE 30.0 +// kludge to make mesh from Triangle 1.6 have about the +// same mesh density as Triangle 1.3 for consistent "smartmesh" results +#define MINANGLE_BUMP 3 +#define MINANGLE_MAX 33.8 + +// definition needed for PtLoc +enum LocateResult { eOnVertex, eOnEdge, eInTriangle, eOutSide }; + +// different sorts of bLinehook cases +#define NormalLua 1 +#define HiddenLua 2 +#define ImportDXF 3 +#define BuildMask 4 + + ////////////////////////////// + // Default Colors // + ////////////////////////////// + + // Greyscale Colormap + #define dGrey00 RGB(55,55,55) + #define dGrey01 RGB(65,65,65) + #define dGrey02 RGB(75,75,75) + #define dGrey03 RGB(85,85,85) + #define dGrey04 RGB(95,95,95) + #define dGrey05 RGB(105,105,105) + #define dGrey06 RGB(115,115,115) + #define dGrey07 RGB(125,125,125) + #define dGrey08 RGB(135,135,135) + #define dGrey09 RGB(145,145,145) + #define dGrey10 RGB(155,155,155) + #define dGrey11 RGB(165,165,165) + #define dGrey12 RGB(175,175,175) + #define dGrey13 RGB(185,185,185) + #define dGrey14 RGB(195,195,195) + #define dGrey15 RGB(205,205,205) + #define dGrey16 RGB(215,215,215) + #define dGrey17 RGB(225,225,225) + #define dGrey18 RGB(235,235,235) + #define dGrey19 RGB(245,245,245) + + // BELA Colormap + #define dColor19 RGB(0,255,255) + #define dColor18 RGB(37,255,195) + #define dColor17 RGB(69,255,147) + #define dColor16 RGB(98,255,108) + #define dColor15 RGB(123,255,76) + #define dColor14 RGB(148,255,51) + #define dColor13 RGB(171,255,31) + #define dColor12 RGB(194,255,16) + #define dColor11 RGB(217,255,6) + #define dColor10 RGB(242,255,1) + #define dColor09 RGB(255,242,1) + #define dColor08 RGB(255,217,6) + #define dColor07 RGB(255,194,16) + #define dColor06 RGB(255,171,31) + #define dColor05 RGB(255,148,51) + #define dColor04 RGB(255,123,76) + #define dColor03 RGB(255,98,108) + #define dColor02 RGB(255,69,147) + #define dColor01 RGB(255,37,195) + #define dColor00 RGB(255,0,255) + + // Other colors + #define dSelColor RGB(255,0,0) + #define dMeshColor RGB(213,228,20) + #define dBlockColor RGB(0,125,0) + #define dLineColor RGB(0,0,255) + #define dRegionColor RGB(0,255,0) + #define dGridColor RGB(0,0,255) + #define dBackColor RGB(255,255,255) + #define dNodeColor RGB(0,0,0) + #define dTextColor RGB(0,0,0) + #define dRealFluxLineColor RGB(0,0,0) + #define dImagFluxLineColor RGB(128,128,128) + #define dNameColor RGB(0,0,0) + #define dMaskLineColor RGB(255,128,64) + #define dRealVectorColor RGB(0,0,0) + #define dImagVectorColor RGB(128,128,128) + +#define lua_todouble(lua,n) Re(lua_tonumber(lua,n)) + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__744766B7_69F6_473E_A1A8_F1100DCD5ECC__INCLUDED_) diff --git a/femm/TKDatafile.cpp b/femm/TKDatafile.cpp new file mode 100644 index 0000000..a85845c --- /dev/null +++ b/femm/TKDatafile.cpp @@ -0,0 +1,130 @@ +// TKDatafile.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "TKDatafile.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTKDatafile dialog + + +CTKDatafile::CTKDatafile(CWnd* pParent /*=NULL*/) + : CDialog(CTKDatafile::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTKDatafile) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTKDatafile::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTKDatafile) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTKDatafile, CDialog) + //{{AFX_MSG_MAP(CTKDatafile) + ON_BN_CLICKED(IDC_TFIRST, OnTfirst) + ON_BN_CLICKED(IDC_KFIRST, OnKfirst) + ON_BN_CLICKED(IDC_KELV, OnKelvin) + ON_BN_CLICKED(IDC_CELC, OnCelcius) + ON_BN_CLICKED(IDC_FAHR, OnFahrenheit) + ON_BN_CLICKED(IDC_RANK, OnRankine) + ON_BN_CLICKED(IDC_WMK, OnWMK) + ON_BN_CLICKED(IDC_BTU, OnBTU) + ON_BN_CLICKED(IDC_KCAL, OnKCAL) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTKDatafile message handlers + +BOOL CTKDatafile::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + TKOrder=0; + TUnits=0; + KUnits=0; + + CheckRadioButton( + IDC_TFIRST,// identifier of first radio button in group + IDC_KFIRST, // identifier of last radio button in group + IDC_TFIRST // identifier of radio button to select + ); + + CheckRadioButton( + IDC_KELV,// identifier of first radio button in group + IDC_RANK, // identifier of last radio button in group + IDC_KELV // identifier of radio button to select + ); + + CheckRadioButton( + IDC_WMK,// identifier of first radio button in group + IDC_KCAL, // identifier of last radio button in group + IDC_WMK // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CTKDatafile::OnTfirst() +{ + // TODO: Add your control notification handler code here + TKOrder=0; +} + +void CTKDatafile::OnKfirst() +{ + TKOrder=1; +} + +void CTKDatafile::OnKelvin() +{ + TUnits=0; +} + +void CTKDatafile::OnCelcius() +{ + TUnits=1; +} + +void CTKDatafile::OnFahrenheit() +{ + TUnits=2; +} + +void CTKDatafile::OnRankine() +{ + TUnits=3; +} + +void CTKDatafile::OnWMK() +{ + KUnits=0; +} + +void CTKDatafile::OnBTU() +{ + KUnits=1; +} + +void CTKDatafile::OnKCAL() +{ + KUnits=2; +} + + diff --git a/femm/TKDatafile.h b/femm/TKDatafile.h new file mode 100644 index 0000000..d932e16 --- /dev/null +++ b/femm/TKDatafile.h @@ -0,0 +1,45 @@ +// TKDatafile.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTKDatafile dialog + +class CTKDatafile : public CDialog +{ +// Construction +public: + CTKDatafile(CWnd* pParent = NULL); // standard constructor + int TKOrder,TUnits,KUnits; + +// Dialog Data + //{{AFX_DATA(CTKDatafile) + enum { IDD = IDD_TKDATAFILE }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTKDatafile) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTKDatafile) + virtual BOOL OnInitDialog(); + afx_msg void OnTfirst(); + afx_msg void OnKfirst(); + afx_msg void OnKelvin(); + afx_msg void OnCelcius(); + afx_msg void OnFahrenheit(); + afx_msg void OnRankine(); + afx_msg void OnWMK(); + afx_msg void OnBTU(); + afx_msg void OnKCAL(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/VPlotDlg.cpp b/femm/VPlotDlg.cpp new file mode 100644 index 0000000..152cab0 --- /dev/null +++ b/femm/VPlotDlg.cpp @@ -0,0 +1,80 @@ +// VPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "VPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CVPlotDlg dialog + + +CVPlotDlg::CVPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(CVPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CVPlotDlg) + m_vectorscalefactor = 0.0; + //}}AFX_DATA_INIT +} + + +void CVPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CVPlotDlg) + DDX_Control(pDX, IDC_VPLOTTYPE, m_vplottype); + DDX_Text(pDX, IDC_VPLOT_SCALE, m_vectorscalefactor); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_VPLOT_SCALE, m_IDC_vectorscalefactor); +} + + +BEGIN_MESSAGE_MAP(CVPlotDlg, CDialog) + //{{AFX_MSG_MAP(CVPlotDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CVPlotDlg message handlers + +void CVPlotDlg::OnOK() +{ + m_plottype=m_vplottype.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL CVPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if (ListType==0){ + m_vplottype.AddString(""); + m_vplottype.AddString("B"); + m_vplottype.AddString("H"); + if ((m_plottype>2) || (m_plottype<0)) m_plottype=0; + m_vplottype.SetCurSel(m_plottype); + } + + if (ListType==1){ + m_vplottype.AddString(""); + m_vplottype.AddString("B_re"); + m_vplottype.AddString("H_re"); + m_vplottype.AddString("B_im"); + m_vplottype.AddString("H_im"); + m_vplottype.AddString("B_re & B_im"); + m_vplottype.AddString("H_re & H_im"); + if ((m_plottype>6) || (m_plottype<0)) m_plottype=0; + m_vplottype.SetCurSel(m_plottype); + } + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/VPlotDlg.h b/femm/VPlotDlg.h new file mode 100644 index 0000000..c2d7495 --- /dev/null +++ b/femm/VPlotDlg.h @@ -0,0 +1,52 @@ +#if !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) +#define AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// VPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CVPlotDlg dialog + +class CVPlotDlg : public CDialog +{ +// Construction +public: + CVPlotDlg(CWnd* pParent = NULL); // standard constructor + + int m_plottype; + int ListType; + CLuaEdit m_IDC_vectorscalefactor; + +// Dialog Data + //{{AFX_DATA(CVPlotDlg) + enum { IDD = IDD_VPLOTDLG }; + CComboBox m_vplottype; + double m_vectorscalefactor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CVPlotDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) diff --git a/femm/XYPlotDlg.cpp b/femm/XYPlotDlg.cpp new file mode 100644 index 0000000..70f98d2 --- /dev/null +++ b/femm/XYPlotDlg.cpp @@ -0,0 +1,118 @@ +// XYPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "problem.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewView.h" +#include "MainFrm.h" +#include "lua.h" + +#include "XYPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CXYPlotDlg dialog + + +CXYPlotDlg::CXYPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(CXYPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CXYPlotDlg) + m_ToFile = FALSE; + m_npoints = 150; + //}}AFX_DATA_INIT + ListType=0; + XYPlotType=0; + FileFormat=0; +} + + +void CXYPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CXYPlotDlg) + DDX_Control(pDX, IDC_FILEFORMAT, m_fileformat); + DDX_Control(pDX, IDC_XYPLOTTYPE, m_XYPlotType); + DDX_Check(pDX, IDC_TOFILE, m_ToFile); + DDX_Text(pDX, IDC_NPOINTS, m_npoints); + DDV_MinMaxInt(pDX, m_npoints, 10, 100000); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_NPOINTS, m_IDC_npoints); +} + + +BEGIN_MESSAGE_MAP(CXYPlotDlg, CDialog) + //{{AFX_MSG_MAP(CXYPlotDlg) + ON_BN_CLICKED(IDC_TOFILE, OnToFileClicked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CXYPlotDlg message handlers + +BOOL CXYPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if (ListType==0){ + m_XYPlotType.AddString("Potential"); + m_XYPlotType.AddString("|B| (Magnitude of flux density)"); + m_XYPlotType.AddString("B . n (Normal flux density)"); + m_XYPlotType.AddString("B . t (Tangential flux density)"); + m_XYPlotType.AddString("|H| (Magnitude of field intensity)"); + m_XYPlotType.AddString("H . n (Normal field intensity)"); + m_XYPlotType.AddString("H . t (Tangential field intensity)"); + m_XYPlotType.SetCurSel(1); + } + + if (ListType==1){ + m_XYPlotType.AddString("Potential"); + m_XYPlotType.AddString("|B| (Magnitude of flux density)"); + m_XYPlotType.AddString("B . n (Normal flux density)"); + m_XYPlotType.AddString("B . t (Tangential flux density)"); + m_XYPlotType.AddString("|H| (Magnitude of field intensity)"); + m_XYPlotType.AddString("H . n (Normal field intensity)"); + m_XYPlotType.AddString("H . t (Tangential field intensity)"); + m_XYPlotType.AddString("J_eddy (Eddy current density)"); + m_XYPlotType.AddString("Js+J_eddy (Source+eddy curent density)"); + m_XYPlotType.SetCurSel(1); + } + + if (ListType==2){ + int k; + for(k=0;kblockproplist.GetSize();k++) + if(pDoc->blockproplist[k].BHpoints>0) + m_XYPlotType.AddString(pDoc->blockproplist[k].BlockName); + m_XYPlotType.SetCurSel(0); + SetWindowText("Plot BH Curves"); + } + + m_fileformat.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CXYPlotDlg::OnOK() +{ + // TODO: Add extra validation here + XYPlotType=m_XYPlotType.GetCurSel(); + FileFormat=m_fileformat.GetCurSel(); + CDialog::OnOK(); +} + +void CXYPlotDlg::OnToFileClicked() +{ + UpdateData(); +} + diff --git a/femm/XYPlotDlg.h b/femm/XYPlotDlg.h new file mode 100644 index 0000000..7e81510 --- /dev/null +++ b/femm/XYPlotDlg.h @@ -0,0 +1,46 @@ +// XYPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CXYPlotDlg dialog + +class CXYPlotDlg : public CDialog +{ +// Construction +public: + CXYPlotDlg(CWnd* pParent = NULL); // standard constructor + int ListType; + int XYPlotType; + int FileFormat; + CFemmviewDoc *pDoc; + +// Dialog Data + //{{AFX_DATA(CXYPlotDlg) + enum { IDD = IDD_XYPLOTDLG }; + CComboBox m_fileformat; + CComboBox m_XYPlotType; + BOOL m_ToFile; + int m_npoints; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CXYPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CXYPlotDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnToFileClicked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_npoints; +}; diff --git a/femm/Xyplot.cpp b/femm/Xyplot.cpp new file mode 100644 index 0000000..09b0a2f --- /dev/null +++ b/femm/Xyplot.cpp @@ -0,0 +1,287 @@ +#include "stdafx.h" +#include "xyplot.h" + +/* +class CXYPlot +{ + public: + // data members + double **M; + double **lbls; + int NumRows; + int NumCols; + + // member functions + CXYPlot(); + ~CXYPlot(); + BOOL Create(int rows, int cols); + BOOL MakePlot(); + BOOL ToDisk(); + + private: +} +*/ + +CXYPlot::CXYPlot() +{ + NumRows=0; + NumCols=0; + M=NULL; + lbls=NULL; +} + +CXYPlot::~CXYPlot() +{ + if (NumRows==0) return; + + int i; + for(i=0;iHiY) HiY=M[i][j]; + if (M[i][j]SelectObject( &PlotPen ); + pDC->MoveTo(0,0); + pDC->LineTo(588,0); + pDC->LineTo(588,343); + pDC->LineTo(0,343); + pDC->LineTo(0,0); + + pDC->MoveTo((int) OffsetX,(int) OffsetY); + pDC->LineTo((int) OffsetX,(int) (OffsetY+Height)); + pDC->LineTo((int) (OffsetX+Width),(int) (OffsetY+Height)); + pDC->SelectObject(pOldPen); + PlotPen.DeleteObject(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(12,0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + // draw those suckers... + for(i=1;iSelectObject( &PlotPen ); + pDC->MoveTo((int)M[0][0],(int)M[0][i]); + for(j=0;jLineTo((int)M[j][0],(int)M[j][i]); + pDC->SetTextColor(PenCols[i-1]); + pDC->TextOut((int)(OffsetX+Width+10.),((int) OffsetY)+14*i,lbls[i],(int) strlen(lbls[i])); + pDC->SelectObject(pOldPen); PlotPen.DeleteObject(); + } + pDC->SetTextColor(0x00000000); + pDC->TextOut(200,(int) (OffsetY+Height+30),lbls[0],(int) strlen(lbls[0])); + k=(int)((HiY-LoY)/dy + 0.5); + if(k<4){ + dy/=2.; + k=(int)((HiY-LoY)/dy + 0.5); + } + if(k==0) k++; + + pDC->SetTextAlign(TA_RIGHT); + for(i=0;i<=k;i++){ + pDC->MoveTo((int) OffsetX,(i*(int)Height)/k +(int) OffsetY); + pDC->LineTo((int) OffsetX-5,(i*(int) Height)/k+ (int) OffsetY); + sprintf(s,"%.4g",HiY-((double) i)*dy); + pDC->TextOut(((int) OffsetX)-10,(i*(int)Height)/k +(int) OffsetY-6,s,(int) strlen(s)); + } + k=(int)((HiX-LoX)/dx ); + if(k<4){ + dx/=2.; + k=(int)((HiX-LoX)/dx ); + } + d=( ((double) Width) * dx/ (HiX-LoX)); + pDC->SetTextAlign(TA_CENTER); + for(i=0;i<=k;i++){ + pDC->MoveTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height)); + pDC->LineTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height)+5); + sprintf(s,"%.4g",LoX+((double) i)*dx); + pDC->TextOut((int)(((double) i)*d + OffsetX),(int) OffsetY+(int)Height+10,s,(int) strlen(s)); + } + pDC->SetTextAlign(TA_LEFT); + + + pDC->SelectObject(pOldFont); +} + +BOOL CXYPlot::ToDisk(int fileformat, CString ToFile) +{ + FILE *fp; + int i,j; + CString dest_name; + + if((NumCols==0) || (NumRows==0)){ + if (ToFile=="") MsgBox("No data to write to disk."); + return FALSE; + } + + if (ToFile=="") + { + CFileDialog *fname_dia=new CFileDialog( + FALSE, + "txt | * ", + dest_name, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Text Files (*.txt) | *.txt; *.TXT | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return FALSE; + } + + dest_name=fname_dia->GetPathName(); + + delete[] fname_dia; + } + else dest_name=ToFile; + + if((fp=fopen(dest_name,"wt"))!=NULL){ + if (fileformat==0){ + for(i=0;i namelist; + + CFont symbfont; + +// Dialog Data + //{{AFX_DATA(bdCBdryDlg) + enum { IDD = IDD_BD_BDRYDLG }; + CComboBox m_BdryFormat; + CString m_BdryName; + double m_c0; + double m_c1; + double m_v; + double m_qs; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCBdryDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCBdryDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeBdryformat(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_IDC_VBDRY, m_IDC_QS, m_IDC_BDRYNAME; + CLuaEdit m_IDC_c0, m_IDC_c1; + +}; diff --git a/femm/bd_CircProp.cpp b/femm/bd_CircProp.cpp new file mode 100644 index 0000000..5009828 --- /dev/null +++ b/femm/bd_CircProp.cpp @@ -0,0 +1,102 @@ +// CircProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCCircProp dialog + + +bdCCircProp::bdCCircProp(CWnd* pParent /*=NULL*/) + : CDialog(bdCCircProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCCircProp) + m_circname = _T(""); + m_v = 0.0; + m_q = 0.0; + //}}AFX_DATA_INIT +} + + +void bdCCircProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCCircProp) + DDX_Text(pDX, IDC_BD_CIRCNAME, m_circname); + DDX_Text(pDX, IDC_BD_V, m_v); + DDX_Text(pDX, IDC_BD_Q, m_q); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_CIRCNAME, m_idc_circname); + DDX_Control(pDX, IDC_BD_V, m_idc_v); + DDX_Control(pDX, IDC_BD_Q, m_idc_q); +} + + +BEGIN_MESSAGE_MAP(bdCCircProp, CDialog) + //{{AFX_MSG_MAP(bdCCircProp) + ON_BN_CLICKED(IDC_BD_RADIOAMP, OnRadioamp) + ON_BN_CLICKED(IDC_BD_RADIOVOLT, OnRadiovolt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCCircProp message handlers + +void bdCCircProp::OnRadioamp() +{ + m_circtype=0; + m_idc_q.EnableWindow(TRUE); + m_idc_v.EnableWindow(FALSE); +} + +void bdCCircProp::OnRadiovolt() +{ + m_circtype=1; + m_idc_q.EnableWindow(FALSE); + m_idc_v.EnableWindow(TRUE); +} + +BOOL bdCCircProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + SetEm=IDC_BD_RADIOAMP; + if(m_circtype==1){ + SetEm=IDC_BD_RADIOVOLT; + OnRadiovolt(); + } + else OnRadioamp(); + + CheckRadioButton( + IDC_BD_RADIOVOLT,// identifier of first radio button in group + IDC_BD_RADIOAMP, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bdCCircProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(bdCCircProp) + enum { IDD = IDD_BD_CIRCPROP }; + CString m_circname; + double m_v; + double m_q; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCCircProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCCircProp) + afx_msg void OnRadioamp(); + afx_msg void OnRadiovolt(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_idc_circname; + CLuaEdit m_idc_v; + CLuaEdit m_idc_q; +}; diff --git a/femm/bd_MatDlg.cpp b/femm/bd_MatDlg.cpp new file mode 100644 index 0000000..e7b96da --- /dev/null +++ b/femm/bd_MatDlg.cpp @@ -0,0 +1,88 @@ +// MatDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bd_MatDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCMatDlg dialog + + +bdCMatDlg::bdCMatDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCMatDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCMatDlg) + m_BlockName = _T(""); + m_ex = 0.0; + m_ey = 0.0; + m_qv = 0.0; + m_mu1label = _T(""); + m_mu2label = _T(""); + //}}AFX_DATA_INIT +} + + +void bdCMatDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCMatDlg) + DDX_Control(pDX, IDC_STATIC_SYMBOL4, m_static4); + DDX_Control(pDX, IDC_STATIC_SYMBOL3, m_static3); + DDX_Text(pDX, IDC_BD_BLOCKNAME, m_BlockName); + DDX_Text(pDX, IDC_BD_EX, m_ex); + DDX_Text(pDX, IDC_BD_EY, m_ey); + DDX_Text(pDX, IDC_BD_QV, m_qv); + DDX_Text(pDX, IDC_BD_MU1LABEL, m_mu1label); + DDX_Text(pDX, IDC_BD_MU2LABEL, m_mu2label); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_BLOCKNAME, m_IDC_BlockName); + DDX_Control(pDX, IDC_BD_EX, m_IDC_EX); + DDX_Control(pDX, IDC_BD_EY, m_IDC_EY); + DDX_Control(pDX, IDC_BD_QV, m_IDC_QV); +} + + +BEGIN_MESSAGE_MAP(bdCMatDlg, CDialog) + //{{AFX_MSG_MAP(bdCMatDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCMatDlg message handlers + +BOOL bdCMatDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + symbfont.CreateFont(0, 0, 0, 0, FW_BOLD, TRUE, 0, 0, + SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, DEFAULT_PITCH | FF_DECORATIVE, "Symbol"); + m_static3.SetFont(&symbfont); + m_static4.SetFont(&symbfont); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bdCMatDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + + CFont symbfont; + CFont bfont; + +// Dialog Data + //{{AFX_DATA(bdCMatDlg) + enum { IDD = IDD_BD_MATDLG }; + CStatic m_static4; + CStatic m_static3; + CString m_BlockName; + double m_ex; + double m_ey; + double m_qv; + CString m_mu1label; + CString m_mu2label; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCMatDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCMatDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_EX, m_IDC_EY, m_IDC_BlockName, m_IDC_QV; + +}; diff --git a/femm/bd_NodeProp.cpp b/femm/bd_NodeProp.cpp new file mode 100644 index 0000000..e99a859 --- /dev/null +++ b/femm/bd_NodeProp.cpp @@ -0,0 +1,110 @@ +// NodeProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bd_NodeProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCNodeProp dialog + + +bdCNodeProp::bdCNodeProp(CWnd* pParent /*=NULL*/) + : CDialog(bdCNodeProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCNodeProp) + m_nodename = _T(""); + m_qp = 0.0; + m_vp = 0.0; + //}}AFX_DATA_INIT +} + + +void bdCNodeProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCNodeProp) + DDX_Text(pDX, IDC_BD_NODENAME, m_nodename); + DDX_Text(pDX, IDC_BD_QP, m_qp); + DDX_Text(pDX, IDC_BD_VP, m_vp); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_VP, m_IDC_vp); + DDX_Control(pDX, IDC_BD_QP, m_IDC_qp); + DDX_Control(pDX, IDC_BD_NODENAME, m_IDC_nodename); +} + + +BEGIN_MESSAGE_MAP(bdCNodeProp, CDialog) + //{{AFX_MSG_MAP(bdCNodeProp) + ON_BN_CLICKED(IDC_BD_SETA, OnSetA) + ON_BN_CLICKED(IDC_BD_SETI, OnSetI) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCNodeProp message handlers + +void bdCNodeProp::OnSetA() +{ + // TODO: Add your control notification handler code here + m_IDC_qp.EnableWindow(FALSE); + m_IDC_vp.EnableWindow(TRUE); + SetDlgItemText(IDC_BD_QP,"0"); m_qp=0; +} + +void bdCNodeProp::OnSetI() +{ + // TODO: Add your control notification handler code here + m_IDC_vp.EnableWindow(FALSE); + m_IDC_qp.EnableWindow(TRUE); + SetDlgItemText(IDC_BD_VP,"0"); m_vp=0; +} + +BOOL bdCNodeProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + if(m_qp!=0){ + SetEm=IDC_BD_SETI; + + m_IDC_vp.EnableWindow(FALSE); + m_IDC_qp.EnableWindow(TRUE); + } + else{ + SetEm=IDC_BD_SETA; + m_IDC_qp.EnableWindow(FALSE); + m_IDC_vp.EnableWindow(TRUE); + } + + + CheckRadioButton( + IDC_BD_SETA,// identifier of first radio button in group + IDC_BD_SETI, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bdCNodeProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + CFont bfont; + +// Dialog Data + //{{AFX_DATA(bdCNodeProp) + enum { IDD = IDD_BD_NODEPROP }; + CString m_nodename; + double m_qp; + double m_vp; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCNodeProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCNodeProp) + afx_msg void OnSetA(); + afx_msg void OnSetI(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_vp, m_IDC_qp, m_IDC_nodename; +}; diff --git a/femm/bd_OpArcSegDlg.cpp b/femm/bd_OpArcSegDlg.cpp new file mode 100644 index 0000000..7743134 --- /dev/null +++ b/femm/bd_OpArcSegDlg.cpp @@ -0,0 +1,86 @@ +// OpArcSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_OpArcSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCOpArcSegDlg dialog + + +bdCOpArcSegDlg::bdCOpArcSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCOpArcSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCOpArcSegDlg) + m_MaxSeg = 0.0; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void bdCOpArcSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCOpArcSegDlg) + DDX_Control(pDX, IDC_BD_ARCSEG_COND, m_arcsegcond); + DDX_Control(pDX, IDC_BD_ARCSEGBDRY2, m_ArcSegBdry); + DDX_Text(pDX, IDC_BD_MAXSEG2, m_MaxSeg); + DDX_Check(pDX, IDC_BD_ARCHIDE, m_hide); + DDX_Text(pDX, IDC_BD_ARCGRP, m_ingroup); + DDV_MinMaxDouble(pDX, m_MaxSeg, 1.e-002, 10.); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_ARCGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_BD_MAXSEG2, m_IDC_MaxSeg); +} + + +BEGIN_MESSAGE_MAP(bdCOpArcSegDlg, CDialog) + //{{AFX_MSG_MAP(bdCOpArcSegDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCOpArcSegDlg message handlers + +BOOL bdCOpArcSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ArcSegBdry.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_arcsegcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(bdCOpArcSegDlg) + enum { IDD = IDD_BD_OPARCSEGDLG }; + CComboBox m_arcsegcond; + CComboBox m_ArcSegBdry; + double m_MaxSeg; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCOpArcSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCOpArcSegDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_MaxSeg; +}; diff --git a/femm/bd_OpBlkDlg.cpp b/femm/bd_OpBlkDlg.cpp new file mode 100644 index 0000000..0525442 --- /dev/null +++ b/femm/bd_OpBlkDlg.cpp @@ -0,0 +1,119 @@ +// OpBlkDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_OpBlkDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCOpBlkDlg dialog + + +bdCOpBlkDlg::bdCOpBlkDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCOpBlkDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCOpBlkDlg) + m_sidelength = 0.0; + m_ingroup = 0; + m_isexternal = FALSE; + m_isdefault = FALSE; + //}}AFX_DATA_INIT + ProblemType=0; +} + + +void bdCOpBlkDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCOpBlkDlg) + DDX_Control(pDX, IDC_BD_AUTOMESHCHECK, m_automesh); + DDX_Control(pDX, IDC_BD_ACKBLK, m_ackblk); + DDX_Check(pDX, IDC_BD_EXTERNAL, m_isexternal); + DDX_Check(pDX, IDC_BD_ISDEFAULT, m_isdefault); + DDX_Text(pDX, IDC_BD_SIDELENGTH, m_sidelength); + DDX_Text(pDX, IDC_BD_BLKGROUP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_SIDELENGTH, m_IDC_sidelength); + DDX_Control(pDX, IDC_BD_BLKGROUP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(bdCOpBlkDlg, CDialog) + //{{AFX_MSG_MAP(bdCOpBlkDlg) + ON_CBN_SELCHANGE(IDC_BD_ACKBLK, OnSelchangeAckblk) + ON_BN_CLICKED(IDC_BD_AUTOMESHCHECK, OnAutomeshcheck) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCOpBlkDlg message handlers + +void bdCOpBlkDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackblk.GetCurSel(); + CDialog::OnOK(); +} + +BOOL bdCOpBlkDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CArray &blockproplist=*pblockproplist; + CArray &circproplist=*pcircproplist; + + int i; + + // TODO: Add extra initialization here + m_ackblk.AddString(""); + m_ackblk.AddString(""); + for(i=0;iEnableWindow(ProblemType); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bdCOpBlkDlg::OnSelchangeAckblk() +{ + CArray &blockproplist=*pblockproplist; + BOOL bEnable=FALSE; + + cursel=m_ackblk.GetCurSel(); +} + +void bdCOpBlkDlg::OnAutomeshcheck() +{ + // TODO: Add your control notification handler code here + int k=m_automesh.GetCheck(); + if (k==TRUE) k=FALSE; + else k=TRUE; + + SendDlgItemMessage( + IDC_BD_SIDELENGTH, // identifier of control + WM_ENABLE, // message to send + (WPARAM) k, // first message parameter + (LPARAM) 0 // second message parameter + ); + if (k==FALSE){ + m_sidelength=0; + SetDlgItemText(IDC_BD_SIDELENGTH, "0" ); + } +} + diff --git a/femm/bd_OpBlkDlg.h b/femm/bd_OpBlkDlg.h new file mode 100644 index 0000000..c1a2666 --- /dev/null +++ b/femm/bd_OpBlkDlg.h @@ -0,0 +1,50 @@ +// bd_OpBlkDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bdCOpBlkDlg dialog + +class bdCOpBlkDlg : public CDialog +{ +// Construction +public: + bdCOpBlkDlg(CWnd* pParent = NULL); // standard constructor + int cursel; + int ProblemType; + CArray *pblockproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(bdCOpBlkDlg) + enum { IDD = IDD_BD_OPBLKDLG }; + CButton m_automesh; + CComboBox m_ackblk; + BOOL m_isexternal; + BOOL m_isdefault; + double m_sidelength; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCOpBlkDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCOpBlkDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAckblk(); + afx_msg void OnAutomeshcheck(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_sidelength; + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/bd_OpNodeDlg.cpp b/femm/bd_OpNodeDlg.cpp new file mode 100644 index 0000000..50a6d29 --- /dev/null +++ b/femm/bd_OpNodeDlg.cpp @@ -0,0 +1,80 @@ +// OpNodeDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_OpNodeDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCOpNodeDlg dialog + + +bdCOpNodeDlg::bdCOpNodeDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCOpNodeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCOpNodeDlg) + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void bdCOpNodeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCOpNodeDlg) + DDX_Control(pDX, IDC_BD_NODE_COND, m_nodecond); + DDX_Control(pDX, IDC_BD_ACKNODE, m_acknode); + DDX_Text(pDX, IDC_BD_PTGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_PTGRP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(bdCOpNodeDlg, CDialog) + //{{AFX_MSG_MAP(bdCOpNodeDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCOpNodeDlg message handlers + +BOOL bdCOpNodeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &nodeproplist=*pnodeproplist; + + int i; + + // TODO: Add extra initialization here + m_acknode.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_nodecond.AddString(""); + for(i=0;i *pnodeproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(bdCOpNodeDlg) + enum { IDD = IDD_BD_OPNODEDLG }; + CComboBox m_nodecond; + CComboBox m_acknode; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCOpNodeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCOpNodeDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/bd_OpSegDlg.cpp b/femm/bd_OpSegDlg.cpp new file mode 100644 index 0000000..6c0925e --- /dev/null +++ b/femm/bd_OpSegDlg.cpp @@ -0,0 +1,126 @@ +// OpSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_OpSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCOpSegDlg dialog + + +bdCOpSegDlg::bdCOpSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCOpSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCOpSegDlg) + m_linemeshsize = 0.0; + m_automesh = FALSE; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void bdCOpSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCOpSegDlg) + DDX_Control(pDX, IDC_BD_SEG_COND, m_segcond); + DDX_Control(pDX, IDC_BD_ACKSEG, m_ackseg); + DDX_Text(pDX, IDC_BD_LINEMESHSIZE, m_linemeshsize); + DDX_Check(pDX, IDC_BD_AUTOMESH, m_automesh); + DDX_Check(pDX, IDC_BD_SEGHIDE, m_hide); + DDX_Text(pDX, IDC_BD_SEGGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_SEGGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_BD_LINEMESHSIZE, m_IDC_linemeshsize); +} + + +BEGIN_MESSAGE_MAP(bdCOpSegDlg, CDialog) + //{{AFX_MSG_MAP(bdCOpSegDlg) + ON_BN_CLICKED(IDC_BD_AUTOMESH, OnAutomesh) + ON_CBN_SELCHANGE(IDC_BD_ACKSEG, OnSelchangeAckseg) + ON_CBN_SELCHANGE(IDC_BD_SEG_COND, OnSelchangeSegCond) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCOpSegDlg message handlers + +void bdCOpSegDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackseg.GetCurSel(); + condsel=m_segcond.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL bdCOpSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ackseg.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_segcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(bdCOpSegDlg) + enum { IDD = IDD_BD_OPSEGDLG }; + CComboBox m_segcond; + CComboBox m_ackseg; + double m_linemeshsize; + BOOL m_automesh; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCOpSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCOpSegDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnAutomesh(); + afx_msg void OnSelchangeAckseg(); + afx_msg void OnSelchangeSegCond(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_linemeshsize; +}; diff --git a/femm/bd_Pref.cpp b/femm/bd_Pref.cpp new file mode 100644 index 0000000..6fc225a --- /dev/null +++ b/femm/bd_Pref.cpp @@ -0,0 +1,413 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "bd_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define SelColor clist[0] +#define MeshColor clist[1] +#define BlockColor clist[2] +#define LineColor clist[3] +#define GridColor clist[4] +#define NodeColor clist[5] +#define BackColor clist[6] +#define NameColor clist[7] + +///////////////////////////////////////////////////////////////////////////// +// bdCPref dialog + + +bdCPref::bdCPref(CWnd* pParent /*=NULL*/) + : CDialog(bdCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCPref) + m_d_gridsize = 0.25; + m_d_pixels = 100.0; + m_d_prec = 1.e-8; + m_d_minangle = DEFAULT_MINIMUM_ANGLE; + m_d_depth = 1.0; + m_d_showgrid = TRUE; + m_d_snapgrid = FALSE; + m_d_showorigin = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + s_action=0; + s_coord=0; + s_length=0; + s_type=0; + + clist=(COLORREF *)calloc(16,sizeof(COLORREF)); + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; +} + +bdCPref::~bdCPref() +{ + free(clist); +} + +void bdCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCPref) + DDX_Control(pDX, IDC_BD_DCOLOR, m_d_color); + DDX_Control(pDX, IDC_BD_DTYPE, m_d_type); + DDX_Control(pDX, IDC_BD_DLENGTH, m_d_length); + DDX_Control(pDX, IDC_BD_DCOORD, m_d_coord); + DDX_Control(pDX, IDC_BD_DACTION, m_d_action); + DDX_Text(pDX, IDC_BD_DGRIDSIZE, m_d_gridsize); + DDX_Text(pDX, IDC_BD_DDEPTH, m_d_depth); + DDX_Text(pDX, IDC_BD_DPIXELS, m_d_pixels); + DDX_Text(pDX, IDC_BD_DPREC, m_d_prec); + DDV_MinMaxDouble(pDX, m_d_prec, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_BD_DMINANGLE, m_d_minangle); + DDV_MinMaxDouble(pDX, m_d_minangle, 1., MINANGLE_MAX); + DDX_Check(pDX, IDC_BD_DSHOWGRID, m_d_showgrid); + DDX_Check(pDX, IDC_BD_DSNAPGRID, m_d_snapgrid); + DDX_Check(pDX, IDC_BD_SHOW_ORIGIN, m_d_showorigin); + DDX_Check(pDX, IDC_BD_SHOW_NAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_DGRIDSIZE, m_IDC_d_gridsize); + DDX_Control(pDX, IDC_BD_DPIXELS, m_IDC_d_pixels); + DDX_Control(pDX, IDC_BD_DPREC, m_IDC_d_prec); + DDX_Control(pDX, IDC_BD_DDEPTH, m_IDC_d_depth); +} + + +BEGIN_MESSAGE_MAP(bdCPref, CDialog) + //{{AFX_MSG_MAP(bdCPref) + ON_BN_CLICKED(IDC_BD_MODBTN, OnModifyButton) + ON_BN_CLICKED(IDC_BD_RESTORE, OnRestoreColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCPref message handlers + +void bdCPref::OnModifyButton() +{ + CColorDialog dlg; + int i; + + UpdateData(); + i=m_d_color.GetCurSel(); + + dlg.m_cc.lpCustColors=clist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + else{ + } + +} + +BOOL bdCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_action.SetCurSel(s_action); + m_d_coord.SetCurSel(s_coord); + m_d_length.SetCurSel(s_length); + m_d_type.SetCurSel(s_type); + m_d_color.SetCurSel(0); + + UpdateData(FALSE); + + return TRUE; +} + + +void bdCPref::OnOK() +{ + UpdateData(); + + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + CDialog::OnOK(); +} + +void bdCPref::OnRestoreColors() +{ + if(MsgBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + clist[0]= dSelColor; + clist[1]= dMeshColor; + clist[2]= dBlockColor; + clist[3]= dLineColor; + clist[4]= dGridColor; + clist[5]= dNodeColor; + clist[6]= dBackColor; + clist[7]= dNameColor; + } +} + +BOOL bdCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +char* StripKey(char *c); + +void bdCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "beladraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",11)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_prec); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_minangle); + q[0]=NULL; + } + + if( _strnicmp(q,"",7)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_depth); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_coord); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_length); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_type); + q[0]=NULL; + } + + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&s_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_pixels); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&m_d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_shownames); + q[0]=NULL; + } + } + fclose(fp); + } +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void bdCPref::WritePrefs() +{ + FILE *fp; + CString fname; + + UpdateData(); + s_action=m_d_action.GetCurSel(); + s_coord=m_d_coord.GetCurSel(); + s_length=m_d_length.GetCurSel(); + s_type=m_d_type.GetCurSel(); + + fname=((CFemmApp *)AfxGetApp())->GetExecutablePath()+"beladraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",s_action); + fprintf(fp," = %g\n",m_d_pixels); + fprintf(fp," = %g\n",m_d_gridsize); + fprintf(fp," = %i\n",m_d_showgrid); + fprintf(fp," = %i\n",m_d_snapgrid); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_showorigin); + fprintf(fp," = %i\n",s_type); + fprintf(fp," = %i\n",s_length); + fprintf(fp," = %g\n",m_d_prec); + fprintf(fp," = %g\n",m_d_minangle); + fprintf(fp," = %g\n",m_d_depth); + fprintf(fp," = %i\n",s_coord); + + fclose(fp); + } +} \ No newline at end of file diff --git a/femm/bd_Pref.h b/femm/bd_Pref.h new file mode 100644 index 0000000..fd735bd --- /dev/null +++ b/femm/bd_Pref.h @@ -0,0 +1,68 @@ +// bd_Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bdCPref dialog + +class bdCPref : public CDialog +{ +// Construction +public: + + bdCPref(CWnd* pParent = NULL); // standard constructor + ~bdCPref(); + + COLORREF *clist; + int s_action; + int s_coord; + int s_length; + int s_type; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(bdCPref) + enum { IDD = IDD_BD_PREF }; + CComboBox m_d_color; + CComboBox m_d_type; + CComboBox m_d_length; + CComboBox m_d_coord; + CComboBox m_d_action; + double m_d_gridsize; + double m_d_pixels; + double m_d_prec; + double m_d_minangle; + double m_d_depth; + BOOL m_d_showgrid; + BOOL m_d_snapgrid; + BOOL m_d_showorigin; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCPref) + afx_msg void OnModifyButton(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnRestoreColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + CLuaEdit m_IDC_d_gridsize, m_IDC_d_depth; + CLuaEdit m_IDC_d_pixels, m_IDC_d_prec, m_IDC_d_minangle; + +}; diff --git a/femm/bd_PtProp.cpp b/femm/bd_PtProp.cpp new file mode 100644 index 0000000..23f2c53 --- /dev/null +++ b/femm/bd_PtProp.cpp @@ -0,0 +1,389 @@ +// PtProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_PtProp.h" +#include "bd_NodeProp.h" +#include "bd_MatDlg.h" +#include "bd_BdryDlg.h" +#include "bd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bdCPtProp dialog + + +bdCPtProp::bdCPtProp(CWnd* pParent /*=NULL*/) + : CDialog(bdCPtProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCPtProp) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void bdCPtProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCPtProp) + DDX_Control(pDX, IDC_NAME_LIST, m_namelist); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(bdCPtProp, CDialog) + //{{AFX_MSG_MAP(bdCPtProp) + ON_BN_CLICKED(IDC_ADD_PROP, OnAddProp) + ON_BN_CLICKED(IDC_DEL_PROP, OnDelProp) + ON_BN_CLICKED(IDC_MOD_PROP, OnModProp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bdCPtProp message handlers + +void bdCPtProp::OnAddProp() +{ + + // Code to deal with adding a Point Property. + if (PropType==0){ + CPointProp PProp; + CArray &nodeproplist=*pnodeproplist; + bdCNodeProp zDlg; + + for(int nn=0;nn &circproplist=*pcircproplist; + bdCCircProp zDlg; + for(int nn=0;nn &lineproplist=*plineproplist; + bdCBdryDlg zDlg; + for(int nn=0;nn &blockproplist=*pblockproplist; + bdCMatDlg zDlg; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (nodeproplist.GetSize()!=0)) + { + nodeproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (circproplist.GetSize()!=0)) + { + circproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (lineproplist.GetSize()!=0)) + { + lineproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (blockproplist.GetSize()!=0)) + { + blockproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } +} + +void bdCPtProp::OnModProp() +{ + // TODO: Add your control notification handler code here + if (PropType==0){ + CArray &nodeproplist=*pnodeproplist; + bdCNodeProp zDlg; + + if (nodeproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_vp=nodeproplist[k].V; + zDlg.m_qp=nodeproplist[k].qp; + zDlg.m_nodename=nodeproplist[k].PointName; + + for(int nn=0;nn &circproplist=*pcircproplist; + + if (circproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + bdCCircProp zDlg; + + zDlg.m_circname = circproplist[k].CircName; + zDlg.m_circtype = circproplist[k].CircType; + zDlg.m_q = circproplist[k].q; + zDlg.m_v = circproplist[k].V; + for(int nn=0;nn &lineproplist=*plineproplist; + bdCBdryDlg zDlg; + + if (lineproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_v =lineproplist[k].V; + zDlg.m_qs =lineproplist[k].qs; + zDlg.m_c0 =lineproplist[k].c0; + zDlg.m_c1 =lineproplist[k].c1; + zDlg.BdryFormat=lineproplist[k].BdryFormat; + zDlg.m_BdryName=lineproplist[k].BdryName; + for(int nn=0;nn &blockproplist=*pblockproplist; + bdCMatDlg zDlg; + + if (blockproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_ex=blockproplist[k].ex; + zDlg.m_ey=blockproplist[k].ey; + zDlg.m_qv=blockproplist[k].qv; + zDlg.m_BlockName=blockproplist[k].BlockName; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/bd_PtProp.h b/femm/bd_PtProp.h new file mode 100644 index 0000000..886ac29 --- /dev/null +++ b/femm/bd_PtProp.h @@ -0,0 +1,48 @@ +// bd_PtProp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bdCPtProp dialog + +class bdCPtProp : public CDialog +{ +// Construction +public: + bdCPtProp(CWnd* pParent = NULL); // standard constructor + + // variables CPrProp needs; + int PropType; + int ProblemType; + CArray *pnodeproplist; + CArray *plineproplist; + CArray *pblockproplist; + CArray *pcircproplist; + + +// Dialog Data + //{{AFX_DATA(bdCPtProp) + enum { IDD = IDD_PTPROP }; + CComboBox m_namelist; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCPtProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCPtProp) + afx_msg void OnAddProp(); + afx_msg void OnDelProp(); + afx_msg void OnModProp(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/bd_libdlg.cpp b/femm/bd_libdlg.cpp new file mode 100644 index 0000000..8a74333 --- /dev/null +++ b/femm/bd_libdlg.cpp @@ -0,0 +1,1175 @@ +// treetestDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_MatDlg.h" +#include "bd_libdlg.h" +#include "libfolderinfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bd_CLibDlg dialog + + +// CLuaConsoleDlg dialog + +bd_CLibDlg::bd_CLibDlg(CWnd* pParent /*=NULL*/) + : CResizableDialog(bd_CLibDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bd_CLibDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + // m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void bd_CLibDlg::DoDataExchange(CDataExchange* pDX) +{ + CResizableDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bd_CLibDlg) + DDX_Control(pDX, IDC_MYLIST, m_mylist); + DDX_Control(pDX, IDC_MYTREE, m_mytree); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(bd_CLibDlg, CResizableDialog) + //{{AFX_MSG_MAP(bd_CLibDlg) + ON_WM_QUERYDRAGICON() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYTREE, OnBegindragMytree) + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYLIST, OnBegindragMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYLIST, OnRclickMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYTREE, OnRclickMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYTREE, OnDblclkMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYLIST, OnDblclkMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYLIST, OnKeydownMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYTREE, OnKeydownMytree) + ON_WM_TIMER() + //}}AFX_MSG_MAP + ON_COMMAND(ID_EDIT_CUT, Zappit) + ON_COMMAND(ID_EDIT_COPY, AddNewProperty) + ON_COMMAND(ID_EDIT_PASTE, AddNewFolder) + ON_COMMAND(ID_EDIT_REPLACE, MouseModify) + ON_COMMAND(ID_EDIT_PASTE_LINK, VendorLink) + ON_COMMAND(ID_EDIT_FIND, ImportMaterials) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bd_CLibDlg message handlers + +BOOL bd_CLibDlg::OnInitDialog() +{ + CResizableDialog::OnInitDialog(); + + // TODO: Add extra initialization here + ////////////////////////////////////////////////////////////////// + + // preset layout + AddAnchor(IDOK,BOTTOM_RIGHT); + AddAnchor(IDCANCEL,BOTTOM_RIGHT); + AddAnchor(IDC_MYTREE,TOP_LEFT,BOTTOM_CENTER); + AddAnchor(IDC_MYLIST,TOP_CENTER,BOTTOM_RIGHT); + + CString LibName=BinDir+"statlib.dat"; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int i,k; + + Ancestors.RemoveAll(); + Parent=NULL; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + + // set up materials library tree control + m_bIsDragging = FALSE; + m_dragTargetTree = NULL; + m_dragTargetList = NULL; + m_dragItem = NULL; + m_imageList.Create( IDB_TREE, 16, 1, RGB(255,0,0) ); + m_mytree.SetImageList( &m_imageList, TVSIL_NORMAL ); + m_mylist.SetImageList( &m_imageList, TVSIL_NORMAL ); + + LibParent = m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Library Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + Parent=LibParent; + ModelParent = m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Model Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + + // Put Model's properties into the InModel edit box; + LibProps.RemoveAll(); + HTREEITEM hResult; + CArray &blockproplist=pDoc->blockproplist; + for(i=0;i=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + break; + + default: + + break; + } + } + + fclose(fp); + +/* + // tutorial example + HTREEITEM hChapter; + hChapter = m_mytree.InsertItem( "Chapter 1", 0, 1 ); + m_mytree.InsertItem( "What", 2, 2, hChapter ); +*/ + + Focus=NULL; + + return TRUE; // return TRUE unless you set the focus to a control +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR bd_CLibDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + + + + + +/////////////////////////////////////////////////// +// Implementation of library-specific file I/O +/////////////////////////////////////////////////// + +char* bd_CLibDlg::StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderName=v; + m_mytree.SetItemText(Parent,v); + 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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderURL=v; + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderVendor=v; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.ex=1.; + MProp.ey=1.; + MProp.qv=0.; + q[0]=NULL; + } + + // Library Hierarchy + if( _strnicmp(q,"",11)==0){ + q[0]=NULL; + return 3; + } + + 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.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.qv); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + q[0]=NULL; + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////// +// Drag-n-Drop Implementation + +void bd_CLibDlg::OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=LibParent) // can't drag top-level folder + { + CImageList* pDragImage; + pDragImage = m_mytree.CreateDragImage( m_dragItem ); + m_mytree.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + SetTimer ( 1, 75, NULL ) ; + bDragFromLibrary=TRUE; + } + + *pResult = 0; + +} + +void bd_CLibDlg::OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=ModelParent) + { + CImageList* pDragImage; + pDragImage = m_mylist.CreateDragImage( m_dragItem ); + m_mylist.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + bDragFromLibrary=FALSE; + SetTimer ( 1, 75, NULL ) ; + } + + *pResult = 0; +} + +void bd_CLibDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + CPoint ptDrag( point ); + CPoint ptTree( point ); + CPoint ptList( point ); + UINT uHitTest = TVHT_ONITEM; + + MapWindowPoints( this, &ptDrag, 1 ); + MapWindowPoints( &m_mytree, &ptTree, 1 ); + MapWindowPoints( &m_mylist, &ptList, 1 ); + + CImageList::DragMove( ptDrag ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + } + + CResizableDialog::OnMouseMove(nFlags, point); +} + +void bd_CLibDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + KillTimer ( 1 ) ; + CImageList::DragLeave( &m_mytree ); + CImageList::EndDrag(); + ReleaseCapture(); + m_bIsDragging = FALSE; + + // Do some logic to drop onto the main tree if the property is + // dropped onto the tree's window, but not exactly on the list + if((m_dragTargetTree==NULL) && (m_dragTargetList==NULL)) + { + POINT point; + GetCursorPos(&point); + void* pVoid = (void*)GetDesktopWindow()->WindowFromPoint(point); + if((void *) &m_mytree==pVoid) m_dragTargetTree=LibParent; + if((void *) &m_mylist==pVoid) m_dragTargetList=ModelParent; + } + + // Drop onto the Library tree + if( m_dragTargetTree != NULL ) + { + if(!IsTailChasing(m_dragItem,m_dragTargetTree)) + { + CopyItemToLibrary(m_dragItem,m_dragTargetTree); + if(bDragFromLibrary) m_mytree.DeleteItem( m_dragItem ); + } + } + + // Drop onto the model materials + if( m_dragTargetList != NULL ) + { + CopyItemToModel(m_dragItem,m_dragTargetList); + if(!bDragFromLibrary) m_mylist.DeleteItem( m_dragItem ); + } + } + else CResizableDialog::OnLButtonUp(nFlags, point); +} + +BOOL bd_CLibDlg::IsFolder(HTREEITEM hItem) +{ + int nImage1, nImage2, nSelImage; + m_mytree.GetItemImage(hItem,nImage1,nSelImage); + m_mylist.GetItemImage(hItem,nImage2,nSelImage); + if ((nImage1!=2) && (nImage2!=2)) return TRUE; + return FALSE; +} + +HTREEITEM bd_CLibDlg::CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(IsFolder(hTarget)) + { + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hTarget, TVI_LAST ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hTarget, TVI_LAST); + m_mytree.SetItemData(hResult,ItemData); + } + } + else + { + hParent = m_mytree.GetParentItem(hTarget); + + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + } + } + + + return hResult; +} + +HTREEITEM bd_CLibDlg::CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + if (IsFolder(hItem)) + { + hChild=m_mytree.GetChildItem(hItem) ; + hParent=hTarget; + while (hChild!=NULL) + { + hParent=CopyItemToModel(hChild,hParent) ; + hChild = m_mytree.GetNextSiblingItem(hChild); + } + hResult=hParent; + } + else{ + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + + hParent = m_mylist.GetParentItem( hTarget ); + if( hParent != NULL ) + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, hTarget); + else + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, TVI_LAST ); + m_mylist.SetItemData(hResult,ItemData); + } + + return hResult; +} + +void bd_CLibDlg::AddNewProperty() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetList!=NULL) + { + hParent = m_mylist.GetParentItem(m_dragTargetList); + if( hParent != NULL ) + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, m_dragTargetList); + else + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mylist.SetItemData(hResult,LibProps.GetUpperBound()); + } + + if(m_dragTargetTree!=NULL) + { + if(IsFolder(m_dragTargetTree)) hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Material", 2, 2, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Material", 2, 2, LibParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mytree.SetItemData(hResult,LibProps.GetUpperBound()); + } +} + +void bd_CLibDlg::AddNewFolder() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetTree!=NULL) + { + if (IsFolder(m_dragTargetTree)) + hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Folder", 0, 1, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Folder", 0, 1, LibParent, TVI_LAST ); + + CFolderProp FProp; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(hResult,FoldProps.GetUpperBound()); + } +} + +void bd_CLibDlg::Zappit() +{ + if ((m_dragTargetTree!=NULL) && (m_dragTargetTree!=LibParent)) + m_mytree.DeleteItem(m_dragTargetTree); + if ((m_dragTargetList!=NULL) && (m_dragTargetList!=ModelParent)) + m_mylist.DeleteItem(m_dragTargetList); +} + +void bd_CLibDlg::OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptTree(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptTree, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree==NULL) m_dragTargetTree=LibParent; + + VERIFY(pMenu->CreatePopupMenu()); + if(m_dragTargetTree!=LibParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Add New Folder")); + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)) + { + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + HTREEITEM hParent=m_mytree.GetParentItem(m_dragTargetTree); + if(hParent!=LibParent) + { + int k=(int) m_mytree.GetItemData(hParent); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + else if(m_dragTargetTree!=LibParent){ + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Edit Folder Info")); + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("bd_CLibDlg::OnRclickMytree failed to destroy menu resource\n"); + pMenu = FALSE; + } + + + *pResult = 0; +} + +void bd_CLibDlg::OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList==NULL) m_dragTargetList=ModelParent; + + VERIFY(pMenu->CreatePopupMenu()); + if (m_dragTargetList!=ModelParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("bd_CLibDlg::OnRclickMylist failed to destroy menu resource\n"); + pMenu = FALSE; + } + + *pResult = 0; +} + +void bd_CLibDlg::OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + + *pResult = 0; +} + +void bd_CLibDlg::OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptList, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptList, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + } + + *pResult = 0; +} + +void bd_CLibDlg::ModifyMaterial(int k) +{ + bdCMatDlg zDlg; + + zDlg.m_ex=LibProps[k].ex; + zDlg.m_ey=LibProps[k].ey; + zDlg.m_qv=LibProps[k].qv; + zDlg.m_BlockName=LibProps[k].BlockName; +// for(int nn=0;nnProblemType==0){ + zDlg.m_mu1label="x"; + zDlg.m_mu2label="y"; + } + else{ + zDlg.m_mu1label="r"; + zDlg.m_mu2label="z"; + } + if(zDlg.DoModal()==IDOK){ + LibProps[k].BlockName=zDlg.m_BlockName; + LibProps[k].ex=zDlg.m_ex; + LibProps[k].ey=zDlg.m_ey; + LibProps[k].qv=zDlg.m_qv; + } +} + +void bd_CLibDlg::MouseModify() +{ + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + else{ + CLibFolderInfo dlg; + + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + dlg.m_foldername =FoldProps[k].FolderName; + dlg.m_folderurl =FoldProps[k].FolderURL; + dlg.m_foldervendor=FoldProps[k].FolderVendor; + if (dlg.DoModal()==IDOK) + { + m_mytree.SetItemText(m_dragTargetTree,dlg.m_foldername); + FoldProps[k].FolderName =dlg.m_foldername; + FoldProps[k].FolderURL =dlg.m_folderurl; + FoldProps[k].FolderVendor=dlg.m_foldervendor; + } + } + } +} + +void bd_CLibDlg::OnOK() +{ + HTREEITEM hChild; + CArray &blockproplist=pDoc->blockproplist; + int k; + + // copy Model Materials into the model + blockproplist.RemoveAll(); + hChild=m_mylist.GetChildItem(ModelParent) ; + while (hChild!=NULL) + { + k=(int) m_mylist.GetItemData(hChild); + blockproplist.Add(LibProps[k]); + hChild = m_mylist.GetNextSiblingItem(hChild) ; + } + + // write Library Materials to disk + + CString LibName=BinDir+"statlib.dat"; + FILE *fp; + + if ((fp=fopen(LibName,"wt"))==NULL) return; + + hChild=m_mytree.GetChildItem(LibParent); + while(hChild!=NULL) + { + CopyItemToDisk(hChild,fp); + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fclose(fp); + + + CResizableDialog::OnOK(); +} + +void bd_CLibDlg::CopyItemToDisk(HTREEITEM hItem, FILE *fp) +{ + HTREEITEM hChild; + int i =(int) m_mytree.GetItemData(hItem); + + if (IsFolder(hItem)) + { + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderName); + if(FoldProps[i].FolderURL!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderURL); + if(FoldProps[i].FolderVendor!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderVendor); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToDisk(hChild,fp) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fprintf(fp,"\n"); + } + else{ + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) LibProps[i].BlockName); + fprintf(fp," = %.17g\n",LibProps[i].ex); + fprintf(fp," = %.17g\n",LibProps[i].ey); + fprintf(fp," = %.17g\n",LibProps[i].qv); + fprintf(fp,"\n\n"); + } +} + +void bd_CLibDlg::VendorLink() +{ + if (VendorURL!="") + ShellExecute(m_hWnd,"open",VendorURL,"","",SW_SHOWMAXIMIZED); + else + MsgBox("No URL available for %s",VendorName); +} + +void bd_CLibDlg::ImportMaterials() +{ + CFileDialog *fname_dia; + CString SourceFile; + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Magnetostatic Input File (*.fem) | *.fem; *.FEM | All Files (*.*) | *.*||", + NULL); + + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + + SourceFile=fname_dia->GetPathName(); + delete[] fname_dia; + + // Add selected properties to the library; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int k; + BOOL bToLibrary=TRUE; + + if ((fp=fopen(SourceFile,"rt"))==NULL) return; + + Ancestors.RemoveAll(); + if(m_dragTargetTree!=NULL){ + // importing into the library + // put the imported materials in a new folder + Parent=m_mytree.InsertItem("Imported Materials", 0, 1, LibParent, TVI_FIRST ); + FProp.FolderName="Imported Materials"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(Parent,FoldProps.GetUpperBound()); + } + else if(m_dragTargetList!=NULL){ + Parent=ModelParent; + bToLibrary=FALSE; + } + else return; + + while (fgets(s,1024,fp)!=NULL) + { + switch(ParseLine(s,fp,MProp)) + { + case 1: + + // add a material to library + k=(int) LibProps.GetSize(); + LibProps.Add(MProp); + if(bToLibrary) + m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + else + m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + break; + + case 2: + if (bToLibrary) + { + // open a new folder + if (Parent!=NULL) Ancestors.Add(Parent); + k=(int) FoldProps.GetSize(); + FoldProps.Add(FProp); + Parent=m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + FProp.FolderName,0,1,NULL,NULL,k,Parent,NULL); + } + + break; + + case 3: + if (bToLibrary) + { + // close a folder + k=(int) Ancestors.GetUpperBound(); + if (k>=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + } + break; + + default: + + break; + } + } + + fclose(fp); +} + +BOOL bd_CLibDlg::IsTailChasing(HTREEITEM hSource, HTREEITEM hDest) +{ + HTREEITEM hItem; + + hItem=hDest; + while(hItem!=NULL) + { + if(hSource==hItem) return TRUE; + hItem=m_mytree.GetParentItem(hItem); + } + + return FALSE; +} + +void bd_CLibDlg::OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mylist.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=ModelParent)) + m_mylist.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetList=m_mylist.GetSelectedItem(); + m_dragTargetTree=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + +void bd_CLibDlg::OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mytree.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=LibParent)) + m_mytree.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetTree=m_mytree.GetSelectedItem(); + m_dragTargetList=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + + +void bd_CLibDlg::OnTimer(UINT_PTR nIDEvent) +{ + POINT pt ; + GetCursorPos ( &pt ) ; + RECT rect ; + + + // check if Library needs to be scrolled and do it; + m_mytree.GetClientRect ( &rect ) ; + m_mytree.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mytree.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + // check if Model Materials needs to be scrolled and do it; + m_mylist.GetClientRect ( &rect ) ; + m_mylist.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mylist.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + CResizableDialog::OnTimer(nIDEvent); +} + + + + + diff --git a/femm/bd_libdlg.h b/femm/bd_libdlg.h new file mode 100644 index 0000000..afeebbd --- /dev/null +++ b/femm/bd_libdlg.h @@ -0,0 +1,105 @@ +#pragma once + +#include "ResizableDialog.h" + +// treetestDlg.h : header file +// + +#if !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) +#define AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// bd_CLibDlg dialog + +class bd_CLibDlg : public CResizableDialog +{ +// Construction +public: + bd_CLibDlg(CWnd* pParent = NULL); // standard constructor + + CbeladrawDoc *pDoc; + CArray LibProps; + CArray FoldProps; + CArray Ancestors; + HTREEITEM Parent; + HTREEITEM ModelParent; + HTREEITEM LibParent; + BOOL bDragFromLibrary; + CString BinDir; + CString VendorURL; + CString VendorName; + int Focus; + + int ParseLine(char *s, FILE *fp, CMaterialProp &MProp); + char* StripKey(char *c); + BOOL IsFolder(HTREEITEM hItem); + HTREEITEM CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget); + HTREEITEM CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget); + void CopyItemToDisk(HTREEITEM hItem, FILE *fp); + void VendorLink(); + void Zappit(); + void MouseModify(); + void AddNewProperty(); + void AddNewFolder(); + void ImportMaterials(); + void ModifyMaterial(int k); + BOOL IsTailChasing(HTREEITEM hSource, HTREEITEM hDest); + +// Dialog Data + //{{AFX_DATA(bd_CLibDlg) + enum { IDD = IDD_TREETEST_DIALOG }; + CTreeCtrl m_mylist; + CTreeCtrl m_mytree; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bd_CLibDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + HICON m_hIcon; + + // stuff needed to do CTreeCtrl properly + CImageList m_imageList; + BOOL m_bIsDragging; + HTREEITEM m_dragItem; + HTREEITEM m_dragTargetTree; + HTREEITEM m_dragTargetList; + + // Generated message map functions + //{{AFX_MSG(bd_CLibDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTimer(UINT_PTR nIDEvent); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) + + + + + diff --git a/femm/bd_movecopy.cpp b/femm/bd_movecopy.cpp new file mode 100644 index 0000000..561e64e --- /dev/null +++ b/femm/bd_movecopy.cpp @@ -0,0 +1,2274 @@ +// beladrawDoc.cpp : implementation of the CbeladrawDoc class (continued...) +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "beladrawView.h" +#include "bd_probdlg.h" +#include "bd_PtProp.h" +#include "bd_OpBlkDlg.h" +#include "bd_OpNodeDlg.h" +#include "bd_OpSegDlg.h" +#include "bd_OpArcSegDlg.h" +#include "ArcDlg.h" +#include "DXFImport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern BOOL bLinehook; +//----------------------------------------------------------------- + +BOOL CbeladrawDoc::ReadDXF(CString fname,double DefTol) +{ + FILE *fp; + int j,k; + CArray layerlist; + CString myLayer; + + if( (fp=fopen(fname,"rt"))==NULL ) return FALSE; + NoDraw=TRUE; + + // clear out any old drawing that we might have; +// 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(); + + char s[256]; + char v[256]; + BOOL PolylineFlag=FALSE; + CNode n[4]; + CSegment segm; + CArcSegment asegm; + CComplex c,p,q; + double R,a0,a1; + int xx,PolyLineClosed,firstpoint; + double angle=0; + + while (fgets(s,256,fp)!=NULL) + { + if (strncmp(s,"LAYER",5)==0) + { + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==2){ + sscanf(v,"%s",s); + myLayer=s; + layerlist.Add(myLayer); + } + } while(1>0); + } + + if (strncmp(s,"POINT",5)==0) + { + xx=0; + n[0].InGroup=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==10) { n[0].x=atof(v); xx=xx | 1; } + if (k==20) { n[0].y=atof(v); xx=xx | 2; } + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + if (xx==3) nodelist.Add(n[0]); + } + + if (strncmp(s,"LWPOLYLINE",10)==0) + { + int segs=0; + PolyLineClosed=FALSE; + firstpoint=-1; + angle = 0; + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + int n0,n1; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) angle=360.; + } + if (k==70) PolyLineClosed=TRUE; + if (xx==3){ + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + xx=0; + if(segs==0) firstpoint=j; + else{ + if(angle==0) + { + segm.n0=j; + segm.n1=j-1; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j-1; n1=j; } + else{ n0=j; n1=j-1; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + if ((PolyLineClosed==TRUE) && (firstpoint>=0) && (segs>0)) + { + // take care of closing the contour, if required. + j=(int) nodelist.GetSize()-1; + if(angle==0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + angle=0; + } + } + } + + + if (strncmp(s,"POLYLINE",8)==0) + { + PolylineFlag=-1; + firstpoint=-1; + PolyLineClosed=FALSE; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==70) { + j=atoi(v); + if (j==1) PolyLineClosed=TRUE; + } + } while(1>0); + + } + + if (strncmp(s,"SEQEND",6)==0) + { + PolylineFlag=FALSE; + int j = ((int) nodelist.GetSize())-1; + if ((PolyLineClosed==TRUE) && (firstpoint>=0)) + { + if (angle == 0.0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else + { + int n0, n1; + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + } + } + PolyLineClosed=FALSE; + angle = 0.0; + } + + if (strncmp(s,"VERTEX",6)==0) + { + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + double next_angle = 0.0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) next_angle=360.; + } + } while(1>0); + + if(xx==3) + { + nodelist.Add(n[0]); + if (angle != 0.0) + { + j = (int)nodelist.GetSize(); + + int n0, n1; + if(angle>0) { n0=j-2; n1=j-1; } + else{ n0=j-1; n1=j-2; angle=fabs(angle); } + + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + + if (xx==15) + { + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + segm.n0=j; segm.n1=j+1; + linelist.Add(segm); + } + } + + // catch ARCALIGNEDTEXT, which derails the ARC code... + if (strncmp(s,"ARCA",4)==0) s[0]=NULL; + + if (strncmp(s,"ARC",3)==0) + { + n[0].InGroup=0; + n[1].InGroup=0; + asegm.InGroup=0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + + if(xx==31) + { + if (a10); + + if(xx==7) + { + n[0].x=c.re+R; n[1].x=c.re-R; + n[0].y=c.im; n[1].y=c.im; + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + asegm.n0=j; asegm.n1=j+1; + asegm.MaxSideLength=5.; + asegm.ArcLength=180.; + arclist.Add(asegm); + asegm.n1=j; asegm.n0=j+1; + arclist.Add(asegm); + } + } + + } + + fclose(fp); + + // could be that nothing actually got read. We want to + // catch this case and tell the user about it. + if(nodelist.GetSize()==0) return FALSE; + + // suggest the proper tolerance + CComplex p0,p1; + CDXFImport dlg; + int i; + + p0=nodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=nodelist[i].x; + if(nodelist[i].yp1.im) p1.im=nodelist[i].y; + } + + R=abs(p1-p0)*1.e-04; + dlg.m_dxftol=floor(R/pow(10.,floor(log10(R))))*pow(10.,floor(log10(R))); + + if(DefTol<0) + { + dlg.DoModal(); + FancyEnforcePSLG(dlg.m_dxftol); + } + else + { + if (DefTol==0) DefTol=dlg.m_dxftol; + FancyEnforcePSLG(DefTol); + } + + NoDraw=FALSE; + + return TRUE; +} + +void CbeladrawDoc::RotateMove(CComplex c, double t, int EditAction) +{ + int i; + CComplex x,z; + + z=exp(I*t*PI/180); + + if(EditAction==0) + { + for(i=0;i newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i; + CComplex p0,p1; + double d; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the nodes; + for(i=0;i newnodes; + + newnodes.RemoveAll(); + + n0=ClosestNode(p0.re,p0.im); + n1=ClosestNode(p1.re,p1.im); + + // 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;i 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;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;iextmaxx) extmaxx=nodelist[i].x; + if(nodelist[i].yextmaxy) extmaxy=nodelist[i].y; + } + + } + + for(i=0;iextmaxx) extmaxx=p.re; + if(p.imextmaxy) 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 newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i,k; + CComplex p0,p1; + double d; + + bLinehook=ImportDXF; // kludge to stop the program from giving a crash if + // the user tries to exit during a dxf import. + + CbeladrawView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + pView=(CbeladrawView *)GetNextView(pos); + + FirstDraw=TRUE; +// pView->lua_zoomnatural(); + dxf_line_hook(); + pView->EditAction=4; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;iInvalidateRect(NULL); + dxf_line_hook(); + + // find out what tolerance is so that there are not nodes right on + // top of each other; + if(tol==0){ + if (newnodelist.GetSize()<2) d=1.e-08; + else{ + p0=newnodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the lines; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + // put in all of the arcs; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + UnselectAll(); + + // do one last check to eliminate shallow arcs that + // link up the same two points as a line segment; + for(i=0;i +#include +#include "bd_nosebl.h" +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + InGroup=0; + BoundaryMarker=""; + InConductor=""; +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CComplex CNode::CC() +{ + return CComplex(x,y); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + MaxSideLength=-1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + ArcLength=90.; + MaxSideLength=10.; + mySideLength=1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; + NormalDirection=TRUE; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + BlockType=""; + InGroup=0; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + ex=1.; + ey=1.; // permittivity, relative + qv=0.; // volume charge density, C/m^3 +} + +CMaterialProp::~CMaterialProp() +{ + +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + V=qs=c0=c1=0; + +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + V=0; // nodal voltage + qp=0; // point current density +} + +CCircuit::CCircuit() +{ + CircName="New Conductor"; + V=0; + q=0; + CircType=0; +}; + +CPeriodicBoundary::CPeriodicBoundary() +{ + BdryName=""; + BdryFormat=0; + nseg=0; + narc=0; + seg[0]=0; + seg[1]=0; +} + +CCommonPoint::CCommonPoint() +{ + x=y=t=0; +} + +void CCommonPoint::Order() +{ + int z; + + if(x>y){ + z=y; + y=x; + x=z; + } +} diff --git a/femm/bd_nosebl.h b/femm/bd_nosebl.h new file mode 100644 index 0000000..e91fa92 --- /dev/null +++ b/femm/bd_nosebl.h @@ -0,0 +1,184 @@ +namespace beladrawdata +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL NormalDirection; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength,mySideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + BOOL IsSelected; + CString BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CMaterialProp(); + ~CMaterialProp(); + + CString BlockName; + double ex,ey; // permittivity, relative + double qv; // and volume charge density + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + int BdryFormat; // type of boundary condition we are applying + // 0 = Fixed Voltage + // 1 = Mixed BC + // 2 = Surface Charge Density + // 3 = Periodic + // 4 = Antiperiodic + + double V; // Fixed value of V for BdryFormat=0; + double c0,c1; // Coefficients for BdryFormat=1; + double qs; // Surface charge density for Bdryformat=2; + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + double V; // prescribed nodal voltage + double qp; // point charge density + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + double V; + double q; + int CircType; + + private: + +}; + +class CPeriodicBoundary +{ + public: + + CPeriodicBoundary(); + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + int nseg; // number of segs with this bc + int narc; // number of arcs with this bc + int seg[2]; // (arc)segments to which is applied + + private: +}; + +class CCommonPoint +{ + public: + + CCommonPoint(); + void Order(); + + int x,y,t; + + private: +}; + +} + +using namespace beladrawdata; \ No newline at end of file diff --git a/femm/bd_probdlg.cpp b/femm/bd_probdlg.cpp new file mode 100644 index 0000000..bca8ae8 --- /dev/null +++ b/femm/bd_probdlg.cpp @@ -0,0 +1,96 @@ +// probdlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bd_probdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// probdlg dialog + + +bdCProbDlg::bdCProbDlg(CWnd* pParent /*=NULL*/) + : CDialog(bdCProbDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bdCProbDlg) + m_problem_note = _T(""); + m_precision = 1.e-8; + m_depth = 1.0; + m_minangle=DEFAULT_MINIMUM_ANGLE; + //}}AFX_DATA_INIT +} + + +void bdCProbDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bdCProbDlg) + DDX_Control(pDX, IDC_BD_LENGTH_UNITS, m_length_units); + DDX_Control(pDX, IDC_BSMART, m_bsmart); + DDX_Control(pDX, IDC_BD_PROBTYPE, m_probtype); + DDX_Text(pDX, IDC_BD_PROBNOTE, m_problem_note); + DDX_Text(pDX, IDC_BD_PRC, m_precision); + DDV_MinMaxDouble(pDX, m_precision, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_BD_MINANG, m_minangle); + DDV_MinMaxDouble(pDX, m_minangle, 1., MINANGLE_MAX); + DDX_Text(pDX, IDC_BD_EDIT_DEPTH, m_depth); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BD_EDIT_DEPTH, m_IDC_depth); + DDX_Control(pDX, IDC_BD_PROBNOTE, m_IDC_problem_note); + DDX_Control(pDX, IDC_BD_PRC, m_IDC_precision); + DDX_Control(pDX, IDC_BD_MINANG, m_IDC_minangle); +} + + +BEGIN_MESSAGE_MAP(bdCProbDlg, CDialog) + //{{AFX_MSG_MAP(bdCProbDlg) + ON_CBN_SELCHANGE(IDC_BD_LENGTH_UNITS, OnSelchangeLengthUnits) + ON_CBN_SELCHANGE(IDC_BD_PROBTYPE, OnSelchangeProbtype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// probdlg message handlers + +BOOL bdCProbDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_probtype.SetCurSel(probtype); + if(probtype) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); + + m_length_units.SetCurSel(lengthunits); + m_bsmart.SetCurSel(bsmart); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bdCProbDlg::OnOK() +{ + if (UpdateData()==FALSE) return; + probtype=m_probtype.GetCurSel(); + if(probtype) m_depth=1; + UpdateData(FALSE); + lengthunits=m_length_units.GetCurSel(); + bsmart=m_bsmart.GetCurSel(); + CDialog::OnOK(); +} + +void bdCProbDlg::OnSelchangeLengthUnits() +{ + +} + +void bdCProbDlg::OnSelchangeProbtype() +{ + if(m_probtype.GetCurSel()) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); +} diff --git a/femm/bd_probdlg.h b/femm/bd_probdlg.h new file mode 100644 index 0000000..460d55f --- /dev/null +++ b/femm/bd_probdlg.h @@ -0,0 +1,51 @@ +// bd_CProbDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bdCProbDlg dialog + +class bdCProbDlg : public CDialog +{ +// Construction +public: + bdCProbDlg(CWnd* pParent = NULL); // standard constructor + + BOOL probtype; // variable denoting problem type + // so list entry can be correctly set + int lengthunits; // contains units of length; + int bsmart; + +// Dialog Data + //{{AFX_DATA(bdCProbDlg) + enum { IDD = IDD_BD_PROBDLG }; + CComboBox m_length_units; + CComboBox m_bsmart; + CComboBox m_probtype; + CString m_problem_note; + double m_precision; + double m_minangle; + double m_depth; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bdCProbDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bdCProbDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeLengthUnits(); + afx_msg void OnSelchangeProbtype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_problem_note, m_IDC_precision, m_IDC_depth, m_IDC_minangle; +}; diff --git a/femm/bd_writepoly.cpp b/femm/bd_writepoly.cpp new file mode 100644 index 0000000..c35166c --- /dev/null +++ b/femm/bd_writepoly.cpp @@ -0,0 +1,1545 @@ +// implementation of various incarnations of calls +// to triangle from the CbeladrawDoc class + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "bd_probdlg.h" +#include "bd_PtProp.h" +#include "bd_OpBlkDlg.h" +#include "bd_OpNodeDlg.h" +#include "bd_OpSegDlg.h" +#include "bd_OpArcSegDlg.h" +#include "OpGrp.h" +#include "ArcDlg.h" + +extern BOOL bLinehook; +extern lua_State *lua; +extern HANDLE hProc; + +double CbeladrawDoc::LineLength(int i) +{ + return abs(nodelist[linelist[i].n0].CC()- + nodelist[linelist[i].n1].CC()); +} + + +BOOL CbeladrawDoc::HasPeriodicBC() +{ + BOOL flag=FALSE; + int i,j,k; + + for(i=0;i=0){ + if ((lineproplist[k].BdryFormat==4) || + (lineproplist[k].BdryFormat==3)) + { + 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==3)) + { + 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 CbeladrawDoc::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 CbeladrawDoc::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;iGetExecutablePath(); + + // read document default behaviors from disk + ScanPreferences(); + + // fire up lua + initalise_lua(); + + // initialize the data in the document + OnNewDocument(); +} + +CbeladrawDoc::~CbeladrawDoc() +{ + if (pBeladrawDoc==this) pBeladrawDoc=NULL; +} + +BOOL CbeladrawDoc::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; + 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 + CbeladrawView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + if (pos!=NULL){ + pView=(CbeladrawView *)GetNextView(pos); + if (pView!=NULL) pView->OnNewDocument(); + } + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawDoc serialization + +void CbeladrawDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawDoc diagnostics + +#ifdef _DEBUG +void CbeladrawDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CbeladrawDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawDoc commands + +void CbeladrawDoc::OnDefineProblem() +{ + bdCProbDlg 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_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; + ProblemNote = pDlg.m_problem_note; + ProblemType = pDlg.probtype; + LengthUnits = pDlg.lengthunits; + Depth = pDlg.m_depth; + } +} + +void CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::OpArcSegDlg() +{ + int i,j,k,nselected; + bdCOpArcSegDlg 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; + } + + // 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; + } + + // 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.V=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.V); + 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.V=0; + BProp.qs=0; + BProp.c0=0; + BProp.c1=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,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c1); + 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.ex=1.; + MProp.ey=1.; // permeabilities, relative + MProp.qv=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.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.qv); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + blockproplist.Add(MProp); + q[0]=NULL; + } + + // Circuit Properties + if( _strnicmp(q,"",16)==0){ + CProp.CircName="New Conductor"; + CProp.V=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.V); + 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].V); + 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].V); + fprintf(fp," = %.17g\n",lineproplist[i].qs); + fprintf(fp," = %.17g\n",lineproplist[i].c0); + fprintf(fp," = %.17g\n",lineproplist[i].c1); + 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].ex); + fprintf(fp," = %.17g\n",blockproplist[i].ey); + fprintf(fp," = %.17g\n",blockproplist[i].qv); + fprintf(fp," \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].V); + 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 CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::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 CbeladrawDoc::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) +#include + +#include "lua.h" +#include "luaconsoledlg.h" +#include "luadebug.h" + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +extern CFemmApp theApp; // + +// beladrawDoc.h : interface of the CbeladrawDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CbeladrawDoc : public CDocument +{ +protected: // create from serialization only + CbeladrawDoc(); + DECLARE_DYNCREATE(CbeladrawDoc) + +// Attributes +public: + + // General problem attributes + double Precision; + double MinAngle; + int SmartMesh; + double Depth; + int LengthUnits; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL NoDraw; + + // default behaviors + double d_prec; + double d_minangle; + double d_depth; + int d_coord; + int d_length; + int d_type; + + CString BinDir; + + // lists of nodes, segments, and block labels + CArray< beladrawdata::CNode, beladrawdata::CNode&> nodelist; + CArray< beladrawdata::CSegment, beladrawdata::CSegment&> linelist; + CArray< beladrawdata::CArcSegment, beladrawdata::CArcSegment&> arclist; + CArray< beladrawdata::CBlockLabel, beladrawdata::CBlockLabel&> blocklist; + + // lists of nodes, segments, and block labels for undo purposes... + CArray< beladrawdata::CNode, beladrawdata::CNode&> undonodelist; + CArray< beladrawdata::CSegment, beladrawdata::CSegment&> undolinelist; + CArray< beladrawdata::CArcSegment, beladrawdata::CArcSegment&> undoarclist; + CArray< beladrawdata::CBlockLabel, beladrawdata::CBlockLabel&> undoblocklist; + + // CArrays containing the mesh information + CArray< CPoint, CPoint&> meshline; + CArray< CPoint, CPoint&> greymeshline; + CArray< beladrawdata::CNode, beladrawdata::CNode&> meshnode; + + // lists of properties + CArray< beladrawdata::CMaterialProp, beladrawdata::CMaterialProp& > blockproplist; + CArray< beladrawdata::CBoundaryProp, beladrawdata::CBoundaryProp& > lineproplist; + CArray< beladrawdata::CPointProp, beladrawdata::CPointProp& > nodeproplist; + CArray< beladrawdata::CCircuit, beladrawdata::CCircuit& > circproplist; + double extRo,extRi,extZo; + +// Operations +public: + + void UnselectAll(); + double ShortestDistance(double p, double q, int segm); + + BOOL AddNode(double x, double y, double d); + + BOOL AddSegment(int n0, int n1, double tol=0); + BOOL AddSegment(int n0, int n1, beladrawdata::CSegment *parsegm, double tol=0); + BOOL AddArcSegment(beladrawdata::CArcSegment &asegm, double tol=0); + BOOL AddBlockLabel(double x, double y, double d); + BOOL AddNode(beladrawdata::CNode &node, double d); + BOOL AddSegment(CComplex p0, CComplex p1, beladrawdata::CSegment &segm, double tol=0); + BOOL AddArcSegment(CComplex p0, CComplex p1, beladrawdata::CArcSegment &asegm, double tol=0); + + BOOL AddBlockLabel(beladrawdata::CBlockLabel &blabel, double d); + int ClosestNode(double x, double y); + int ClosestBlockLabel(double x, double y); + int ClosestSegment(double x, double y); + BOOL GetIntersection(int n0, int n1, int segm, double *xi, double *yi); + int ClosestArcSegment(double x, double y); + void GetCircle(beladrawdata::CArcSegment &asegm,CComplex &c, double &R); + int GetLineArcIntersection(beladrawdata::CSegment &seg, beladrawdata::CArcSegment &arc, CComplex *p); + int GetArcArcIntersection(beladrawdata::CArcSegment &arc1, beladrawdata::CArcSegment &arc2, CComplex *p); + double ShortestDistanceFromArc(CComplex p, beladrawdata::CArcSegment &arc); + void RotateMove(CComplex c, double t, int EditAction); + void TranslateMove(double dx, double dy, int EditAction); + void ScaleMove(double bx, double by, double sf, int EditAction); + void MirrorSelected(double x0, double y0, double x1, double y1, int ea); + void RotateCopy(CComplex c, double t, int ncopies, int EditAction); + void TranslateCopy(double dx, double dy, int ncopies, int EditAction); + BOOL DeleteSelectedNodes(); + BOOL DeleteSelectedSegments(); + BOOL DeleteSelectedArcSegments(); + BOOL DeleteSelectedBlockLabels(); + BOOL OpBlkDlg(); + void OpNodeDlg(); + void OpSegDlg(); + void OpArcSegDlg(); + void OpGrpDlg(); + BOOL LoadMesh(); + BOOL OnWritePoly(); + BOOL FunnyOnWritePoly(); + BOOL ReadDXF(CString fname, double DefTol=-1.); + BOOL WriteDXF(CString fname); + BOOL HasPeriodicBC(); + BOOL CanCreateRadius(int n); + BOOL CreateRadius(int n, double r); + double LineLength(int i); + BOOL ScanPreferences(); + + void UpdateUndo(); + void Undo(); + void EnforcePSLG(); // makes sure that everything is kosher... + void EnforcePSLG(double tol); + void FancyEnforcePSLG(double tol); + BOOL SelectOrphans(); + BOOL dxf_line_hook(); +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CbeladrawDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + void initalise_lua(); + static int lua_prob_def(lua_State *L); + static int luaSaveDocument(lua_State *L); + static int lua_create_mesh(lua_State *L); + static int lua_smartmesh(lua_State *L); + static int lua_purge_mesh(lua_State *L); + static int lua_show_mesh(lua_State *L); + static int lua_analyze(lua_State *L); + static int lua_runpost(lua_State *L); + static int lua_addnode(lua_State *L); + static int lua_addlabel(lua_State *L); + static int lua_addline(lua_State *L); + static int lua_addarc(lua_State *L); + static int lua_selectnode(lua_State *L); + static int lua_selectlabel(lua_State *L); + static int lua_selectsegment(lua_State *L); + static int lua_selectarcsegment(lua_State *L); + static int lua_clearselected(lua_State *L); + static int lua_setnodeprop(lua_State *L); + static int lua_setblockprop(lua_State *L); + static int lua_setsegmentprop(lua_State *L); + static int lua_setarcsegmentprop(lua_State *L); + static int lua_deleteselected(lua_State *L); + static int lua_deleteselectedsegments(lua_State *L); + static int lua_deleteselectednodes(lua_State *L); + static int lua_deleteselectedlabels(lua_State *L); + static int lua_deleteselectedarcsegments(lua_State *L); + static int lua_zoomout(lua_State *L); + static int lua_zoomnatural(lua_State *L); + static int lua_zoomin(lua_State *L); + static int lua_move_translate(lua_State *L); + static int lua_move_rotate(lua_State *L); + static int lua_copy_translate(lua_State *L); + static int lua_copy_rotate(lua_State *L); + static int lua_mirror(lua_State *L); + static int lua_scale(lua_State *L); + static int lua_addmatprop(lua_State *L); + static int lua_addpointprop(lua_State *L); + static int lua_addboundprop(lua_State *L); + static int lua_addcircuitprop(lua_State *L); + static int lua_delcircuitprop(lua_State *L); + static int lua_delpointprop(lua_State *L); + static int lua_delboundprop(lua_State *L); + static int lua_delmatprop(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_selectgroup(lua_State *L); + static int lua_zoom(lua_State *L); + static int lua_newdocument(lua_State *L); + static int lua_savebitmap(lua_State * L); + static int lua_modmatprop(lua_State *L); + static int lua_modboundprop(lua_State *L); + static int lua_modpointprop(lua_State *L); + static int lua_modcircprop(lua_State *L); + static int lua_exitpre(lua_State *L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC); + static int lua_saveWMF(lua_State *L); + static int lua_updatewindow(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_showgrid(lua_State *L); + static int lua_hidegrid(lua_State *L); + static int lua_gridsnap(lua_State *L); + static int lua_setgrid(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int lua_readdxf(lua_State *L); + static int lua_savedxf(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_defineouterspace(lua_State *L); + static int lua_attachouterspace(lua_State *L); + static int lua_detachouterspace(lua_State *L); + static int lua_attachdefault(lua_State *L); + static int lua_detachdefault(lua_State *L); + static int lua_createradius(lua_State *L); + static int lua_gettitle(lua_State *L); + static int lua_setgroup(lua_State *L); + static int lua_getmaterial(lua_State *L); + static int lua_getboundingbox(lua_State *L); + static int lua_getprobleminfo(lua_State *L); + static int lua_selectcircle(lua_State *L); + static int lua_selectrectangle(lua_State *L); + virtual ~CbeladrawDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CbeladrawDoc) + afx_msg void OnDefineProblem(); + afx_msg void OnEditMatprops(); + afx_msg void OnEditPtprops(); + afx_msg void OnEditSegprops(); + afx_msg void OnEditCircprops(); + afx_msg void OnEditExterior(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); +char *ParseDbl(char *t, double *f); +char *ParseInt(char *t, int *f); \ No newline at end of file diff --git a/femm/beladrawLua.cpp b/femm/beladrawLua.cpp new file mode 100644 index 0000000..6300b49 --- /dev/null +++ b/femm/beladrawLua.cpp @@ -0,0 +1,2781 @@ +// beladrawDoc.cpp : implementation of the CbeladrawDoc class +// + +#include "stdafx.h" +#include "femm.h" +#include "beladrawDoc.h" +#include "beladrawView.h" +#include "promptbox.h" +#include "MainFrm.h" +#include "ChildFrm.h" + +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern void *pBeladrawDoc; +extern lua_State * lua; +extern BOOL bLinehook; +extern int m_luaWindowStatus; + +#define CatchNullDocument(); if (pBeladrawDoc==NULL)\ + { CString msg="No current electrostatics input in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//---------------------Lua Extensions------------------------ + +void CbeladrawDoc::initalise_lua() +{ + + // register lua extensions + lua_register(lua,"ei_setfocus",lua_switchfocus); + lua_register(lua,"ei_saveas",luaSaveDocument); + lua_register(lua,"ei_createmesh",lua_create_mesh); + lua_register(lua,"ei_smartmesh",lua_smartmesh); + lua_register(lua,"ei_showmesh",lua_show_mesh); + lua_register(lua,"ei_purgemesh",lua_purge_mesh); + lua_register(lua,"ei_probdef",lua_prob_def); + lua_register(lua,"ei_analyse",lua_analyze); + lua_register(lua,"ei_loadsolution",lua_runpost); + lua_register(lua,"ei_addnode",lua_addnode); + lua_register(lua,"ei_addblocklabel",lua_addlabel); + lua_register(lua,"ei_addsegment",lua_addline); + lua_register(lua,"ei_addarc",lua_addarc); + lua_register(lua,"ei_selectnode",lua_selectnode); + lua_register(lua,"ei_selectlabel",lua_selectlabel); + lua_register(lua,"ei_selectsegment",lua_selectsegment); + lua_register(lua,"ei_selectarcsegment",lua_selectarcsegment); + lua_register(lua,"ei_clearselected",lua_clearselected); + lua_register(lua,"ei_setnodeprop",lua_setnodeprop); + lua_register(lua,"ei_setblockprop",lua_setblockprop); + lua_register(lua,"ei_setsegmentprop",lua_setsegmentprop); + lua_register(lua,"ei_setarcsegmentprop",lua_setarcsegmentprop); + lua_register(lua,"ei_deleteselected",lua_deleteselected); + lua_register(lua,"ei_deleteselectednodes",lua_deleteselectednodes); + lua_register(lua,"ei_deleteselectedlabels",lua_deleteselectedlabels); + lua_register(lua,"ei_deleteselectedsegments",lua_deleteselectedsegments); + lua_register(lua,"ei_deleteselectedarcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"ei_zoomnatural",lua_zoomnatural); + lua_register(lua,"ei_zoomout",lua_zoomout); + lua_register(lua,"ei_zoomin",lua_zoomin); + lua_register(lua,"ei_zoom",lua_zoom); + lua_register(lua,"ei_addmaterial",lua_addmatprop); + lua_register(lua,"ei_addpointprop",lua_addpointprop); + lua_register(lua,"ei_addconductorprop",lua_addcircuitprop); + lua_register(lua,"ei_addboundprop",lua_addboundprop); + lua_register(lua,"ei_modifymaterial",lua_modmatprop); + lua_register(lua,"ei_modifyboundprop",lua_modboundprop); + lua_register(lua,"ei_modifypointprop",lua_modpointprop); + lua_register(lua,"ei_modifyconductorprop",lua_modcircprop); + lua_register(lua,"ei_deletematerial",lua_delmatprop); + lua_register(lua,"ei_deleteboundprop",lua_delboundprop); + lua_register(lua,"ei_deleteconductor",lua_delcircuitprop); + lua_register(lua,"ei_deletepointprop",lua_delpointprop); + lua_register(lua,"ei_moverotate",lua_move_rotate); + lua_register(lua,"ei_movetranslate",lua_move_translate); + lua_register(lua,"ei_copyrotate",lua_copy_rotate); + lua_register(lua,"ei_copytranslate",lua_copy_translate); + lua_register(lua,"ei_mirror",lua_mirror); + lua_register(lua,"ei_scale",lua_scale); + lua_register(lua,"ei_seteditmode",lua_seteditmode); + lua_register(lua,"ei_selectgroup",lua_selectgroup); + lua_register(lua,"ei_newdocument",lua_newdocument); + lua_register(lua,"ei_savebitmap",lua_savebitmap); + lua_register(lua,"ei_savemetafile",lua_saveWMF); + lua_register(lua,"ei_close",lua_exitpre); + lua_register(lua,"ei_refreshview",lua_updatewindow); + lua_register(lua,"ei_shownames",lua_shownames); + lua_register(lua,"ei_showgrid",lua_showgrid); + lua_register(lua,"ei_hidegrid",lua_hidegrid); + lua_register(lua,"ei_gridsnap",lua_gridsnap); + lua_register(lua,"ei_setgrid",lua_setgrid); + lua_register(lua,"ei_readdxf",lua_readdxf); + lua_register(lua,"ei_savedxf",lua_savedxf); + lua_register(lua,"ei_defineouterspace",lua_defineouterspace); + lua_register(lua,"ei_attachouterspace",lua_attachouterspace); + lua_register(lua,"ei_detachouterspace",lua_detachouterspace); + lua_register(lua,"ei_attachdefault",lua_attachdefault); + lua_register(lua,"ei_detachdefault",lua_detachdefault); + lua_register(lua,"ei_attach_default",lua_attachdefault); + lua_register(lua,"ei_detach_default",lua_detachdefault); + lua_register(lua,"ei_resize",luaResize); + lua_register(lua,"ei_minimize",luaMinimize); + lua_register(lua,"ei_maximize",luaMaximize); + lua_register(lua,"ei_restore", luaRestore); + lua_register(lua,"ei_createradius",lua_createradius); + lua_register(lua,"ei_gettitle",lua_gettitle); + lua_register(lua,"ei_get_title",lua_gettitle); + lua_register(lua,"ei_setgroup",lua_setgroup); + lua_register(lua,"ei_set_group",lua_setgroup); + lua_register(lua,"ei_getmaterial",lua_getmaterial); + lua_register(lua,"ei_get_material",lua_getmaterial); + lua_register(lua,"ei_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"ei_getboundingbox",lua_getboundingbox); + lua_register(lua,"ei_selectcircle",lua_selectcircle); + lua_register(lua,"ei_selectrectangle",lua_selectrectangle); + + + // compatibility lua function names + lua_register(lua,"ei_select_rectangle",lua_selectrectangle); + lua_register(lua,"ei_select_circle",lua_selectcircle); + lua_register(lua,"ei_define_outer_space",lua_defineouterspace); + lua_register(lua,"ei_attach_outer_space",lua_attachouterspace); + lua_register(lua,"ei_detach_outer_space",lua_detachouterspace); + lua_register(lua,"ei_set_focus",lua_switchfocus); + lua_register(lua,"ei_save_as",luaSaveDocument); + lua_register(lua,"ei_create_mesh",lua_create_mesh); + lua_register(lua,"ei_show_mesh",lua_show_mesh); + lua_register(lua,"ei_purge_mesh",lua_purge_mesh); + lua_register(lua,"ei_prob_def",lua_prob_def); + lua_register(lua,"ei_analyze",lua_analyze); + lua_register(lua,"ei_load_solution",lua_runpost); + lua_register(lua,"ei_add_node",lua_addnode); + lua_register(lua,"ei_add_block_label",lua_addlabel); + lua_register(lua,"ei_add_segment",lua_addline); + lua_register(lua,"ei_add_arc",lua_addarc); + lua_register(lua,"ei_select_node",lua_selectnode); + lua_register(lua,"ei_select_label",lua_selectlabel); + lua_register(lua,"ei_select_segment",lua_selectsegment); + lua_register(lua,"ei_select_arcsegment",lua_selectarcsegment); + lua_register(lua,"ei_clear_selected",lua_clearselected); + lua_register(lua,"ei_set_node_prop",lua_setnodeprop); + lua_register(lua,"ei_set_block_prop",lua_setblockprop); + lua_register(lua,"ei_set_segment_prop",lua_setsegmentprop); + lua_register(lua,"ei_set_arcsegment_prop",lua_setarcsegmentprop); + lua_register(lua,"ei_delete_selected",lua_deleteselected); + lua_register(lua,"ei_delete_selected_nodes",lua_deleteselectednodes); + lua_register(lua,"ei_delete_selected_labels",lua_deleteselectedlabels); + lua_register(lua,"ei_delete_selected_segments",lua_deleteselectedsegments); + lua_register(lua,"ei_delete_selected_arcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"ei_zoom_natural",lua_zoomnatural); + lua_register(lua,"ei_zoom_out",lua_zoomout); + lua_register(lua,"ei_zoom_in",lua_zoomin); + lua_register(lua,"ei_add_material",lua_addmatprop); + lua_register(lua,"ei_add_point_prop",lua_addpointprop); + lua_register(lua,"ei_add_conductor_prop",lua_addcircuitprop); + lua_register(lua,"ei_add_bound_prop",lua_addboundprop); + lua_register(lua,"ei_modify_material",lua_modmatprop); + lua_register(lua,"ei_modify_bound_prop",lua_modboundprop); + lua_register(lua,"ei_modify_point_prop",lua_modpointprop); + lua_register(lua,"ei_modify_conductor_prop",lua_modcircprop); + lua_register(lua,"ei_delete_material",lua_delmatprop); + lua_register(lua,"ei_delete_bound_prop",lua_delboundprop); + lua_register(lua,"ei_delete_conductor",lua_delcircuitprop); + lua_register(lua,"ei_delete_point_prop",lua_delpointprop); + lua_register(lua,"ei_move_rotate",lua_move_rotate); + lua_register(lua,"ei_move_translate",lua_move_translate); + lua_register(lua,"ei_copy_rotate",lua_copy_rotate); + lua_register(lua,"ei_copy_translate",lua_copy_translate); + lua_register(lua,"ei_set_edit_mode",lua_seteditmode); + lua_register(lua,"ei_select_group",lua_selectgroup); + lua_register(lua,"ei_new_document",lua_newdocument); + lua_register(lua,"ei_save_bitmap",lua_savebitmap); + lua_register(lua,"ei_save_metafile",lua_saveWMF); + lua_register(lua,"ei_refresh_view",lua_updatewindow); + lua_register(lua,"ei_show_grid",lua_showgrid); + lua_register(lua,"ei_hide_grid",lua_hidegrid); + lua_register(lua,"ei_grid_snap",lua_gridsnap); + lua_register(lua,"ei_set_grid",lua_setgrid); + lua_register(lua,"ei_show_names",lua_shownames); + lua_register(lua,"ei_read_dxf",lua_readdxf); + lua_register(lua,"ei_save_dxf",lua_savedxf); + lua_register(lua,"ei_create_radius",lua_createradius); + + pBeladrawDoc=(CbeladrawDoc *)this; +} + +int CbeladrawDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CbeladrawDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".fee") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for (int i=0;i<2;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CbeladrawDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".fee") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pBeladrawDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CbeladrawDoc::lua_exitpre(lua_State *L) +{ + CatchNullDocument(); + ((CbeladrawDoc *)pBeladrawDoc)->OnCloseDocument( ); + + return 0; +} + +int CbeladrawDoc::luaSaveDocument(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + int n; + n=lua_gettop(L); + + CString temp; + temp.Format("%s",lua_tostring(L,n)); + thisDoc->OnSaveDocument(temp); + thisDoc->SetPathName(temp); + + return 0; +} + +int CbeladrawDoc::lua_readdxf(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + double DefTol; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + if (n==2) DefTol=lua_todouble(L,2); + else DefTol=0; + + result=thisDoc->ReadDXF(DocTitle,DefTol); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CbeladrawDoc::lua_savedxf(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + + result=thisDoc->WriteDXF(DocTitle); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CbeladrawDoc::lua_prob_def(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + CString units,type; + int n; + n=lua_gettop(L); + + // error traps + int LengthUnits=-1; + int ProblemType=-1; + double Precision; + double MinAngle=-1; + + units.Format("%s",lua_tostring(L,1)); + type.Format("%s",lua_tostring(L,2)); + Precision=lua_todouble(L,3); + if(n>3) thisDoc->Depth=lua_todouble(L,4); + if(n>4) MinAngle =lua_todouble(L,5); + if(units=="inches") LengthUnits=0; + if(units=="millimeters") LengthUnits=1; + if(units=="centimeters") LengthUnits=2; + if(units=="meters") LengthUnits=3; + if(units=="mills") LengthUnits=4; + if(units=="mils") LengthUnits=4; + if(units=="micrometers") LengthUnits=5; + if(type=="planar") ProblemType=0; + if(type=="axi") ProblemType=1; + + + // error detection and nice variable handling + + if (LengthUnits==-1) + { + CString msg; + msg.Format("Unknown length unit %s",units); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + thisDoc->LengthUnits=LengthUnits; + } + + if (ProblemType==-1) + { + CString msg; + msg.Format("Unknown problem type %s",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->ProblemType=ProblemType; + } + + + if (Precision < 1.e-16 || Precision >1.e-8) + { + CString msg; + msg.Format("Invalid Precision %lf",Precision); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->Precision=Precision; + } + + if ((MinAngle <=MINANGLE_MAX) && (MinAngle>=1.)) + { + thisDoc->MinAngle=MinAngle; + } + + if (thisDoc->Depth<=0) thisDoc->Depth=1; + +// CString temp; +// temp.Format("%s",lua_tostring(L,n)); + + + + + return 0; +} + +int CbeladrawDoc::lua_create_mesh(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + theView->lnuMakeMesh(); + + return 1; +} + +int CbeladrawDoc::lua_smartmesh(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + if (lua_gettop(L)!=0) + { + int k = (int)lua_todouble(L,1); + if (k!=0) k=1; + thisDoc->SmartMesh=k; + } + + return 0; +} + +int CbeladrawDoc::lua_show_mesh(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + theView->lnu_show_mesh(); + + return 0; +} + +int CbeladrawDoc::lua_purge_mesh(lua_State *L) +{ + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + theView->lnu_purge_mesh(); + + return 0; +} + +int CbeladrawDoc::lua_analyze(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n>0) n=(int)lua_todouble(L,1); + if (n!=0) n=1; + + theView->lnu_analyze(n); + + return 0; +} + +int CbeladrawDoc::lua_runpost(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + CString pn = thisDoc->GetPathName(); + + if (pn.GetLength()==0){ + CString msg; + msg.Format("No results to display"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".res\""; + if (((CFemmApp *) AfxGetApp())->EOCheckIfAlreadyOpen(rootname)==FALSE) + AfxGetApp( )->OpenDocumentFile(rootname); + + return 0; +} + + +int CbeladrawDoc::lua_addnode(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + double x,y,d; + + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddNode(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + +int CbeladrawDoc::lua_addlabel(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + double x,y,d; + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddBlockLabel(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + + +int CbeladrawDoc::lua_addline(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + CPoint mypntstart,mypntend; + + double sx,sy,ex,ey; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + flag=thisDoc->AddSegment(thisDoc->ClosestNode(sx,sy),thisDoc->ClosestNode(ex,ey)); + + if(flag==TRUE) + { + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CbeladrawDoc::lua_addarc(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + double sx,sy,ex,ey; + double angle,maxseg; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + angle=lua_todouble(L,5); + maxseg=lua_todouble(L,6); + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + BOOL flag; + + CArcSegment asegm; + asegm.n0=thisDoc->ClosestNode(sx,sy); + asegm.n1=thisDoc->ClosestNode(ex,ey); + thisDoc->nodelist[asegm.n1].ToggleSelect(); + theView->DrawPSLG(); + + asegm.MaxSideLength=maxseg; + asegm.ArcLength=angle; + asegm.BoundaryMarker=""; + + flag=thisDoc->AddArcSegment(asegm); + flag=FALSE; + thisDoc->UnselectAll(); + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CbeladrawDoc::lua_selectnode(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->nodelist.GetSize()==0) return 0; + node=thisDoc->ClosestNode(mx,my); + thisDoc->nodelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[node].x); + lua_pushnumber(L,thisDoc->nodelist[node].y); + + return 2; +} + +int CbeladrawDoc::lua_selectlabel(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->blocklist.GetSize()==0) return 0; + node=thisDoc->ClosestBlockLabel(mx,my); + thisDoc->blocklist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->blocklist[node].x); + lua_pushnumber(L,thisDoc->blocklist[node].y); + + return 2; +} + + +int CbeladrawDoc::lua_selectsegment(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->linelist.GetSize()==0) return 0; + node=thisDoc->ClosestSegment(mx,my); + thisDoc->linelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].y); + + return 4; +} + + +int CbeladrawDoc::lua_selectarcsegment(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->arclist.GetSize()==0) return 0; + node=thisDoc->ClosestArcSegment(mx,my); + thisDoc->arclist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].y); + + return 4; +} + +int CbeladrawDoc::lua_clearselected(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + thisDoc->UnselectAll(); + return 0; +} + +int CbeladrawDoc::lua_setnodeprop(lua_State *L) +{ + CatchNullDocument(); + CString nodeprop,inconductor; + int groupno; + + nodeprop.Format("%s",lua_tostring(L,1)); + groupno=(int) lua_todouble(L,2); + inconductor.Format("%s",lua_tostring(L,3)); + + if (groupno<0) + { + CString msg; + msg.Format("Invalid group no %d",groupno); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int i; + + // check to see how many (if any) nodes are selected. + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].IsSelected==TRUE) + { + thisDoc->nodelist[i].InGroup=groupno; + thisDoc->nodelist[i].BoundaryMarker=nodeprop; + thisDoc->nodelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CbeladrawDoc::lua_setblockprop(lua_State *L) +{ + CatchNullDocument(); + CString blocktype; + BOOL automesh; + double meshsize; + int group; + + int n=lua_gettop(L); + + blocktype=""; + automesh=1; + meshsize=0; + group=0; + + if (n>0) blocktype.Format("%s",lua_tostring(L,1)); + if (n>1) automesh=(int) lua_todouble(L,2); + if (n>2) meshsize=lua_todouble(L,3); + if (n>3) group=(int) lua_todouble(L,4); + + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].MaxArea=PI*meshsize*meshsize/4.; + thisDoc->blocklist[i].BlockType=blocktype; + thisDoc->blocklist[i].InGroup=group; + if(automesh==1) thisDoc->blocklist[i].MaxArea=0; + } + } + + return 0; +} + +int CbeladrawDoc::lua_setsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString prop,inconductor; + double elesize; + int automesh,hide,group; + + prop.Format("%s",lua_tostring(L,1)); + elesize=lua_todouble(L,2); + automesh=(int) lua_todouble(L,3); + hide=(int) lua_todouble(L,4); + group=(int) lua_todouble(L,5); + inconductor.Format("%s",lua_tostring(L,6)); + + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + for(int i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].IsSelected==TRUE){ + if (automesh==1) thisDoc->linelist[i].MaxSideLength=-1; + else{ + if (elesize>0) + thisDoc->linelist[i].MaxSideLength=elesize; + else elesize=-1; + } + thisDoc->linelist[i].BoundaryMarker=prop; + thisDoc->linelist[i].Hidden=hide; + thisDoc->linelist[i].InGroup=group; + thisDoc->linelist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CbeladrawDoc::lua_setarcsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString boundprop,inconductor; + double maxsegdeg; + int hide,group; + + maxsegdeg=lua_todouble(L,1); + if (maxsegdeg>10) maxsegdeg=10; + if (maxsegdeg<=0) maxsegdeg=1; + boundprop.Format("%s",lua_tostring(L,2)); + hide=(int) lua_todouble(L,3); + group=(int) lua_todouble(L,4); + inconductor.Format("%s",lua_tostring(L,5)); + + CbeladrawDoc *thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int i; + + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].IsSelected==TRUE){ + thisDoc->arclist[i].BoundaryMarker=boundprop; + thisDoc->arclist[i].MaxSideLength=maxsegdeg; + thisDoc->arclist[i].Hidden=hide; + thisDoc->arclist[i].InGroup=group; + thisDoc->arclist[i].InConductor=inconductor; + } + } + + return 0; +} + +int CbeladrawDoc::lua_deleteselectednodes(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + thisDoc->DeleteSelectedNodes(); + return 0; +} + +int CbeladrawDoc::lua_deleteselectedlabels(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + thisDoc->DeleteSelectedBlockLabels(); + return 0; + +} + +int CbeladrawDoc::lua_deleteselectedsegments(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + thisDoc->DeleteSelectedSegments(); + return 0; +} + +int CbeladrawDoc::lua_deleteselectedarcsegments(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + thisDoc->DeleteSelectedArcSegments(); + return 0; +} + +int CbeladrawDoc::lua_deleteselected(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + thisDoc->DeleteSelectedSegments(); + thisDoc->DeleteSelectedArcSegments(); + thisDoc->DeleteSelectedNodes(); + thisDoc->DeleteSelectedBlockLabels(); + + return 0; +} + +int CbeladrawDoc::lua_newdocument(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + thisDoc->OnNewDocument(); + thisDoc->SetPathName("Untitled",FALSE); + thisDoc->SetTitle("Untitled"); + return 0; +} + + +int CbeladrawDoc::lua_zoomnatural(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomnatural(); + + return 0; +} + + +int CbeladrawDoc::lua_zoomout(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + theView->lua_zoomout(); + + return 0; +} + +int CbeladrawDoc::lua_zoomin(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + theView->lua_zoomin(); + + return 0; +} + +int CbeladrawDoc::lua_zoom(lua_State *L) +{ + CatchNullDocument(); + + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CRect r; + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CbeladrawDoc::lua_copy_rotate(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + // IF N=5 WE Have an edit action, if n=4 we dont ! + + int EditAction,copies; + + double x,y,angle; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + angle=lua_todouble(L,3); + copies=(int) lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for copy rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + thisDoc->RotateCopy(CComplex(x,y),angle,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + +int CbeladrawDoc::lua_copy_translate(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + int EditAction, copies; + double x,y; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + copies=(int) lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for copy translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->TranslateCopy(x,y,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + + +int CbeladrawDoc::lua_move_translate(lua_State *L) +{ + CatchNullDocument(); + + double x,y; + int EditAction; + + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + if (n==3) EditAction=(int) lua_todouble(L,3); + if (n==2) EditAction=theView->EditAction; + + if(n!=3 && n!=2) + { + CString msg; + msg.Format("Invalid number of parameters for move translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->TranslateMove(x,y,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + +int CbeladrawDoc::lua_move_rotate(lua_State *L) +{ + CatchNullDocument(); + + double x,y,shiftangle; + int EditAction; + + int n; + n=lua_gettop(L); + + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + shiftangle=lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for move rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->RotateMove(CComplex(x,y),shiftangle,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + + +int CbeladrawDoc::lua_mirror(lua_State *L) +{ + CatchNullDocument(); + double m_pax,m_pay,m_pbx,m_pby; + int EditAction; + + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + m_pax=lua_todouble(L,1); + m_pay=lua_todouble(L,2); + m_pbx=lua_todouble(L,3); + m_pby=lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for mirror"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->MirrorSelected(m_pax,m_pay,m_pbx,m_pby,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int CbeladrawDoc::lua_scale(lua_State *L) +{ + CatchNullDocument(); + int EditAction; + double x,y,scalefactor; + + int n; + n=lua_gettop(L); + + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + scalefactor=lua_todouble(L,3); + EditAction=(int) lua_todouble(L,4); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for scale"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->ScaleMove(x,y,scalefactor,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int CbeladrawDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CbeladrawDoc * thisDoc;CbeladrawView * theView; + + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int iEditAction; + iEditAction=-1; + + if (EditAction=="nodes") iEditAction=0; + if (EditAction=="segments") iEditAction=1; + if (EditAction=="blocks") iEditAction=2; + if (EditAction=="arcsegments") iEditAction=3; + if (EditAction=="group") iEditAction=4; + + if(iEditAction==-1) + { + CString msg; + msg.Format("Invalid Edit Action %s",EditAction); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + theView->EditAction=iEditAction; + } + + + return 0; +} + +int CbeladrawDoc::lua_selectgroup(lua_State *L) +{ + CatchNullDocument(); + int group,i; + group=(int) lua_todouble(L,1); + + if(group<0) + { + CString msg; + msg.Format("Invalid group %d",group); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + +// thisDoc->UnselectAll(); + + // select nodes + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].InGroup==group) + thisDoc->nodelist[i].IsSelected=TRUE; + } + + // select segments + for(i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].InGroup==group) + thisDoc->linelist[i].IsSelected=TRUE; + } + + // select arc segments + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].InGroup==group) + thisDoc->arclist[i].IsSelected=TRUE; + } + + // select blocks + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].InGroup==group) + thisDoc->blocklist[i].IsSelected=TRUE; + } + + + theView->EditAction=4; // set to group + + return 0; +} + + +int CbeladrawDoc::lua_addmatprop(lua_State *L) +{ + CatchNullDocument(); + + CMaterialProp m; + int n=lua_gettop(L); + + if (n>0) m.BlockName.Format("%s",lua_tostring(L,1)); + if (n>1){ + m.ex=lua_todouble(L,2); + m.ey=m.ex; + } + if(n>2) m.ey=lua_todouble(L,3); + if(n>3) m.qv=lua_todouble(L,4); + + ((CbeladrawDoc *)pBeladrawDoc)->blockproplist.Add(m); + + return 0; +} + + + +int CbeladrawDoc::lua_modmatprop(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k,modprop; + + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->blockproplist[k].BlockName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->blockproplist[k].ex=lua_todouble(L,3); + break; + case 2: + thisDoc->blockproplist[k].ey=lua_todouble(L,3); + break; + case 3: + thisDoc->blockproplist[k].qv=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CbeladrawDoc::lua_addboundprop(lua_State *L) +{ + CatchNullDocument(); + + CBoundaryProp m; + int n=lua_gettop(L); + + if(n>0) m.BdryName.Format("%s",lua_tostring(L,1)); + if(n>1) m.V=lua_todouble(L,2); + if(n>2) m.qs=lua_todouble(L,3); + if(n>3) m.c0=lua_todouble(L,4); + if(n>4) m.c1=lua_todouble(L,5); + if(n>5) m.BdryFormat=(int) lua_todouble(L,6); + + ((CbeladrawDoc *)pBeladrawDoc)->lineproplist.Add(m); + + return 0; +} + +int CbeladrawDoc::lua_modboundprop(lua_State *L) +{ + CatchNullDocument(); + CString BdryName; + int k,modprop; + + CbeladrawDoc * thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + // find the index of the boundary property to modify; + if (thisDoc->lineproplist.GetSize()==0) return TRUE; + BdryName.Format("%s",lua_tostring(L,1)); + for(k=0;klineproplist.GetSize();k++) + if(BdryName==thisDoc->lineproplist[k].BdryName) break; + + // get out of here if there's no matching material + if(k==thisDoc->lineproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->lineproplist[k].BdryName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->lineproplist[k].V =lua_todouble(L,3); + break; + case 2: + thisDoc->lineproplist[k].qs =lua_todouble(L,3); + break; + case 3: + thisDoc->lineproplist[k].c0 =lua_todouble(L,3); + break; + case 4: + thisDoc->lineproplist[k].c1 =lua_todouble(L,3); + break; + case 5: + thisDoc->lineproplist[k].BdryFormat=(int)lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CbeladrawDoc::lua_addpointprop(lua_State *L) +{ + CatchNullDocument(); + + CPointProp m; + int n=lua_gettop(L); + + if(n>0) m.PointName.Format("%s",lua_tostring(L,1)); + if(n>1) m.V=lua_todouble(L,2); + if(n>2) m.qp=lua_todouble(L,3); + + ((CbeladrawDoc *)pBeladrawDoc)->nodeproplist.Add(m); + + return 0; +} + +int CbeladrawDoc::lua_modpointprop(lua_State *L) +{ + CatchNullDocument(); + CString PointName; + int k,modprop; + + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + // find the index of the material to modify; + if (thisDoc->nodeproplist.GetSize()==0) return TRUE; + PointName.Format("%s",lua_tostring(L,1)); + for(k=0;knodeproplist.GetSize();k++) + if(PointName==thisDoc->nodeproplist[k].PointName) break; + + // get out of here if there's no matching material + if(k==thisDoc->nodeproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->nodeproplist[k].PointName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->nodeproplist[k].V=lua_todouble(L,3); + break; + case 2: + thisDoc->nodeproplist[k].qp=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CbeladrawDoc::lua_addcircuitprop(lua_State *L) +{ + CatchNullDocument(); + + CCircuit m; + int n=lua_gettop(L); + + if(n>0) m.CircName=lua_tostring(L,1); + if(n>1) m.V=lua_todouble(L,2); + if(n>2) m.q=lua_todouble(L,3); + if(n>3) m.CircType=(int) lua_todouble(L,4); + + ((CbeladrawDoc *)pBeladrawDoc)->circproplist.Add(m); + + return 0; +} + +int CbeladrawDoc::lua_modcircprop(lua_State *L) +{ + CatchNullDocument(); + CString CircName; + int k,modprop; + + CbeladrawDoc * thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + // find the index of the material to modify; + if (thisDoc->circproplist.GetSize()==0) return TRUE; + CircName.Format("%s",lua_tostring(L,1)); + for(k=0;kcircproplist.GetSize();k++) + if(CircName==thisDoc->circproplist[k].CircName) break; + + // get out of here if there's no matching circuit + if(k==thisDoc->circproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->circproplist[k].CircName.Format("%s",lua_tostring(L,3)); + break; + case 3: + thisDoc->circproplist[k].CircType=(int) lua_todouble(L,3); + break; + case 1: + thisDoc->circproplist[k].V=lua_todouble(L,3); + break; + case 2: + thisDoc->circproplist[k].q=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CbeladrawDoc::lua_delcircuitprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CbeladrawDoc * thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;icircproplist.GetSize();i++) + { + if (thisDoc->circproplist[i].CircName==name) + thisDoc->circproplist.RemoveAt(i); + + } + + return 0; +} + +int CbeladrawDoc::lua_delmatprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;iblockproplist.GetSize();i++) + { + if (thisDoc->blockproplist[i].BlockName==name) + thisDoc->blockproplist.RemoveAt(i); + + } + + return 0; +} + + +int CbeladrawDoc::lua_delboundprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;ilineproplist.GetSize();i++) + { + if (thisDoc->lineproplist[i].BdryName==name) + thisDoc->lineproplist.RemoveAt(i); + } + + + return 0; +} + +int CbeladrawDoc::lua_delpointprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CbeladrawDoc *thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;inodeproplist.GetSize();i++) + { + if (thisDoc->nodeproplist[i].PointName==name) + thisDoc->nodeproplist.RemoveAt(i); + } + + return 0; +} + +int CbeladrawDoc::lua_updatewindow(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CDC tempDC; + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // force redraw + theView->OnDraw(pDC); + + return 0; +} + + +int CbeladrawDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + return 0; +} + + +PBITMAPINFO CbeladrawDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy1"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits != 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CbeladrawDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy2"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy3"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy4"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy5"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy6"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy7"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy8"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + + +int CbeladrawDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CbeladrawDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CbeladrawDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CbeladrawDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CbeladrawDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->InvalidateRect(NULL); + + return 0; +} + +int CbeladrawDoc::lua_shownames(lua_State * L) +{ + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +void CbeladrawView::lnuMakeMesh() +{ + OnMakeMesh(); +} + +void CbeladrawView::lnu_purge_mesh() +{ + OnPurgemesh(); +} + +void CbeladrawView::lnu_show_mesh() +{ + OnShowMesh(); +} + +void CbeladrawView::lnu_analyze(int bShow) +{ + if (bShow>0) bLinehook=HiddenLua; + else bLinehook=NormalLua; + OnMenuAnalyze(); +} + +void CbeladrawView::lua_zoomnatural() +{ + OnZoomNatural(); +} + +void CbeladrawView::lua_zoomout() +{ + OnZoomOut(); +} + +void CbeladrawView::lua_zoomin() +{ + OnZoomIn(); +} + +int CbeladrawDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CbeladrawDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CbeladrawDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CbeladrawDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int CbeladrawDoc::lua_defineouterspace(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + int n=lua_gettop(L); + if (n!=3) return 0; + + thisDoc->extZo = fabs(lua_todouble(L,1)); + thisDoc->extRo = fabs(lua_todouble(L,2)); + thisDoc->extRi = fabs(lua_todouble(L,3)); + + if((thisDoc->extRo==0) || (thisDoc->extRi==0)) + { + thisDoc->extZo = 0; + thisDoc->extRo = 0; + thisDoc->extRi = 0; + } + + return 0; +} + +int CbeladrawDoc::lua_attachouterspace(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=TRUE; + + return 0; +} + +int CbeladrawDoc::lua_detachouterspace(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=FALSE; + + return 0; +} + +int CbeladrawDoc::lua_createradius(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + CbeladrawView * theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n!=3) return 0; + + double x,y,r; + int k; + + x = lua_todouble(L,1); + y = lua_todouble(L,2); + r = fabs(lua_todouble(L,3)); + + if ((k=thisDoc->ClosestNode(x,y))<0) return 0; // catch case where no nodes have been drawn yet; + + if (thisDoc->CanCreateRadius(k)==FALSE) + { + CString msg; + msg.Format("The specified point is not suitable for conversion into a radius"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + if (thisDoc->CreateRadius(k,r)) + { + theView->InvalidateRect(NULL); + theView->MeshUpToDate=FALSE; + } + else{ + CString msg; + msg.Format("Could not make a radius of the prescribed dimension"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + return 0; +} + +int CbeladrawDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + +int CbeladrawDoc::lua_setgroup(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + int grp,i; + + int n=lua_gettop(L); + + if (n>0) grp =(int) lua_todouble(L,1); + else return 0; + + for(i=0;inodelist.GetSize();i++) + if(thisDoc->nodelist[i].IsSelected==TRUE) + thisDoc->nodelist[i].InGroup=grp; + + for(i=0;ilinelist.GetSize();i++) + if(thisDoc->linelist[i].IsSelected==TRUE) + thisDoc->linelist[i].InGroup=grp; + + for(i=0;iarclist.GetSize();i++) + if(thisDoc->arclist[i].IsSelected==TRUE) + thisDoc->arclist[i].InGroup=grp; + + for(i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].InGroup=grp; + + thisDoc->UnselectAll(); + + return 0; +} + +int CbeladrawDoc::lua_getmaterial(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + CString matname; + int n=lua_gettop(L); + + if (n>0) matname=lua_tostring(L,1); + else return 0; + + CString LibName=thisDoc->BinDir+"statlib.dat"; + + FILE *fp; + int i,k; + char s[1024],q[1024]; + char *v; + + CMaterialProp MProp; + + if ((fp=fopen(LibName,"rt"))==NULL){ + CString msg; + msg.Format("Couldn't open %s",LibName); + lua_error(L,msg.GetBuffer(1)); + return FALSE; + } + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + if (sscanf(s,"%s",q)==EOF) q[0]=NULL; + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.ex=1.; + MProp.ey=1.; + MProp.qv=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.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.qv); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + if (MProp.BlockName==matname){ + thisDoc->blockproplist.Add(MProp); + fclose(fp); + return 0; + } + q[0]=NULL; + } + } + + fclose(fp); + + CString msg; + msg.Format("Couldn't load \"%s\" from the materials library",matname); + lua_error(L,msg.GetBuffer(1)); + return FALSE; +} + +int CbeladrawDoc::lua_attachdefault(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0,j=0;iblocklist.GetSize();i++) + { + if ((thisDoc->blocklist[i].IsSelected==TRUE) && (j==0)) + { + thisDoc->blocklist[i].IsDefault=2; + j++; + } + else thisDoc->blocklist[i].IsDefault=FALSE; + } + + return 0; +} + +int CbeladrawDoc::lua_detachdefault(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsDefault=FALSE; + + return 0; +} + +int CbeladrawDoc::lua_getprobleminfo(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Depth); + switch (thisDoc->LengthUnits) + { + case 1: // mm + lua_pushnumber(L,0.001); + break; + case 2: // cm + lua_pushnumber(L,0.01); + break; + case 3: // m + lua_pushnumber(L,1.0); + break; + case 4: // mils + lua_pushnumber(L,2.54e-05); + break; + case 5: // um + lua_pushnumber(L,1.0e-06); + break; + default:// inches + lua_pushnumber(L,0.0254); + break; + } + return 3; +} + +int CbeladrawDoc::lua_getboundingbox(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc *thisDoc; + CbeladrawView *theView; + thisDoc=(CbeladrawDoc *)pBeladrawDoc; + + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)thisDoc->GetNextView(pos); + + double x[2],y[2]; + if (theView->GetBoundingBox(x,y)) + { + lua_pushnumber(L,x[0]); + lua_pushnumber(L,x[1]); + lua_pushnumber(L,y[0]); + lua_pushnumber(L,y[1]); + return 4; + } + else return 0; +} + +int CbeladrawDoc::lua_selectcircle(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * pDoc; + CbeladrawView * theView; + + pDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double R; + CComplex c,q; + + n=lua_gettop(L); + if (n<3) return 0; + c=lua_tonumber(L,1)+I*lua_tonumber(L,2); + R=lua_todouble(L,3); + if (n>3) EditAction=(int) lua_todouble(L,4); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} + +int CbeladrawDoc::lua_selectrectangle(lua_State *L) +{ + CatchNullDocument(); + CbeladrawDoc * pDoc; + CbeladrawView * theView; + + pDoc=(CbeladrawDoc *)pBeladrawDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CbeladrawView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double mx,my,wzx,wzy,x,y,z; + + n=lua_gettop(L); + if (n<4) return 0; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + wzx=lua_todouble(L,3); + wzy=lua_todouble(L,4); + if (n>4) EditAction=(int) lua_todouble(L,5); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} \ No newline at end of file diff --git a/femm/beladrawView.cpp b/femm/beladrawView.cpp new file mode 100644 index 0000000..e5d9ae5 --- /dev/null +++ b/femm/beladrawView.cpp @@ -0,0 +1,3288 @@ +// beladrawView.cpp : implementation of the CbeladrawView class +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "beladrawDoc.h" +#include "beladrawView.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "GRIDDLG.h" +#include "EnterPt.h" +#include "KbdZoom.h" +#include "ArcDlg.h" +#include "CopyDlg.h" +#include "scaledlg.h" +#include "MirrorDlg.h" +#include "GroupNumber.h" +#include "bd_libdlg.h" +#include "PromptBox.h" +#include "MakeABCDlg.h" + +#include + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +extern lua_State * lua; +extern BOOL bLinehook; +extern HANDLE hProc; + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView + +IMPLEMENT_DYNCREATE(CbeladrawView, CView) + +BEGIN_MESSAGE_MAP(CbeladrawView, CView) + //{{AFX_MSG_MAP(CbeladrawView) + ON_COMMAND(ID_NODE_OP, OnNodeOp) + ON_COMMAND(ID_SEGMENT_OP, OnSegmentOp) + ON_COMMAND(ID_BLOCK_OP, OnBlockOp) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_WM_KEYDOWN() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWnd) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_MAKE_MESH, OnMakeMesh) + ON_COMMAND(ID_MENU_ANALYZE, OnMenuAnalyze) + ON_COMMAND(ID_MENU_VIEWRES, OnMenuViewres) + ON_COMMAND(ID_ARCSEG_OP, OnArcsegOp) + ON_COMMAND(ID_UNDO, OnUndo) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_COMMAND(ID_MOVE_OBJECTS, OnMoveObjects) + ON_COMMAND(ID_COPY_OBJECTS, OnCopyObjects) + ON_COMMAND(ID_DXFIN, OnDxfin) + ON_COMMAND(ID_PURGEMESH, OnPurgemesh) + ON_COMMAND(ID_DXFWRITE, OnDxfwrite) + ON_COMMAND(ID_SELECTWND, OnSelectwnd) + ON_COMMAND(ID_SELECTCIRC, OnBDSelectCirc) + ON_WM_ERASEBKGND() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_MENU_MATLIB, OnMenuMatlib) + ON_COMMAND(ID_GROUP_OP, OnGroupOp) + ON_COMMAND(ID_OPEN_SELECTED, OnOpenSelected) + ON_COMMAND(ID_EDIT_SCALE, OnEditScale) + ON_COMMAND(ID_EDIT_MIRROR, OnEditMirror) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames) + ON_COMMAND(ID_VIEW_SHOWORPHANS, OnViewShowOrphans) + ON_COMMAND(ID_CREATERADIUS, OnCreateRadius) + ON_UPDATE_COMMAND_UI(ID_EDIT_EXTERIOR, OnUpdateEditExterior) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_COMMAND(ID_EDIT_CREATEOPENBOUNDARY, &CbeladrawView::OnMakeABC) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView construction/destruction + +CbeladrawView::CbeladrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // Default Colors + SelColor = RGB(255,0,0); + MeshColor = RGB(213,228,20); + BlockColor = RGB(0,125,0); + LineColor = RGB(0,0,255); + GridColor = RGB(0,0,255); + NodeColor = RGB(0,0,0); + BackColor = RGB(255,255,255); + NameColor = RGB(0,0,0); + + // assume some default behaviors if they can't be + // loaded from disk + d_action=0; + d_mag=100.; + d_gridsize=0.25; + d_showgrid=TRUE; + d_snapgrid=FALSE; + d_showorigin=FALSE; + d_shownames=TRUE; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // now, set default look for the preprocessor; + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + MaxSeg = 1.0; + ArcAngle = 90.0; +} + +void CbeladrawView::OnNewDocument() +{ + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) return; + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + if (StatBar==NULL) return; + + // update check boxes in the main menu... + EditAction=d_action; + GridFlag=d_showgrid; + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(d_action==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(d_action==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(d_action==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(d_action==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(d_action==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(d_showgrid==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(d_snapgrid==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(d_shownames==TRUE) + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); +} + +CbeladrawView::~CbeladrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL CbeladrawView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView drawing + +void CbeladrawView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +void CbeladrawView::DrawPSLG() +{ + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen,penMesh; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penBlack.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + + CbeladrawDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + + // make sure all the right boxes are checked. + { + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r); + if(d_showorigin==TRUE) + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penBlack ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlack ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw node block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + + ReleaseDC(pDC); +} + +BOOL CbeladrawView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CbeladrawView::OnDraw(CDC* pDC) +{ + CbeladrawDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if(pDoc->NoDraw==TRUE) return; + + // TODO: add draw code for native data here + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + if (pDoc->FirstDraw==TRUE) OnZoomNatural(); + + CPen *pOldPen; + CPen penBlue,penRed,penNode,penGreen,penMesh,penGrey; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penGrey.CreatePen(PS_SOLID,1,RGB(220,220,220)); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=1.1; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + if(MeshFlag==TRUE) + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penNode ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->meshline[i].x].xs, + pDoc->meshnode[pDoc->meshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->meshline[i].y].xs, + pDoc->meshnode[pDoc->meshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + + pOldPen = pDC->SelectObject( &penGrey ); + for(i=0;igreymeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].x].xs, + pDoc->meshnode[pDoc->greymeshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].y].xs, + pDoc->meshnode[pDoc->greymeshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + } + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +void CbeladrawView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + EditAction=d_action; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + CheckIt(); +} + +void CbeladrawView::CheckIt() +{ + // once again, this is sort of a punt + // to make sure that the right buttons + // are checked. It can be relatively + // easy to change the internal flags + // associated with the buttons without + // taking the time to service the button + // state otherwise. + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame()"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + + // update check boxes in the main menu... + + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(EditAction==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(EditAction==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(EditAction==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(EditAction==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(EditAction==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(GridFlag==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(SnapFlag==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(ShowNames==TRUE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView printing + +BOOL CbeladrawView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CbeladrawView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CbeladrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView diagnostics + +#ifdef _DEBUG +void CbeladrawView::AssertValid() const +{ + CView::AssertValid(); +} + +void CbeladrawView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CbeladrawDoc* CbeladrawView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CbeladrawDoc))); + return (CbeladrawDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CbeladrawView message handlers + +void CbeladrawView::OnNodeOp() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,TRUE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CbeladrawView::OnSegmentOp() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=1; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,TRUE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CbeladrawView::OnArcsegOp() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=3; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,TRUE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} +void CbeladrawView::OnBlockOp() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,TRUE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + + +void CbeladrawView::OnGroupOp() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=4; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,TRUE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CbeladrawView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CbeladrawDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ( (SnapFlag==TRUE) && ((EditAction==0) || (EditAction==2)) ) + { + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + if((ZoomWndFlag==2) || (SelectWndFlag==2)){ + + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + + } + + if(SelectCircFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + double R; + CComplex q; + + int xso,yso,xsi,ysi,xsn,ysn,i,k; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old circle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + R=abs((xso-xsn)+I*(yso-ysn)); + for(i=1;i<=(int)(2.*PI*R);i++){ + q=R*exp(I*((double) i)/R)+(xso+I*yso); + ocol=pDC->GetPixel((int) Re(q),(int) Im(q)); + p.c=ocol; p.x=(int) Re(q); p.y=(int) Im(q); + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel((int) Re(q),(int) Im(q),ocol); + } + + ReleaseDC(pDC); + + } + + // update mouse location; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CbeladrawView::OnZoomIn() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + InvalidateRect(NULL); +} + +void CbeladrawView::OnZoomOut() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + InvalidateRect(NULL); +} + +BOOL CbeladrawView::GetBoundingBox(double *x, double *y) +{ + // look at points, block labels, and arcs to get bounding box. + CbeladrawDoc *pDoc=GetDocument(); + int i,j,k; + double R,dt; + CComplex p,s,c; + + if (pDoc->nodelist.GetSize()<2) return FALSE; + + x[0]=pDoc->nodelist[0].x; x[1]=pDoc->nodelist[0].x; + y[0]=pDoc->nodelist[0].y; y[1]=pDoc->nodelist[0].y; + for(i=1;inodelist.GetSize();i++) + { + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + { + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;iarclist.GetSize();i++) + { + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + return TRUE; +} + +void CbeladrawView::OnZoomNatural() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + + if (GetBoundingBox(x,y)==FALSE) return; + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0]) > (y[1]-y[0])) w=(x[1]-x[0]); + else w=(y[1]-y[0]); + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-0.5)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) + pDoc->FirstDraw=FALSE; + else InvalidateRect(NULL); +} + +void CbeladrawView::OnBDSelectCirc() +{ + SelectCircFlag=TRUE; + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,TRUE); +} + +void CbeladrawView::OnZoomWnd() +{ + // TODO: Add your command handler code here + ZoomWndFlag=TRUE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; +} + +void CbeladrawView::OnSelectwnd() +{ + // TODO: Add your command handler code here + SelectWndFlag=TRUE; + SelectCircFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,TRUE); +} + +void CbeladrawView::OnShowGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + + InvalidateRect(NULL); +} + +void CbeladrawView::OnSetGrid() +{ + // TODO: Add your command handler code here + GRIDDLG pDlg; + CbeladrawDoc *pDoc=GetDocument(); + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + InvalidateRect(NULL); + } +} + +void CbeladrawView::OnSnapGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CbeladrawView::OnShowMesh() +{ + // TODO: Add your command handler code here + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + } + else if(MeshUpToDate==TRUE){ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + } + InvalidateRect(NULL); +} + +void CbeladrawView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CbeladrawView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void CbeladrawView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Add your message handler code here and/or call default + // VK_TAB, VK_DELETE -- ones that we want to catch + CbeladrawDoc *pDoc=GetDocument(); + + if (((nChar=='z') || (nChar=='Z')) && (GetKeyState(VK_CONTROL))) OnUndo(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if (nChar==VK_TAB) + { + if ((EditAction==0) || (EditAction==2)) EnterPoint(); + if (EditAction==4) + { + CGroupNumber dlg; + dlg.m_groupnumber=0; + if(dlg.DoModal()==IDOK) + { + int i,j; + j=dlg.m_groupnumber; + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + } + + if (nChar==VK_DELETE) OnEditCut(); + + if (nChar==VK_SPACE) OnOpenSelected(); + + if (nChar==VK_ESCAPE){ + pDoc->UnselectAll(); + FirstPoint=-1; + ZoomWndFlag=0; + SelectWndFlag=0; + SelectCircFlag=0; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + DrawPSLG(); + } + + if (nChar==VK_F3) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if ((GetBoundingBox(x,y)!=FALSE) && (pDoc->SmartMesh)) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + for (i=0;iblocklist.GetSize();i++) + { + if (pDoc->blocklist[i].MaxArea>0) pDoc->blocklist[i].MaxArea/=4.; + else if (pDoc->SmartMesh) pDoc->blocklist[i].MaxArea=DefaultMeshSize/4.; + } + InvalidateRect(NULL); + } + + if (nChar==VK_F4) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if (GetBoundingBox(x,y)!=FALSE) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + + for (i=0;iblocklist.GetSize();i++) + { + pDoc->blocklist[i].MaxArea*=4.; + if ((pDoc->blocklist[i].MaxArea>DefaultMeshSize) && (DefaultMeshSize>0)) + pDoc->blocklist[i].MaxArea=DefaultMeshSize; + } + InvalidateRect(NULL); + } + + // Call to base class... + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CbeladrawView::EnterPoint() +{ + // TODO: Add your command handler code here + CEnterPt pDlg; + double x,y,t,d; + int i; + CbeladrawDoc* pDoc = GetDocument(); + BOOL flag; + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + pDoc->UpdateUndo(); + + if (pDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=pDoc->nodelist[0].CC(); + p1=p0; + for(i=1;inodelist.GetSize();i++) + { + p2=pDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(x,y,d); + } + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(x,y,d); + } + + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } +} + +void CbeladrawView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonDown(nFlags, point); + return; + } + + BOOL flag; + CbeladrawDoc* pDoc = GetDocument(); + + if (CreateRadiusFlag==TRUE) + { + int k; + double r; + + CreateRadiusFlag=FALSE; + if ((k=pDoc->ClosestNode(mx,my))<0) return; // catch case where no nodes have been drawn yet; + if (pDoc->CanCreateRadius(k)==FALSE) + { + MsgBox("The specified point is not suitable for\nconversion into a radius"); + return; + } + + CPromptBox dlg; + dlg.mytitle = "Enter desired radius dimension:"; + if (dlg.DoModal()==IDOK) + { + r=dlg.ParseDouble(); + if (r>0){ + if (pDoc->CreateRadius(k,r)) + { + InvalidateRect(NULL); + MeshUpToDate=FALSE; + } + else MsgBox("Could not make a radius of the prescribed dimension"); + } + } + + return; + } + + if (SelectWndFlag==1) + { + ZoomPix.RemoveAll(); + SelectWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectWndFlag==2) return; + + if (SelectCircFlag==1) + { + ZoomPix.RemoveAll(); + SelectCircFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectCircFlag==2) return; + + if (ZoomWndFlag==1) + { + ZoomPix.RemoveAll(); + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(mx,my,1./mag); + if (flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==1){ + if (FirstPoint<0){ + if(pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + pDoc->nodelist[FirstPoint].ToggleSelect(); + pDoc->UpdateUndo(); + flag=pDoc->AddSegment(FirstPoint,pDoc->ClosestNode(mx,my)); + FirstPoint=-1; + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(mx,my,1./mag); + if(flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==3){ + if (FirstPoint<0){ + if (pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + CArcSegment asegm; + CArcDlg dlg; + asegm.n0=FirstPoint; + asegm.n1=pDoc->ClosestNode(mx,my); + pDoc->nodelist[asegm.n1].ToggleSelect(); + DrawPSLG(); + + for(int k=0;klineproplist.GetSize();k++) + dlg.namelist.Add(pDoc->lineproplist[k].BdryName); + + dlg.cursel=0; + dlg.m_MaxSeg=MaxSeg; + dlg.m_ArcAngle=ArcAngle; + if (dlg.DoModal()==IDCANCEL){ + FirstPoint=-1; + pDoc->UnselectAll(); + DrawPSLG(); + return; + } + MaxSeg = asegm.MaxSideLength = dlg.m_MaxSeg; + ArcAngle = asegm.ArcLength=dlg.m_ArcAngle; + if (dlg.cursel==0) asegm.BoundaryMarker=""; + else asegm.BoundaryMarker=pDoc->lineproplist[dlg.cursel-1].BdryName; + + pDoc->UpdateUndo(); + flag=pDoc->AddArcSegment(asegm); + flag=FALSE; + FirstPoint=-1; + pDoc->UnselectAll(); + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + CView::OnLButtonDown(nFlags, point); +} + +void CbeladrawView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag==2){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + RECT r; + double z,m[2]; + if (mxGetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + int i,k; + double x,y,z; + CbeladrawDoc *pDoc=GetDocument(); + SelectWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + if (SelectCircFlag==2){ + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,FALSE); + + int i,k; + double R; + CComplex c,q; + CbeladrawDoc *pDoc=GetDocument(); + SelectCircFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + + R=abs((mx-wzx)+I*(my-wzy)); + c=wzx+I*wzy; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + CView::OnLButtonUp(nFlags, point); +} + +void CbeladrawView::OnRButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnRButtonDown(nFlags, point); + return; + } + + CbeladrawDoc* pDoc = GetDocument(); + int i,j; + + //toggle select of nearest point + if(EditAction==0){ + j=pDoc->ClosestNode(mx,my); + if(j>=0) pDoc->nodelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest segment + if(EditAction==1){ + j=pDoc->ClosestSegment(mx,my); + if(j>=0) pDoc->linelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest arc segment + if(EditAction==3){ + j=pDoc->ClosestArcSegment(mx,my); + if(j>=0) pDoc->arclist[j].ToggleSelect(); + DrawPSLG(); + } + //toggle select of nearest blocklabel + if(EditAction==2){ + j=pDoc->ClosestBlockLabel(mx,my); + if(j>=0) pDoc->blocklist[j].ToggleSelect(); + DrawPSLG(); + } + + if(EditAction==4){ + int clnode,clseg,claseg,cllbl; + double dnode,dseg,daseg,dlbl,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // find distance to closest block label; + cllbl=pDoc->ClosestBlockLabel(mx,my); + if(cllbl>=0) dlbl=pDoc->blocklist[cllbl].GetDistance(mx,my); + else dlbl=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InGroup; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InGroup; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InGroup; + } + if ((dlbl=0)){ + d=dlbl; + j=pDoc->blocklist[cllbl].InGroup; + } + + if (j<1) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CbeladrawView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CView::OnLButtonDblClk(nFlags, point); +} + +void CbeladrawView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + + CbeladrawDoc *pDoc=GetDocument(); + if (EditAction==0) + { + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + int j; + CString ss; + + sprintf(s,"Closest node: (%g,%g)\n",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + ss+=s; + + ss+="Nodal Property: "; + sprintf(s,"\n"); + for(j=0;jnodeproplist.GetSize();j++) + { + if(pDoc->nodeproplist[j].PointName== + pDoc->nodelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->nodelist[i].BoundaryMarker); + } + } + ss+=s; + + sprintf(s,"In Group: %i\n",pDoc->nodelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->nodelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->nodelist[i].InConductor); + } + } + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->nodelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==1) + { + int i=pDoc->ClosestSegment(mx,my); + int j; + CString ss; + + if(i>=0){ + char s[256]; + sprintf(s,"Length of closest segment: %g\n", + pDoc->LineLength(i)); + + ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->linelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->linelist[i].BoundaryMarker); + } + } + ss+=s; + + ss+="Grid spacing: "; + if (pDoc->linelist[i].MaxSideLength<=0) + sprintf(s,"\n"); + else sprintf(s,"%g\n",pDoc->linelist[i].MaxSideLength); + ss+=s; + sprintf(s,"In Group: %i\n",pDoc->linelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->linelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->linelist[i].InConductor); + } + } + ss+=s; + + if(pDoc->linelist[i].Hidden==TRUE) + ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->linelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==2) + { + int i=pDoc->ClosestBlockLabel(mx,my); + int j,k; + if(i>=0){ + char s[256]; + sprintf(s,"Closest block label: (%g,%g)\n",pDoc->blocklist[i].x, + pDoc->blocklist[i].y); + CString ss=s; + ss+="Block Material: "; + k=-1; + sprintf(s,"\n"); + if (pDoc->blocklist[i].BlockType=="") + { + sprintf(s,"\n"); + } + else for(j=0;jblockproplist.GetSize();j++) + { + if(pDoc->blockproplist[j].BlockName== + pDoc->blocklist[i].BlockType) + { + sprintf(s,"%s\n", (const char *) pDoc->blocklist[i].BlockType); + k=j; + } + } + ss+=s; + + ss+="Mesh size: "; + if (pDoc->blocklist[i].MaxArea==0) + sprintf(s,"\n"); + else sprintf(s,"%g\n", + floor(2.e07*sqrt(pDoc->blocklist[i].MaxArea/PI) + +0.5)/1.e07 ); + ss+=s; + + sprintf(s,"In Group: %i",pDoc->blocklist[i].InGroup); + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==3) + { + int i=pDoc->ClosestArcSegment(mx,my); + if(i>=0){ + char s[256]; + CString ss; + int j; + double R; + CComplex c; + + sprintf(s,"Angle spanned by closest arc: %g deg\n", + pDoc->arclist[i].ArcLength); ss+=s; + pDoc->GetCircle(pDoc->arclist[i],c,R); + c=Chop(c); + sprintf(s,"Radius of associated circle: %g\n",R); ss+=s; + sprintf(s,"Center of associated circle: (%g,%g)\n",Re(c),Im(c)); ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->arclist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->arclist[i].BoundaryMarker); + } + } + ss+=s; + sprintf(s,"Grid spacing: %g deg\n",pDoc->arclist[i].MaxSideLength); ss+=s; + sprintf(s,"In Group: %i\n",pDoc->arclist[i].InGroup); ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->arclist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->arclist[i].InConductor); + } + } + ss+=s; + + if(pDoc->arclist[i].Hidden==TRUE) ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->arclist[i].ToggleSelect(); + DrawPSLG(); + } + } + CView::OnRButtonDblClk(nFlags, point); +} + +void CbeladrawView::OnMakeMesh() +{ + CbeladrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved."); + return; + } + + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + BOOL LoadMesh=TheDoc->LoadMesh(); + if (bLinehook==FALSE) EndWaitCursor(); + + if(LoadMesh==TRUE){ + MeshUpToDate=TRUE; + if(MeshFlag==FALSE) OnShowMesh(); + else InvalidateRect(NULL); + CString s; + s.Format("Created mesh with %i nodes",TheDoc->meshnode.GetSize()); + if (TheDoc->greymeshline.GetSize()!=0) + s+="\nGrey mesh lines denote regions\nthat have no block label."; + if(bLinehook==FALSE) AfxMessageBox(s,MB_ICONINFORMATION); + else lua_pushnumber(lua,(int) TheDoc->meshnode.GetSize()); + } + +} + +void CbeladrawView::OnMenuAnalyze() +{ + + int i,j,k; + CbeladrawDoc *TheDoc = GetDocument(); + BOOL bFlag=FALSE; + BOOL bExteriorDefined=TRUE; + + ASSERT_VALID(TheDoc); + + // check to see if all blocklabels are kosher... + if (TheDoc->blocklist.GetSize()==0){ + MsgBox("No block information has been defined\nCannot analyze the problem"); + return; + } + + for(i=0,bFlag=FALSE;iblocklist.GetSize();i++) + { + for(k=0,j=0;kblockproplist.GetSize();k++) + if (TheDoc->blocklist[i].BlockType!=TheDoc->blockproplist[k].BlockName) j++; + if((j==TheDoc->blockproplist.GetSize()) && (TheDoc->blocklist[i].BlockType!="")) + { + if(bFlag==FALSE) OnBlockOp(); + bFlag=TRUE; + TheDoc->blocklist[i].IsSelected=TRUE; + } + } + + if(bFlag==TRUE){ + InvalidateRect(NULL); + CString ermsg="Material properties have not\n"; + ermsg+= "been defined for all block labels\n"; + ermsg+= "cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + + + + // check to see if all of the input points are on r>=0 for axisymmetric problems. + if(TheDoc->ProblemType==1) + { + for(k=0;knodelist.GetSize();k++) + if(TheDoc->nodelist[k].x<-(1.e-6)) + { + InvalidateRect(NULL); + CString ermsg="The problem domain must lie in\n"; + ermsg+= "r>=0 for axisymmetric problems.\n"; + ermsg+= "Cannot analyze the problem."; + MsgBox(ermsg); + return; + } + + + // check to see if all block defined to be in an axisymmetric external region are isotropic + for(k=0;kblocklist.GetSize();k++) + { + if(TheDoc->blocklist[k].IsExternal){ + if ((TheDoc->extRi==0) || (TheDoc->extRo==0)) bExteriorDefined=FALSE; + for(i=0;iblockproplist.GetSize();i++) + if(TheDoc->blocklist[k].BlockType==TheDoc->blockproplist[i].BlockName) + { + if(TheDoc->blockproplist[i].ex!=TheDoc->blockproplist[i].ey) bFlag=TRUE; + } + } + } + if(bFlag) + { + InvalidateRect(NULL); + CString ermsg="Only istropic materials are allowed\n"; + ermsg+= "in axisymmetric external regions.\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + if(!bExteriorDefined) + { + InvalidateRect(NULL); + CString ermsg="Some block labels have been specific as placed in\n"; + ermsg+= "an axisymmetric exterior region, but no properties\n"; + ermsg+= "have been adequately defined for the exterior region\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + } + + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved."); + return; + } + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + if (bLinehook==FALSE) EndWaitCursor(); + + char CommandLine[512]; + CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; + + if(bLinehook==FALSE) + sprintf(CommandLine,"\"%sbelasolv.exe\" %s", (const char *) BinDir, (const char *) rootname); + else + sprintf(CommandLine,"\"%sbelasolv.exe\" %s bLinehook", (const char *) BinDir, (const char *) rootname); + + CString MyPath=pn.Left(pn.ReverseFind('\\')); + + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + StartupInfo2.dwFlags = STARTF_FORCEOFFFEEDBACK; + if(bLinehook==HiddenLua){ + StartupInfo2.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK; + // SHOWNOACTIVATE doesn't steal focus to others + StartupInfo2.wShowWindow = SW_SHOWMINNOACTIVE; + } + if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, + 0, NULL, MyPath, &StartupInfo2, &ProcessInfo2)) + { + if(bLinehook!=FALSE) + { + DWORD ExitCode; + hProc=ProcessInfo2.hProcess; + do{ + GetExitCodeProcess(ProcessInfo2.hProcess,&ExitCode); + ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); + Sleep(1); + } while(ExitCode==STILL_ACTIVE); + hProc=NULL; + + if (ExitCode==1) + MsgBox("Material properties have not been defined for all regions"); + if (ExitCode==2) + MsgBox("problem loading mesh"); + if (ExitCode==3) + MsgBox("problem renumbering node points"); + if (ExitCode==4) + MsgBox("couldn't allocate enough space for matrices"); + if (ExitCode==5) + MsgBox("Couldn't solve the problem"); + if (ExitCode==6) + MsgBox("couldn't write results to disk"); + if (ExitCode==7) + MsgBox("problem loading input file"); + } + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } + else + { + MsgBox("Problem executing the solver"); + return; + } + +} + +void CbeladrawView::OnMenuViewres() +{ + // TODO: Add your command handler code here + CbeladrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("No results to display"); + return; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".res\""; + ((CFemmApp *) AfxGetApp())->EOCheckIfAlreadyOpen(rootname); + AfxGetApp( )->OpenDocumentFile(rootname); + +} + +void CbeladrawView::OnUndo() +{ + CbeladrawDoc *TheDoc = GetDocument(); + TheDoc->Undo(); + TheDoc->UnselectAll(); + InvalidateRect(NULL); +} + +void CbeladrawView::OnKbdZoom() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]UpdateUndo(); + pDoc->RotateMove(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateMove(dlg.m_deltax,dlg.m_deltay,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CbeladrawView::OnCopyObjects() +{ + // TODO: Add your command handler code here + CCopyDlg dlg; + CbeladrawDoc *pDoc=GetDocument(); + + dlg.m_aboutx=0; + dlg.m_abouty=0; + dlg.m_shiftangle=0; + dlg.m_deltax=0; + dlg.m_deltay=0; + dlg.IsMove=FALSE; + dlg.m_ncopies=1; + + if(dlg.DoModal()==IDOK) + { + if(dlg.BtnState==0) // Rotate + { + pDoc->UpdateUndo(); + pDoc->RotateCopy(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateCopy(dlg.m_deltax,dlg.m_deltay,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CbeladrawView::OnDxfin() +{ + // TODO: Add your command handler code here + CString dxffile; + CFileDialog *fname_dia; + CbeladrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + TRUE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if(pDoc->ReadDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't read specified DXF file\nMake sure the the specified file\nis in ASCII DXF r12 format"); + pDoc->NoDraw=FALSE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } +} + +void CbeladrawView::OnPurgemesh() +{ + // TODO: Add your command handler code here + CbeladrawDoc *pDoc=GetDocument(); + pDoc->meshnode.RemoveAll(); + pDoc->meshnode.FreeExtra(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + pDoc->meshline.FreeExtra(); + pDoc->greymeshline.FreeExtra(); + MeshUpToDate=FALSE; + if (MeshFlag==TRUE){ + MeshFlag=FALSE; + InvalidateRect(NULL); + } + +} + +void CbeladrawView::OnDxfwrite() +{ + CString dxffile; + CFileDialog *fname_dia; + CbeladrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + FALSE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if (bLinehook==FALSE) BeginWaitCursor(); + if(pDoc->WriteDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + pDoc->FirstDraw=TRUE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't write specified DXF file"); + if (bLinehook==FALSE) EndWaitCursor(); + } +} + + +BOOL CbeladrawView::OnEraseBkgnd(CDC* pDC) +{ + + // idea is to always make the background white. + // source code copied from: + // Frequently Asked Questions About Foundation Classes + + // Set brush to desired background color + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + return TRUE; + +} + +void CbeladrawView::OnPanDown() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox=ox-0.25*x/mag; + oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CbeladrawView::OnPanLeft() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CbeladrawView::OnPanRight() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CbeladrawView::OnPanUp() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox+=0.25*x/mag; + oy+=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CbeladrawView::OnMenuMatlib() +{ + bd_CLibDlg dlg; + + dlg.pDoc=GetDocument(); + dlg.BinDir=BinDir; + + dlg.DoModal(); +} + +void CbeladrawView::OnOpenSelected() +{ + CbeladrawDoc *pDoc=GetDocument(); + + if(EditAction==1) pDoc->OpSegDlg(); + if(EditAction==2){ + if (pDoc->OpBlkDlg()==TRUE) + InvalidateRect(NULL); + } + if(EditAction==3){ + pDoc->OpArcSegDlg(); + InvalidateRect(NULL); + } + if(EditAction==0) pDoc->OpNodeDlg(); + + if(EditAction==4) pDoc->OpGrpDlg(); + + pDoc->UnselectAll(); + DrawPSLG(); +} + +void CbeladrawView::OnEditScale() +{ + // TODO: Add your command handler code here + CScaleDlg dlg; + CbeladrawDoc *pDoc=GetDocument(); + double x[2],y[2],R,dt; + int i,j,k; + CComplex p,s,c; + BOOL bFlag=FALSE; + + // look at points, block labels, and arcs to get bounding box. + for(i=0;inodelist.GetSize();i++) + if(pDoc->nodelist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[i].x; x[1]=x[0]; + y[0]=pDoc->nodelist[i].y; y[1]=y[0]; + } + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + if(pDoc->blocklist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->blocklist[i].x; x[1]=x[0]; + y[0]=pDoc->blocklist[i].y; y[1]=y[0]; + } + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;ilinelist.GetSize();i++) + if(pDoc->linelist[i].IsSelected==TRUE){ + for(j=0;j<2;j++){ + if(j==0) k=pDoc->linelist[i].n0; + else k=pDoc->linelist[i].n1; + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[k].x; x[1]=x[0]; + y[0]=pDoc->nodelist[k].y; y[1]=y[0]; + } + if(pDoc->nodelist[k].xnodelist[k].x; + if(pDoc->nodelist[k].x>x[1]) x[1]=pDoc->nodelist[k].x; + if(pDoc->nodelist[k].ynodelist[k].y; + if(pDoc->nodelist[k].y>y[1]) y[1]=pDoc->nodelist[k].y; + } + } + + + for(i=0;iarclist.GetSize();i++) + if(pDoc->arclist[i].IsSelected==TRUE){ + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + if(bFlag==FALSE) return; + + dlg.m_scalefactor=1.; + dlg.m_basex=(x[1]+x[0])/2.; + dlg.m_basey=(y[1]+y[0])/2.; + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->ScaleMove(dlg.m_basex,dlg.m_basey,dlg.m_scalefactor,EditAction); + InvalidateRect(NULL); + } +} + +void CbeladrawView::OnEditMirror() +{ + // TODO: Add your command handler code here + CMirrorDlg dlg; + CbeladrawDoc *pDoc=GetDocument(); + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->MirrorSelected(dlg.m_pax,dlg.m_pay, + dlg.m_pbx,dlg.m_pby,EditAction); + InvalidateRect(NULL); + } +} + +void CbeladrawView::OnEditCut() +{ + CbeladrawDoc *pDoc=GetDocument(); + BOOL flag; + + pDoc->UpdateUndo(); + if(EditAction==0) flag=pDoc->DeleteSelectedNodes(); + if(EditAction==1) flag=pDoc->DeleteSelectedSegments(); + if(EditAction==2) flag=pDoc->DeleteSelectedBlockLabels(); + if(EditAction==3) flag=pDoc->DeleteSelectedArcSegments(); + if(EditAction==4){ + flag=FALSE; + if (pDoc->DeleteSelectedSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedArcSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedNodes()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedBlockLabels()==TRUE) flag=TRUE; + } + if (flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else InvalidateRect(NULL); + } + +} + + +BOOL CbeladrawView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"beladraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_mag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_shownames); + q[0]=NULL; + } + } + fclose(fp); + return TRUE; + } + + return FALSE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + + +BOOL CbeladrawView::WritePreferences() +{ + FILE *fp; + CString fname; + CbeladrawDoc *pDoc=GetDocument(); + + fname=BinDir+"beladraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",d_action); + fprintf(fp," = %g\n",d_mag); + fprintf(fp," = %g\n",d_gridsize); + fprintf(fp," = %i\n",d_showgrid); + fprintf(fp," = %i\n",d_snapgrid); + fprintf(fp," = %i\n",d_shownames); + fprintf(fp," = %i\n",d_showorigin); + fprintf(fp," = %i\n",pDoc->d_type); + fprintf(fp," = %i\n",pDoc->d_length); + fprintf(fp," = %g\n",pDoc->d_prec); + fprintf(fp," = %g\n",pDoc->d_minangle); + fprintf(fp," = %g\n",pDoc->d_depth); + fprintf(fp," = %i\n",pDoc->d_coord); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void CbeladrawView::OnViewShownames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + InvalidateRect(NULL); +} + +void CbeladrawView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CbeladrawView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +void CbeladrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if (bActivate && pActivateView==this) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(3); + + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + CheckIt(); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CbeladrawView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CbeladrawView::OnViewShowOrphans() +{ + CbeladrawDoc *pDoc=GetDocument(); + + OnGroupOp(); + pDoc->SelectOrphans(); + InvalidateRect(NULL); +} + +void CbeladrawView::OnUpdateEditExterior(CCmdUI* pCmdUI) +{ + if(GetDocument()->ProblemType) pCmdUI->Enable ( TRUE); + else pCmdUI->Enable ( FALSE ); +} + +void CbeladrawView::OnCreateRadius() +{ + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=TRUE; + + StatBar->SetPaneText(0,"SELECT POINT AT WHICH A RADIUS IS DESIRED",TRUE); +} + +void CbeladrawView::OnMakeABC() +{ + CMakeABCDlg dlg; + CbeladrawDoc *pDoc=GetDocument(); + + double xx[2],yy[2]; + if (GetBoundingBox(xx,yy)==0) return; + + if(pDoc->ProblemType == 0) // 2D planar case + { + dlg.abcr=0.75*abs((xx[0]+I*yy[0])-(xx[1]+I*yy[1])); + dlg.abcx=(xx[0]+xx[1])/2.0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.n=1; + } + else{ //Axi case + dlg.abcx=0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.abcr=1.5*abs(xx[1]+I*(yy[1]-yy[0])/2.0); + dlg.n=0; + } + + dlg.abcn=7; // suggested default number of layers + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + CString LuaCmd; + LuaCmd.Format("ei_makeABC(%i,%g,%g,%g,%i)",dlg.abcn,dlg.abcr,dlg.abcx,dlg.abcy,dlg.n); + lua_dostring(lua,LuaCmd); + } +} diff --git a/femm/beladrawView.h b/femm/beladrawView.h new file mode 100644 index 0000000..de76ba8 --- /dev/null +++ b/femm/beladrawView.h @@ -0,0 +1,167 @@ +// beladrawView.h : interface of the CbeladrawView class +// +///////////////////////////////////////////////////////////////////////////// + +class CbeladrawView : public CView +{ +protected: // create from serialization only + CbeladrawView(); + DECLARE_DYNCREATE(CbeladrawView) + +// Attributes +public: + CbeladrawDoc* GetDocument(); + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void DrawPSLG(); + void EnterPoint(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void OnNewDocument(); + void CheckIt(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL ShowNames; + BOOL MeshUpToDate; + int FirstPoint; + int ZoomWndFlag; + int SelectWndFlag; + int SelectCircFlag; + int CreateRadiusFlag; + double wzx,wzy; + double MaxSeg,ArcAngle; + + + // Colors used to render the view + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF NodeColor; + COLORREF NameColor; + + // default view properties + int d_action; //=0; + double d_mag; //=100.; + double d_gridsize; //=0.25; + BOOL d_showgrid; //=TRUE; + BOOL d_snapgrid; //=FALSE; + BOOL d_shownames; //=FALSE; + BOOL d_showorigin; + + CString BinDir; // pathname for other FEMM executables + CArray ZoomPix; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CbeladrawView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual void OnInitialUpdate(); // called first time after construct + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + void lua_zoomin(); + void lua_zoomout(); + void lua_zoomnatural(); + void lnu_show_mesh(); + void lnu_purge_mesh(); + void lnuMakeMesh(); + void lnu_analyze(int bShow); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL GetBoundingBox(double *x, double *y); + + virtual ~CbeladrawView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CbeladrawView) + afx_msg void OnNodeOp(); + afx_msg void OnSegmentOp(); + afx_msg void OnBlockOp(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnZoomIn(); + afx_msg void OnZoomOut(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnEditCopy(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomWnd(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMakeMesh(); + afx_msg void OnMenuAnalyze(); + afx_msg void OnMenuViewres(); + afx_msg void OnArcsegOp(); + afx_msg void OnUndo(); + afx_msg void OnKbdZoom(); + afx_msg void OnMoveObjects(); + afx_msg void OnCopyObjects(); + afx_msg void OnDxfin(); + afx_msg void OnPurgemesh(); + afx_msg void OnDxfwrite(); + afx_msg void OnSelectwnd(); + afx_msg void OnBDSelectCirc(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnMenuMatlib(); + afx_msg void OnGroupOp(); + afx_msg void OnOpenSelected(); + afx_msg void OnEditScale(); + afx_msg void OnEditMirror(); + afx_msg void OnEditCut(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnViewShownames(); + afx_msg void OnViewShowOrphans(); + afx_msg void OnCreateRadius(); + afx_msg void OnUpdateEditExterior(CCmdUI* pCmdUI); + afx_msg void OnMakeABC(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +#ifndef _DEBUG // debug version in beladrawView.cpp +inline CbeladrawDoc* CbeladrawView::GetDocument() + { return (CbeladrawDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/femm/belaviewDoc.cpp b/femm/belaviewDoc.cpp new file mode 100644 index 0000000..b2f0357 --- /dev/null +++ b/femm/belaviewDoc.cpp @@ -0,0 +1,2096 @@ +// belaviewDoc.cpp : implementation of the CbelaviewDoc class +// + + +#include "stdafx.h" +#include +#include +#include "bv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "belaviewDoc.h" +#include "belaviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#define AXISYMMETRIC 1 + +extern lua_State * lua; +extern void *pBelaviewDoc; +extern BOOL bLinehook; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewDoc + +IMPLEMENT_DYNCREATE(CbelaviewDoc, CDocument) + +BEGIN_MESSAGE_MAP(CbelaviewDoc, CDocument) + //{{AFX_MSG_MAP(CbelaviewDoc) + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewDoc construction/destruction + +double sqr(double x); + +CbelaviewDoc::CbelaviewDoc() +{ + // set some default values for problem definition + d_LineIntegralPoints=400; + Depth=1/0.0254; + LengthUnits=0; + ProblemType=FALSE; + ProblemNote="Add comments here."; + FirstDraw=-1; + A_High=0.; + A_Low=0.; + A_lb=0.; + A_ub=0.; + extRo=extRi=extZo=0; + Smooth=TRUE; + NumList=NULL; + ConList=NULL; + bHasMask=FALSE; + LengthConv=(double *)calloc(6,sizeof(double)); + LengthConv[0]=0.0254; //inches + LengthConv[1]=0.001; //millimeters + LengthConv[2]=0.01; //centimeters + LengthConv[3]=1.; //meters + LengthConv[4]=2.54e-05; //mils + LengthConv[5]=1.e-06; //micrometers + Coords=FALSE; + + for(int i=0;i<4;i++) + d_PlotBounds[i][0]=d_PlotBounds[i][1]= + PlotBounds[i][0]=PlotBounds[i][1]=0; + + // determine path to bin directory + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // lua initialization stuff + initalise_lua(); +} + +CbelaviewDoc::~CbelaviewDoc() +{ + int i; + free(LengthConv); + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + ProblemNote=v; + 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.V=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.V); + 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.V = BProp.qs = 0; + BProp.c0 = BProp.c1 = 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,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.V); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.qs); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c0); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&BProp.c1); + 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.ex=1.; + MProp.ey=1.; + MProp.qv=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.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.qv); + q[0]=NULL; + } + + + if( _strnicmp(q,"",9)==0){ + blockproplist.Add(MProp); + q[0]=NULL; + } + + // Circuit Properties + if( _strnicmp(q,"",16)==0){ + CProp.CircName="New Circuit"; + CProp.V=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.V); + 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)asegm.MaxSideLength=b; + asegm.InConductor--; + arclist.Add(asegm); + } + q[0]=NULL; + } + + + // read in list of holes; + if(_strnicmp(q,"[numholes]",13)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) + { + blk.BlockType=-1; + blk.MaxArea=0; + for(i=0;imeshelem[i].rsqr) meshelem[i].rsqr=b; + } + } + + // Find flux density in each element; + for(i=0;iA_High) A_High=meshnode[i].V; + if (meshnode[i].Varg(u1)) + { + swa=ConList[i][k]; + ConList[i][k]=ConList[i][k+1]; + ConList[i][k+1]=swa; + flg=TRUE; + } + } + if(!flg) j=NumList[i]; + } + } + + + // Find extreme values of potential + d_PlotBounds[0][0]=A_Low; + d_PlotBounds[0][1]=A_High; + PlotBounds[0][0]=d_PlotBounds[0][0]; + PlotBounds[0][1]=d_PlotBounds[0][1]; + + for(i=0;i1)) + { + for(k=1;k<10;k++) + { + if (myBlockName[1]==('0'+k)){ + isExt[i]=TRUE; + break; + } + } + } + } + i=0; while(isExt[i]) i++; + d_PlotBounds[1][0]=abs(D(i)); + d_PlotBounds[1][1]=d_PlotBounds[1][0]; + d_PlotBounds[2][0]=abs(E(0)); + d_PlotBounds[2][1]=d_PlotBounds[2][0]; + for(i=0;id_PlotBounds[1][1]) d_PlotBounds[1][1]=b; + if(bd_PlotBounds[2][1]) d_PlotBounds[2][1]=b; + if(b=0) + { + if(meshelem[i].lbl!=k) + { + blocklist[meshelem[i].lbl].IsSelected=TRUE; + if (!bMultiplyDefinedLabels) + { + CString msg; + msg ="Some regions in the problem have been defined\n"; + msg+="by more than one block label. These potentially\n"; + msg+="problematic regions will appear as selected in\n"; + msg+="the initial view."; + MsgBox(msg); + bMultiplyDefinedLabels=TRUE; + } + } + } + } + + + FirstDraw=TRUE; + + return TRUE; +} + +int CbelaviewDoc::InTriangle(double x, double y) +{ + static int k; + int j,hi,lo,sz; + double z; + + sz=(int) meshelem.GetSize(); + if((k<0) || (k>=sz)) k=0; + + // In most applications, the triangle we're looking + // for is nearby the last one we found. Since the elements + // are ordered in a banded structure, we want to check the + // elements nearby the last one selected first. + if (InTriangleTest(x,y,k)) return k; + + hi=k;lo=k; + + for(j=0;j=sz) hi=0; + lo--; if(lo<0) lo=sz-1; + + z=(meshelem[hi].ctr.re-x)*(meshelem[hi].ctr.re-x) + + (meshelem[hi].ctr.im-y)*(meshelem[hi].ctr.im-y); + if(z<=meshelem[hi].rsqr) + { + if(InTriangleTest(x,y,hi)) + { + k=hi; + return k; + } + } + + z=(meshelem[lo].ctr.re-x)*(meshelem[lo].ctr.re-x) + + (meshelem[lo].ctr.im-y)*(meshelem[lo].ctr.im-y); + if(z<=meshelem[lo].rsqr) + { + if(InTriangleTest(x,y,lo)) + { + k=lo; + return k; + } + } + + } + + return (-1); +} + +BOOL CbelaviewDoc::GetPointValues(double x, double y, CPointVals &u) +{ + int k; + k=InTriangle(x,y); + if (k<0) return FALSE; + GetPointValues(x,y,k,u); + return TRUE; +} + +BOOL CbelaviewDoc::GetPointValues(double x, double y, int k, CPointVals &u) +{ + int i,n[3]; + double a[3],b[3],c[3],da,ravg; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + ravg=LengthConv[LengthUnits]* + (meshnode[n[0]].x + meshnode[n[1]].x + meshnode[n[2]].x)/3.; + + GetPointD(x,y,u.D,meshelem[k]); + u.e=blockproplist[meshelem[k].blk].ex+I*blockproplist[meshelem[k].blk].ey; + u.e/=AECF(k,x+I*y); + + u.V=0; + for(i=0;i<3;i++) u.V+=meshnode[n[i]].V*(a[i]+b[i]*x+c[i]*y)/(da); + u.E.re = u.D.re/(u.e.re*eo); + u.E.im = u.D.im/(u.e.im*eo); + + u.nrg=Re(u.D*conj(u.E))/2.; + + return TRUE; +} + +void CbelaviewDoc::GetPointD(double x, double y, CComplex &D, CElement &elm) +{ + // elm is a reference to the element that contains the point of interest. + int i,n[3]; + double da,a[3],b[3],c[3]; + + if(Smooth==FALSE){ + D=elm.D; + return; + } + + for(i=0;i<3;i++) n[i]=elm.p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,D=0;i<3;i++) D+=(elm.d[i]*(a[i]+b[i]*x+c[i]*y)/da); +} + +BOOL CbelaviewDoc::IsSameMaterial(int e1, int e2) +{ + int b1,b2; + + b1=meshelem[e1].blk; + b2=meshelem[e2].blk; + + if ((blockproplist[b1].ex==blockproplist[b2].ex) && + (blockproplist[b1].ey==blockproplist[b2].ey)) return TRUE; + + return FALSE; +} + +void CbelaviewDoc::GetNodalD(CComplex *d, int N) +{ + int i,j,k,n,m,p,eos,nos,qn; + int lf,rt; + double xi,yi,ii,xx,xy,yy,iv,xv,yv,dx,dy,dv,Ex,Ey,det; + static int q[21]; + BOOL flag; + + for(i=0;i<3;i++) + { + j=meshelem[N].p[i]; + lf=rt=-1; + flag=FALSE; + for(eos=0;eos2) nos=0; + p=meshelem[n].p[nos]; + + // add this node to the list. We can have a max of 20 nodes, + // which should never actually occur (usually about 6 to 8) + if (qn<20) q[qn++]=p; + + // if this node has a fixed definition, get out of the loop; + if((meshnode[j].Q!=-2) &&(meshnode[p].Q!=-2)){ + lf=p; + break; + } + + m--; if(m<0) m=NumList[j]-1; + } + + // catch some annoying special cases; + if ((lf==rt) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is at the end of a conductor; not much to + // do but punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + else if ((rt!=-1) && (meshnode[j].Q!=-2) && (lf==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + d[i]=meshelem[N].D; + flag=TRUE; + } + else if ((lf!=-1) && (meshnode[j].Q!=-2) && (rt==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + d[i]=meshelem[N].D; + flag=TRUE; + } + else if((lf==-1) && (rt==-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is an isolated charge. Again, not much to + // do but punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + else if((lf!=-1) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + + // The node of interest is on some boundary where the charge is fixed. + // if the angle is shallow enough, we can just do the regular thing; + // Otherwise, we punt. + CComplex x,y; + x=meshnode[lf].CC()-meshnode[j].CC(); x/=abs(x); + y=meshnode[j].CC()-meshnode[rt].CC(); y/=abs(y); + if(fabs(arg(x/y))>10.0001*PI/180.) + { + // if the angle is greater than 10 degrees, punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + } + + if(flag==FALSE) + { + // The nominal case. + // Fit a plane through the nodes in the list to solve for E. + // Then, multiply by permittivity to get D. + xi=yi=ii=xx=xy=yy=iv=xv=yv=0; + + q[qn++]=j; + + for(k=0;k0) + { + OnNewDocument(); + SetPathName(pname,FALSE); + OnOpenDocument(pname); + } +} + +int CbelaviewDoc::ClosestNode(double x, double y) +{ + int i,j; + double d0,d1; + + if(nodelist.GetSize()==0) return -1; + + j=0; + d0=nodelist[0].GetDistance(x,y); + for(i=0;iq[k]) && (k<(contour.GetSize()-1))) k++; + u=(z-q[k-1])/(q[k]-q[k-1]); + pt=contour[k-1]+u*(contour[k]-contour[k-1]); + t=contour[k]-contour[k-1]; + t/=abs(t); + n = I*t; + pt+=(n*1.e-06); + + if (elm<0) elm=InTriangle(pt.re,pt.im); + else if (InTriangleTest(pt.re,pt.im,elm)==FALSE) + { + flag=FALSE; + for(j=0;j<3;j++) + for(m=0;m=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + p.M[i][0]=z; + if(flag!=FALSE) + { + switch (PlotType) + { + case 0: + p.M[i][1]=v.V; + break; + case 1: + p.M[i][1]=abs(v.D); + break; + case 2: + p.M[i][1]=Re(v.D/n); + break; + case 3: + p.M[i][1]=Re(v.D/t); + break; + case 4: + p.M[i][1]=abs(v.E); + break; + case 5: + p.M[i][1]=Re(v.E/n); + break; + case 6: + p.M[i][1]=Re(v.E/t); + break; + default: + p.M[i][1]=0; + break; + } + } + } + + free(q); +} + +BOOL CbelaviewDoc::InTriangleTest(double x, double y, int i) +{ + if ((i<0) || (i>=meshelem.GetSize())) return FALSE; + + int j,k; + double z; + + for(j=0;j<3;j++) + { + k=j+1; if(k==3) k=0; + // Case 1: p[k]>p[j] + if (meshelem[i].p[k] > meshelem[i].p[j]) + { + z=(meshnode[meshelem[i].p[k]].x-meshnode[meshelem[i].p[j]].x)* + (y-meshnode[meshelem[i].p[j]].y) - + (meshnode[meshelem[i].p[k]].y-meshnode[meshelem[i].p[j]].y)* + (x-meshnode[meshelem[i].p[j]].x); + if(z<0) return FALSE; + } + //Case 2: p[k]0) return FALSE; + } + } + + return TRUE; +} + +CPointVals::CPointVals() +{ + V=0; // vector potential + D=0; // flux density + e=0; // permittivity + E=0; // field intensity + nrg=0; // energy stored in the field +} + +CComplex CbelaviewDoc::Ctr(int i) +{ + CComplex p,c; + int j; + + for(j=0,c=0;j<3;j++){ + p.Set(meshnode[meshelem[i].p[j]].x/3.,meshnode[meshelem[i].p[j]].y/3.); + c+=p; + } + + return c; +} + +double CbelaviewDoc::ElmArea(int i) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=meshelem[i].p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +double CbelaviewDoc::ElmArea(CElement *elm) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=elm->p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +CComplex CbelaviewDoc::HenrotteVector(int k) +{ + int i,n[3]; + double b[3],c[3],da; + CComplex v; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,v=0;i<3;i++) + v-=meshnode[n[i]].msk*(b[i]+I*c[i])/(da*LengthConv[LengthUnits]); // grad + + return v; +} + +CComplex CbelaviewDoc::BlockIntegral(int inttype) +{ + int i,k; + double B1,B2,F1,F2,y; + CComplex c,z; + CComplex A[3],Jn[3],U[3],V[3]; + double a,R; + double r[3]; + + for(i=0,z=0;i4) + { + a=ElmArea(i)*pow(LengthConv[LengthUnits],2.); + if(ProblemType==1){ + for(k=0;k<3;k++) + r[k]=meshnode[meshelem[i].p[k]].x*LengthConv[LengthUnits]; + R=(r[0]+r[1]+r[2])/3.; + a*=(2.*PI*R); + } + else a*=Depth; + + switch(inttype){ + + case 5: + B1=Re(D(i)); + B2=Im(D(i)); + c=HenrotteVector(i); + + // x (or r) direction Henrotte force, SS part. + if(ProblemType==0){ + y=(((B1*B1) - (B2*B2))*Re(c) + 2.*(B1*B2)*Im(c))/(2.*eo)*AECF(i); + z.re += (a*y); + } + + // y (or z) direction Henrotte force, SS part + y=(((B2*B2) - (B1*B1))*Im(c) + 2.*(B1*B2)*Re(c))/(2.*eo)*AECF(i); + z.im += (a*y); + + break; + + case 6: // Henrotte torque, SS part. + if(ProblemType!=0) break; + B1=Re(D(i)); + B2=Im(D(i)); + c=HenrotteVector(i); + + F1 = (((B1*B1) - (B2*B2))*Re(c) + + 2.*(B1*B2)*Im(c))/(2.*eo); + F2 = (((B2*B2) - (B1*B1))*Im(c) + + 2.*(B1*B2)*Re(c))/(2.*eo); + + for(c=0,k=0;k<3;k++) + c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3.; + + y=Re(c)*F2 -Im(c)*F1; + y*=AECF(i); + z+=(a*y); + + break; + + default: + break; + } + } + } + + // Integrals 3 and 4 are averages over the selected volume; + // Need to divide by the block volme to get the average. + if((inttype==3) || (inttype==4)) z/=BlockIntegral(2); + + return z; +} + +void CbelaviewDoc::LineIntegral(int inttype, double *z) +{ +// inttype Integral +// 0 E.t +// 1 D.n +// 2 Contour length +// 3 Stress Tensor Force +// 4 Stress Tensor Torque + + // inttype==0 => E.t + if(inttype==0){ + CPointVals u; + int k; + + k=(int) contour.GetSize(); + GetPointValues(contour[0].re,contour[0].im, u); + z[0] = u.V; + GetPointValues(contour[k-1].re,contour[k-1].im,u); + z[0]-= u.V; + } + + // inttype==1 => D.n + if(inttype==1){ + CComplex n,t,pt; + CPointVals v; + double dz,u,d,Dn; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + z[1]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + Dn = Re(v.D/n); + + if (ProblemType==AXISYMMETRIC) + d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); + else + d=Depth*LengthConv[LengthUnits]; + + z[0]+=(Dn*dz*d); + z[1]+=dz*d; + } + } + } + z[1]=z[0]/z[1]; // Average D.n over the surface; + } + + // inttype==2 => Contour Length + if(inttype==2){ + int i,k; + k=(int) contour.GetSize(); + for(i=0,z[0]=0;i Stress Tensor Force + if(inttype==3){ + CComplex n,t,pt; + double Hn,Bn,BH,dF1,dF2; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + for(i=0;i<4;i++) z[i]=0; + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE) + { + Hn= Re(v.E/n); + Bn= Re(v.D/n); + BH= Re(v.D*conj(v.E)); + dF1=v.E.re*Bn + v.D.re*Hn - n.re*BH; + dF2=v.E.im*Bn + v.D.im*Hn - n.im*BH; + + dza=dz*LengthConv[LengthUnits]; + if(ProblemType==1){ + dza*=2.*PI*pt.re*LengthConv[LengthUnits]; + dF1=0; + } + else dza*=Depth; + + z[0]+=(dF1*dza/2.); + z[1]+=(dF2*dza/2.); + } + } + + } + } + + // inttype==4 => Stress Tensor Torque + if(inttype==4){ + CComplex n,t,pt; + double Hn,Bn,BH,dF1,dF2,dT; + CPointVals v; + double dz,dza,u; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=z[1]=0; + + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE) + { + Hn= Re(v.E/n); + Bn= Re(v.D/n); + BH= Re(v.D*conj(v.E)); + dF1=v.E.re*Bn + v.D.re*Hn - n.re*BH; + dF2=v.E.im*Bn + v.D.im*Hn - n.im*BH; + dT= pt.re*dF2 - dF1*pt.im; + dza=dz*LengthConv[LengthUnits]*LengthConv[LengthUnits]; + + z[0]+=(dT*dza*Depth/2.); + } + } + } + + } + + return; +} + + +int CbelaviewDoc::ClosestArcSegment(double x, double y) +{ + double d0,d1; + int i,j; + + if(arclist.GetSize()==0) return -1; + + j=0; + d0=ShortestDistanceFromArc(CComplex(x,y),arclist[0]); + 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])); +} + +BOOL CbelaviewDoc::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"belaview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LineIntegralPoints); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void CbelaviewDoc::BendContour(double angle, double anglestep) +{ + if (angle==0) return; + if (anglestep==0) anglestep=1; + + int k,n; + double d,tta,dtta,R; + CComplex c,a0,a1; + + // check to see if there are at least enough + // points to have made one line; + k=(int) contour.GetSize()-1; + if (k<1) return; + + // restrict the angle of the contour to 180 degrees; + if ((angle<-180.) || (angle>180.)) return; + n=(int) ceil(fabs(angle/anglestep)); + tta=angle*PI/180.; + dtta=tta/((double) n); + + // pop last point off of the contour; + a1=contour[k]; + contour.RemoveAt(k); + a0=contour[k-1]; + + // compute location of arc center; + // and radius of the circle that the + // arc lives on. + d=abs(a1-a0); + R=d/(2.*sin(fabs(tta/2.))); + if(tta>0) c=a0 + (R/d)*(a1-a0)*exp(I*(PI-tta)/2.); + else c=a0+(R/d)*(a1-a0)*exp(-I*(PI+tta)/2.); + + // add the points on the contour + for(k=1;k<=n;k++) contour.Add(c+(a0-c)*exp(k*I*dtta)); +} + +CComplex CbelaviewDoc::E(int k) +{ + // return average electric field intensity for the kth element + return (meshelem[k].D.re/blockproplist[meshelem[k].blk].ex + + I*meshelem[k].D.im/blockproplist[meshelem[k].blk].ey)/eo * AECF(k); + + // AECF(k) part corrects permittivity for axisymmetric external region; +} + +CComplex CbelaviewDoc::D(int k) +{ + // return average electric flux density for the kth element + return meshelem[k].D; +} + +CComplex CbelaviewDoc::e(int k, int i) +{ + // return nodal field intensity for the ith node of the kth element + double aecf=1; + + if((ProblemType) && (blocklist[meshelem[k].lbl].IsExternal)) + { + // correct for axisymmetric external region + double x=meshnode[meshelem[k].p[i]].x; + double y=meshnode[meshelem[k].p[i]].y-extZo; + aecf=(x*x+y*y)/(extRi*extRo); + } + + return (meshelem[k].d[i].re/blockproplist[meshelem[k].blk].ex + + I*meshelem[k].d[i].im/blockproplist[meshelem[k].blk].ey)/eo * aecf; +} + +CComplex CbelaviewDoc::d(int k, int i) +{ + // return nodal flux density for the ith node of the kth element; + return meshelem[k].d[i]; +} + +double CbelaviewDoc::ShortestDistance(double p, double q, int segm) +{ + double t,x[3],y[3]; + + x[0]=nodelist[linelist[segm].n0].x; + y[0]=nodelist[linelist[segm].n0].y; + x[1]=nodelist[linelist[segm].n1].x; + y[1]=nodelist[linelist[segm].n1].y; + + t=((p-x[0])*(x[1]-x[0]) + (q-y[0])*(y[1]-y[0]))/ + ((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])); + + if (t>1.) 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 CbelaviewDoc::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 + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +class CbelaviewDoc : public CDocument +{ +protected: // create from serialization only + CbelaviewDoc(); + DECLARE_DYNCREATE(CbelaviewDoc) + +// Attributes +public: + + // General problem attributes + double Depth; + int LengthUnits; + double *LengthConv; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL Smooth; + BOOL bMultiplyDefinedLabels; + double extRo, extRi, extZo; + + double A_High, A_Low; + double A_lb, A_ub; + + double d_PlotBounds[4][2]; + double PlotBounds[4][2]; + + + // Some default behaviors + CString BinDir; + int d_LineIntegralPoints; + BOOL bHasMask; + + // lists of nodes, segments, and block labels + CArray< belaviewtype::CNode, belaviewtype::CNode&> nodelist; + CArray< belaviewtype::CSegment, belaviewtype::CSegment&> linelist; + CArray< belaviewtype::CBlockLabel, belaviewtype::CBlockLabel&> blocklist; + CArray< belaviewtype::CArcSegment, belaviewtype::CArcSegment&> arclist; + + // CArrays containing the mesh information + CArray< belaviewtype::CMeshNode, belaviewtype::CMeshNode&> meshnode; + CArray< belaviewtype::CElement, belaviewtype::CElement&> meshelem; + + // List of elements connected to each node; + int *NumList; + int **ConList; + + // lists of properties + CArray< belaviewtype::CMaterialProp, belaviewtype::CMaterialProp& > blockproplist; + CArray< belaviewtype::CBoundaryProp, belaviewtype::CBoundaryProp& > lineproplist; + CArray< belaviewtype::CPointProp, belaviewtype::CPointProp& > nodeproplist; + CArray< belaviewtype::CCircuit, belaviewtype::CCircuit& > circproplist; + + // list of points in a user-defined contour; + CArray< CComplex, CComplex& > contour; + + // member functions + int InTriangle(double x, double y); + BOOL InTriangleTest(double x, double y, int i); + BOOL GetPointValues(double x, double y, belaviewtype::CPointVals &u); + BOOL GetPointValues(double x, double y, int k, belaviewtype::CPointVals &u); + void GetLineValues(CXYPlot &p, int PlotType, int npoints); + void GetElementD(int k); + void OnReload(); + int ClosestNode(double x, double y); + CComplex Ctr(int i); + double ElmArea(int i); + double ElmArea(belaviewtype::CElement *elm); + void GetPointD(double x, double y, CComplex &D, belaviewtype::CElement &elm); + void GetNodalD(CComplex *d, int i); + CComplex BlockIntegral(int inttype); + void LineIntegral(int inttype, double *z); + int ClosestArcSegment(double x, double y); + void GetCircle(belaviewtype::CArcSegment &asegm,CComplex &c, double &R); + double ShortestDistanceFromArc(CComplex p, belaviewtype::CArcSegment &arc); + double ShortestDistanceFromSegment(double p, double q, int segm); + double ShortestDistance(double p, double q, int segm); + int ClosestSegment(double x, double y); + BOOL IsSameMaterial(int e1, int e2); + double AECF(int k); + double AECF(int k, CComplex p); + + BOOL ScanPreferences(); + void BendContour(double angle, double anglestep); + BOOL MakeMask(); + CComplex HenrotteVector(int k); + void FindBoundaryEdges(); + BOOL IsKosher(int k); + CComplex E(int k); + CComplex D(int k); + CComplex e(int k, int i); + CComplex d(int k, int i); + +/* // Tests for whether or not one is inside a user-defined + // contour; this was really mostly used pre- v3.0, when + // the areas over which block integrals were taken were + // defined by a closed, user-generated contour. + BOOL ContourClosed(); + BOOL SlowInContour(double x, double y); + BOOL InContour(double x, double y); + BOOL InContour(CElement &elm); + BOOL InContour(CComplex p); + BOOL OnContour(CElement &elm); + void AvgMaxwell(double &fx, double &fy); + void AvgMaxwell(double &fx, double &fy, + CComplex &f2x, CComplex &f2y); +*/ + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CbelaviewDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + // lua extensions + bool luafired; + void initalise_lua(); + static int lua_dumpheader(lua_State * L); + static int lua_getpointvals(lua_State * L); + static int lua_exitpost(lua_State * L); + static int lua_addcontour(lua_State * L); + static int lua_clearcontour(lua_State * L); + static int lua_lineintegral(lua_State * L); + static int lua_selectblock(lua_State * L); + static int lua_groupselectblock(lua_State * L); + static int lua_blockintegral(lua_State * L); + static int lua_clearblock(lua_State * L); + static int lua_zoomout(lua_State * L); + static int lua_zoomin(lua_State * L); + static int lua_zoomnatural(lua_State * L); + static int lua_hidemesh(lua_State * L); + static int lua_showmesh(lua_State * L); + static int lua_showgrid(lua_State * L); + static int lua_hidegrid(lua_State * L); + static int lua_showdensity(lua_State * L); + static int lua_hidedensity(lua_State * L); + static int lua_hidecountour(lua_State * L); + static int lua_showcountour(lua_State * L); + static int lua_zoom(lua_State * L); + static int lua_smoothing(lua_State * L); + static int lua_hidepoints(lua_State * L); + static int lua_showpoints(lua_State * L); + static int lua_gridsnap(lua_State * L); + static int lua_setgrid(lua_State * L); + static int lua_getprobleminfo(lua_State * L); + static int lua_savebitmap(lua_State * L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC) ; + static int lua_getcircuitprops(lua_State *L); + static int lua_saveWMF(lua_State *L); + static int lua_refreshview(lua_State *L); + static int lua_selectline(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_bendcontour(lua_State *L); + static int lua_makeplot(lua_State *L); + static int lua_unselectall(lua_State *L); + static int lua_selectconductor(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_vectorplot(lua_State * L); + static int lua_reload(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_gettitle(lua_State *L); + + + // commands to access low-level information through Lua + static int lua_numnodes(lua_State *L); + static int lua_numelements(lua_State *L); + static int lua_getnode(lua_State *L); + static int lua_getelement(lua_State *L); + + virtual ~CbelaviewDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CbelaviewDoc) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); diff --git a/femm/belaviewLua.cpp b/femm/belaviewLua.cpp new file mode 100644 index 0000000..c0a94c7 --- /dev/null +++ b/femm/belaviewLua.cpp @@ -0,0 +1,1880 @@ +#include "stdafx.h" +#include +#include +#include "bv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "belaviewDoc.h" +#include "belaviewview.h" +#include "MainFrm.h" +#include "windows.h" //necessary for bitmap saving +#include "lua.h" +#include "mycommandlineinfo.h" +#include "promptbox.h" +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern lua_State * lua; +extern BOOL bLinehook; +extern void *pBelaviewDoc; +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern CLuaConsoleDlg *LuaConsole; + +#define CatchNullDocument(); if (pBelaviewDoc==NULL)\ + { CString msg="No current electrostatics output in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//-------------------Lua Extensions------------------------- + +void CbelaviewDoc::initalise_lua() +{ + // use a messagebox to display errors + lua_register(lua,"eo_setfocus",lua_switchfocus); + lua_register(lua,"eo_getpointvalues",lua_getpointvals); + lua_register(lua,"eo_close",lua_exitpost); + lua_register(lua,"eo_addcontour",lua_addcontour); + lua_register(lua,"eo_clearcontour",lua_clearcontour); + lua_register(lua,"eo_lineintegral",lua_lineintegral); + lua_register(lua,"eo_selectblock",lua_selectblock); + lua_register(lua,"eo_groupselectblock",lua_groupselectblock); + lua_register(lua,"eo_clearblock",lua_clearblock); + lua_register(lua,"eo_blockintegral",lua_blockintegral); + lua_register(lua,"eo_zoomnatural",lua_zoomnatural); + lua_register(lua,"eo_zoomin",lua_zoomin); + lua_register(lua,"eo_zoomout",lua_zoomout); + lua_register(lua,"eo_zoom",lua_zoom); + lua_register(lua,"eo_showgrid",lua_showgrid); + lua_register(lua,"eo_hidegrid",lua_hidegrid); + lua_register(lua,"eo_gridsnap",lua_gridsnap); + lua_register(lua,"eo_setgrid",lua_setgrid); + lua_register(lua,"eo_showmesh",lua_showmesh); + lua_register(lua,"eo_hidemesh",lua_hidemesh); + lua_register(lua,"eo_hidedensityplot",lua_hidedensity); + lua_register(lua,"eo_showdensityplot",lua_showdensity); + lua_register(lua,"eo_hidecontourplot",lua_hidecountour); + lua_register(lua,"eo_showcontourplot",lua_showcountour); + lua_register(lua,"eo_showvectorplot" ,lua_vectorplot); + lua_register(lua,"eo_smooth",lua_smoothing); + lua_register(lua,"eo_showpoints",lua_showpoints); + lua_register(lua,"eo_hidepoints",lua_hidepoints); + lua_register(lua,"eo_shownames",lua_shownames); + lua_register(lua,"eo_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"eo_savebitmap",lua_savebitmap); + lua_register(lua,"eo_getconductorproperties",lua_getcircuitprops); + lua_register(lua,"eo_savemetafile",lua_saveWMF); + lua_register(lua,"eo_refreshview",lua_refreshview); + lua_register(lua,"eo_selectpoint",lua_selectline); + lua_register(lua,"eo_seteditmode",lua_seteditmode); + lua_register(lua,"eo_bendcontour",lua_bendcontour); + lua_register(lua,"eo_makeplot",lua_makeplot); + lua_register(lua,"eo_selectconductor",lua_selectconductor); + lua_register(lua,"eo_reload",lua_reload); + + lua_register(lua,"eo_resize",luaResize); + lua_register(lua,"eo_minimize",luaMinimize); + lua_register(lua,"eo_maximize",luaMaximize); + lua_register(lua,"eo_restore", luaRestore); + lua_register(lua,"eo_gettitle",lua_gettitle); + lua_register(lua,"eo_get_title",lua_gettitle); + + // compatibility with alternate lua function naming convention + lua_register(lua,"eo_set_focus",lua_switchfocus); + lua_register(lua,"eo_get_point_values",lua_getpointvals); + lua_register(lua,"eo_add_contour",lua_addcontour); + lua_register(lua,"eo_clear_contour",lua_clearcontour); + lua_register(lua,"eo_line_integral",lua_lineintegral); + lua_register(lua,"eo_select_block",lua_selectblock); + lua_register(lua,"eo_group_select_block",lua_groupselectblock); + lua_register(lua,"eo_clear_block",lua_clearblock); + lua_register(lua,"eo_block_integral",lua_blockintegral); + lua_register(lua,"eo_zoom_natural",lua_zoomnatural); + lua_register(lua,"eo_zoom_in",lua_zoomin); + lua_register(lua,"eo_zoom_out",lua_zoomout); + lua_register(lua,"eo_show_grid",lua_showgrid); + lua_register(lua,"eo_hide_grid",lua_hidegrid); + lua_register(lua,"eo_show_mesh",lua_showmesh); + lua_register(lua,"eo_hide_mesh",lua_hidemesh); + lua_register(lua,"eo_hide_density_plot",lua_hidedensity); + lua_register(lua,"eo_show_density_plot",lua_showdensity); + lua_register(lua,"eo_hide_contour_plot",lua_hidecountour); + lua_register(lua,"eo_show_contour_plot",lua_showcountour); + lua_register(lua,"eo_show_points",lua_showpoints); + lua_register(lua,"eo_hide_points",lua_hidepoints); + lua_register(lua,"eo_grid_snap",lua_gridsnap); + lua_register(lua,"eo_set_grid",lua_setgrid); + lua_register(lua,"eo_get_problem_info",lua_getprobleminfo); + lua_register(lua,"eo_save_bitmap",lua_savebitmap); + lua_register(lua,"eo_get_conductor_properties",lua_getcircuitprops); + lua_register(lua,"eo_save_metafile",lua_saveWMF); + lua_register(lua,"eo_refresh_view",lua_refreshview); + lua_register(lua,"eo_select_point",lua_selectline); + lua_register(lua,"eo_set_edit_mode",lua_seteditmode); + lua_register(lua,"eo_bend_contour",lua_bendcontour); + lua_register(lua,"eo_make_plot",lua_makeplot); + lua_register(lua,"eo_select_conductor",lua_selectconductor); + lua_register(lua,"eo_show_names",lua_shownames); + lua_register(lua,"eo_show_vector_plot",lua_vectorplot); + + // functions to access low-level mesh info + lua_register(lua,"eo_numnodes",lua_numnodes); + lua_register(lua,"eo_numelements",lua_numelements); + lua_register(lua,"eo_getnode",lua_getnode); + lua_register(lua,"eo_getelement",lua_getelement); + + lua_register(lua,"eo_num_nodes",lua_numnodes); + lua_register(lua,"eo_num_elements",lua_numelements); + lua_register(lua,"eo_get_node",lua_getnode); + lua_register(lua,"eo_get_element",lua_getelement); + + pBelaviewDoc=this; + +} + +int CbelaviewDoc::lua_dumpheader(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + return 0; +} + +int CbelaviewDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CbelaviewDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".res") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<6;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CbelaviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".res") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pBelaviewDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CbelaviewDoc::lua_getpointvals(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CPointVals u; + CComplex Jtot; + + if(thisDoc->GetPointValues(px, py, u)==TRUE) + { + lua_pushnumber(L,u.V); + lua_pushnumber(L,u.D.re); + lua_pushnumber(L,u.D.im); + lua_pushnumber(L,u.E.re); + lua_pushnumber(L,u.E.im); + lua_pushnumber(L,u.e.re); + lua_pushnumber(L,u.e.im); + lua_pushnumber(L,u.nrg); + return 8; + } + + return 0; +} + +int CbelaviewDoc::lua_exitpost(lua_State * L) +{ + CatchNullDocument(); + ((CbelaviewDoc *)pBelaviewDoc)->OnCloseDocument( ); + + return 0; +} + +int CbelaviewDoc::lua_reload(lua_State * L) +{ + CatchNullDocument(); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + // theView->BeginWaitCursor(); + thisDoc->OnReload(); + // theView->EndWaitCursor(); + if (theView->d_ResetOnReload==FALSE) thisDoc->FirstDraw=FALSE; + theView->RedrawView(); + theView->LuaViewInfo(); + return 0; +} + +void CbelaviewView::LuaViewInfo() +{ + OnViewInfo(); +} + +int CbelaviewDoc::lua_addcontour(lua_State * L) +{ + CatchNullDocument(); + CComplex z; + int i; + z.Set(lua_todouble(L,1),lua_todouble(L,2)); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + i=(int) thisDoc->contour.GetSize(); + + if(i>0){ + if (z!=thisDoc->contour[i-1]) + thisDoc->contour.Add(z); + } + else thisDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + + return 0; +} + +int CbelaviewDoc::lua_clearcontour(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + + return 0; +} + +int CbelaviewDoc::lua_lineintegral(lua_State * L) +{ + CatchNullDocument(); + int type; + double z[4]; + + type=(int) lua_todouble(L,1); + // 0 - E.t + // 1 - D.n + // 2 - Cont length + // 3 - Force from stress tensor + // 4 - Torque from stress tensor + + if (type<0 || type >4) + { + CString msg; + msg.Format("Invalid line integral selected %d",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + z[0]=z[1]=0; + thisDoc->LineIntegral(type,z); + + lua_pushnumber(lua,z[0]); + lua_pushnumber(lua,z[1]); + + return 2; +} + +int CbelaviewDoc::lua_selectblock(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int k; + + if (thisDoc->meshelem.GetSize()>0){ + k=thisDoc->InTriangle(px,py); + if(k>=0){ + thisDoc->bHasMask=FALSE; + thisDoc->blocklist[thisDoc->meshelem[k].lbl].ToggleSelect(); + // RedrawView(); + theView->DrawSelected=thisDoc->meshelem[k].lbl; + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + } + + return 0; +} + +int CbelaviewDoc::lua_groupselectblock(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int j,k,n; + + if (thisDoc->meshelem.GetSize()>0) + { + n=lua_gettop(L); + k=0; if (n>0) k=(int)lua_todouble(L,1); + + for(j=0;jblocklist.GetSize();j++) + { + if ((thisDoc->blocklist[j].InGroup==k) || (n==0)) + thisDoc->blocklist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } + + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + + return 0; +} + +int CbelaviewDoc::lua_clearblock(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + theView->UnselectAll(); + theView->EditAction=0; + theView->RedrawView(); + + return 0; +} + + +int CbelaviewDoc::lua_blockintegral(lua_State * L) +{ + // 0 - Stored anergy + // 1 - Area + // 2 - Volume + // 3 - Average D + // 4 - Average E + // 5 - Weighted Stress Tensor Force + // 6 - Weighted Stress Tensor Torque + + CatchNullDocument(); + int type; + type=(int) lua_todouble(L,1); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CComplex z; + + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (thisDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + if (type>=5) + for(i=0;imeshnode.GetSize();i++) + if (thisDoc->meshnode[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE) + { + CString msg="Cannot integrate\nNo area has been selected"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + if(type>=5) thisDoc->MakeMask(); + z=thisDoc->BlockIntegral(type); + + lua_pushnumber(L,z.re); + lua_pushnumber(L,z.im); + + return 2; +} + +int CbelaviewDoc::lua_zoomin(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + + theView->ox=theView->ox+0.25*x/theView->mag; + theView->oy=theView->oy+0.25*y/theView->mag; + theView->mag*=2.; + + theView->RedrawView(); + + + + + return 0; +} + +int CbelaviewDoc::lua_zoom(lua_State * L) +{ + CatchNullDocument(); + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CRect r; + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CbelaviewDoc::lua_zoomnatural(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + + CbelaviewDoc *pDoc=theView->GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return 0; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + theView->GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + if(pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else theView->RedrawView(); + + + + return 0; +} + +int CbelaviewDoc::lua_zoomout(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + theView->ox=theView->ox-0.5*x/theView->mag; + theView->oy=theView->oy-0.5*y/theView->mag; + theView->mag/=2.; + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_showmesh(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_hidemesh(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->RedrawView(); + + return 0; +} + + +int CbelaviewDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_showdensity(lua_State * L) +{ + CatchNullDocument(); + BOOL showlegend; + BOOL gscale; + int PlotType,n; + double m_ub1,m_lb1; + CString type; + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + n=lua_gettop(L); if(n<3) return 0; + + showlegend=(int) lua_todouble(L,1); + gscale=(int) lua_todouble(L,2); + PlotType=(int) lua_todouble(L,3); + + if(n>=5) + { + m_ub1=lua_todouble(L,4); + m_lb1=lua_todouble(L,5); + } + + if(m_lb1>m_ub1) + { + double temp=m_lb1; + m_lb1=m_ub1; + m_ub1=temp; + } + + if ((PlotType>2)|| (PlotType<0)) PlotType=0; + + if (showlegend==-1) + { + // load back the default plot range + m_lb1=thisDoc->d_PlotBounds[PlotType][0]; + m_ub1=thisDoc->d_PlotBounds[PlotType][1]; + showlegend=1; + gscale=0; + n=5; + } + + theView->DensityPlot=PlotType+1; + theView->LegendFlag=showlegend; + theView->GreyContours=gscale; + if(n>=5) + { + thisDoc->PlotBounds[PlotType][1]=m_ub1; + thisDoc->PlotBounds[PlotType][0]=m_lb1; + } + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_hidedensity(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + theView->DensityPlot=0; + + theView->RedrawView(); + + return 0; +} + + +int CbelaviewDoc::lua_showcountour(lua_State * L) +{ + CatchNullDocument(); + int m_numcontours; + double m_alow,m_ahigh; + CString type; + m_numcontours=(int) lua_todouble(L,1); + m_alow=lua_todouble(L,2); + m_ahigh=lua_todouble(L,3); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + + theView->ShowAr=true; + thisDoc->A_Low=m_alow; + thisDoc->A_High=m_ahigh; + theView->NumContours=m_numcontours; + theView->RedrawView(); + + if(m_numcontours==-1) + { + thisDoc->A_Low=thisDoc->A_lb; + thisDoc->A_High=thisDoc->A_ub; + theView->NumContours=19; + } + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_hidecountour(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + theView->ShowAr=FALSE; + + theView->RedrawView(); + return 0; +} + +int CbelaviewDoc::lua_smoothing(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + + if (temp=="off") + { + thisDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + + } + if (temp=="on") + { + thisDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for smoothing"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + + theView->RedrawView(); + + return 0; +} + + +int CbelaviewDoc::lua_showpoints(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_hidepoints(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CbelaviewDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_getprobleminfo(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Depth); + lua_pushnumber(L,thisDoc->LengthConv[thisDoc->LengthUnits]); + + return 3; +} + +int CbelaviewDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + // tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + // to save a bitmap file we need + // a bitmapheader lets use the v5 + + // OpenClipboard(); + // EmptyClipboard(); + // SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + // CloseClipboard(); +return 0; +} + + +PBITMAPINFO CbelaviewDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy9"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits >= 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CbelaviewDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy10"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy11"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy12"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy13"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy14"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy15"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy16"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + +int CbelaviewDoc::lua_getcircuitprops(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * TheDoc; // note normally thisdoc + CbelaviewView * theView; + TheDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=TheDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)TheDoc->GetNextView(pos); + + int NumCircuits,i,k; + CString circuitname; + circuitname=lua_tostring(L,1); + k=-1; + + // ok we need to find the correct entry for the circuit name + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName==circuitname) + { + k=i; + i=NumCircuits; // that will break it + } + } + +// trap errors + + if(k==-1) + { + CString msg="Unknown conductor"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + lua_pushnumber(L,TheDoc->circproplist[k].V); + lua_pushnumber(L,TheDoc->circproplist[k].q); + return 2; +} + +int CbelaviewDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CbelaviewDoc::lua_refreshview(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // redraw the view + theView->OnDraw(pDC); + + return 0; +} + +int CbelaviewDoc::lua_selectline(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * pDoc; // note normally thisdoc + CbelaviewView * theView; + pDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)pDoc->GetNextView(pos); + + theView->EditAction=1; // make sure things update OK + + double mx,my; + int i,j,k,m; + + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + + +//*************** + { + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return 0; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + theView->DrawUserContour(FALSE); + return 0; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(y); + theView->DrawUserContour(FALSE); + } + } + } + } + + +//************* + return 0; +} + +int CbelaviewDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + if (EditAction=="point") + { + if (theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + if (theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) + { + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=0; + } + if (EditAction=="contour") + { + if(theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=1; + } + if (EditAction=="area") + { + if(theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + theView->EditAction=2; + } + + return 0; +} + +int CbelaviewDoc::lua_bendcontour(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + thisDoc->BendContour(lua_todouble(L,1),lua_todouble(L,2)); + theView->InvalidateRect(NULL); + + return 0; +} + +int CbelaviewDoc::lua_makeplot(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc *pDoc; + CbelaviewView *pView; + pDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + pView=(CbelaviewView *)pDoc->GetNextView(pos); + + int PlotType,npoints,FileFormat,n; + CString ToFile; + +// if ((pView->EditAction!=1) || (pDoc->contour.GetSize()==0)){ + if (pDoc->contour.GetSize()==0){ + CString outmsg; + outmsg.Format("*** Cannot create a plot;\r\n*** No contour has been defined\r\n"); + LuaConsole->ToOutput(outmsg); + return TRUE; + } + + n=lua_gettop(L); + + if(n>0) PlotType=(int) lua_todouble(L,1); + else return FALSE; + + if(n>1) npoints=(int) lua_todouble(L,2); + else npoints=pView->d_PlotPoints; + + CXYPlot xyplot; + pDoc->GetLineValues(xyplot,PlotType,npoints); + + if(n<3) + { + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (pView->OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else{ + ToFile.Format("%s",lua_tostring(L,3)); + + if(n>3){ + FileFormat=(int) lua_todouble(L,4); + if (xyplot.ToDisk(FileFormat,ToFile)==FALSE) + LuaConsole->ToOutput("*** Couldn't write data to disk\r\n"); + } + else{ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,ToFile)); + DeleteEnhMetaFile(hMeta); + } + } + + return TRUE; +} + +int CbelaviewDoc::lua_selectconductor(lua_State *L) +{ + CatchNullDocument(); + int n=lua_gettop(L); + if (n==0) return 0; + + int j,i; + CString name; + name=lua_tostring(L,1); + + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + for(i=0,j=-1;icircproplist.GetSize();i++) + { + + if (name==thisDoc->circproplist[i].CircName) + { + j=i; + break; + } + } + + if (j<0) return 0; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (thisDoc->nodelist[i].InConductor==j) thisDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (thisDoc->linelist[i].InConductor==j) thisDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (thisDoc->arclist[i].InConductor==j) thisDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (thisDoc->meshnode[i].Q==j) + { + thisDoc->meshnode[i].IsSelected=1-thisDoc->meshnode[i].IsSelected; + } + } + theView->RedrawView(); + + return 0; +} + +int CbelaviewDoc::lua_shownames(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +int CbelaviewDoc::lua_vectorplot(lua_State * L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n>0) theView->VectorPlot=(int)lua_todouble(L,1); + if (n>1) theView->VectorScaleFactor=lua_todouble(L,2); + + theView->InvalidateRect(NULL); + + return 0; +} + +int CbelaviewDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CbelaviewDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CbelaviewDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CbelaviewDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + CbelaviewView * theView; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CbelaviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + + +int CbelaviewDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + +/////////////////////////////////////////////////////// +// Functions that provide low-level access to the mesh +/////////////////////////////////////////////////////// + +int CbelaviewDoc::lua_numnodes(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshnode.GetSize()); + + return 1; +} + +int CbelaviewDoc::lua_numelements(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshelem.GetSize()); + + return 1; +} + +int CbelaviewDoc::lua_getnode(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshnode.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshnode[k].x); + lua_pushnumber(L,thisDoc->meshnode[k].y); + + return 2; +} + +int CbelaviewDoc::lua_getelement(lua_State *L) +{ + CatchNullDocument(); + CbelaviewDoc * thisDoc; + thisDoc=(CbelaviewDoc *)pBelaviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshelem.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshelem[k].p[0]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[1]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[2]+1); + lua_pushnumber(L,Re(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,Im(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,thisDoc->ElmArea(k)); + lua_pushnumber(L,thisDoc->blocklist[thisDoc->meshelem[k].lbl].InGroup); + + return 7; +} diff --git a/femm/belaviewView.cpp b/femm/belaviewView.cpp new file mode 100644 index 0000000..dd57312 --- /dev/null +++ b/femm/belaviewView.cpp @@ -0,0 +1,3690 @@ +// belaviewView.cpp : implementation of the CbelaviewView class +// + +#include "stdafx.h" +#include +#include +#include "femm.h" +#include "bv_problem.h" +#include "xyplot.h" +#include "belaviewDoc.h" +#include "belaviewView.h" +#include "GridMod.h" +#include "EnterPt.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "KbdZoom.h" +#include "bv_CPlotDlg2.h" +#include "bv_DPlotDlg2.h" +#include "bv_VPlotDlg.h" +#include "MyMsgBox.h" +#include "bv_XYPlotDlg.h" +#include "bv_LIntDlg.h" +#include "bv_BlockInt.h" +#include "bv_CircDlg.h" +#include "BendContourDlg.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +#define MSKHI (1. + 1.e-08) +#define MSKLO (0. - 1.e-08) + +extern lua_State * lua; +extern BOOL bLinehook; + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView + +IMPLEMENT_DYNCREATE(CbelaviewView, CView) + +BEGIN_MESSAGE_MAP(CbelaviewView, CView) + //{{AFX_MSG_MAP(CbelaviewView) + ON_COMMAND(ID_SMOOTH, OnSmooth) + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_CPLOT, OnCplot) + ON_COMMAND(ID_DPLOT, OnDplot) + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWindow) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_RELOAD, OnReload) + ON_COMMAND(ID_MENU_AREA, OnMenuArea) + ON_COMMAND(ID_MENU_CONTOUR, OnMenuContour) + ON_COMMAND(ID_MENU_POINT, OnMenuPoint) + ON_WM_KEYDOWN() + ON_COMMAND(ID_MENU_PLOT, OnMenuPlot) + ON_COMMAND(ID_MENU_INTEGRATE, OnMenuIntegrate) + ON_COMMAND(ID_MENUSHOWPTS, OnMenushowpts) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_WM_ERASEBKGND() + ON_WM_RBUTTONDBLCLK() + ON_WM_SIZE() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_VIEW_CIRCPROPS, OnViewCircprops) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_INFO, OnViewInfo) + ON_COMMAND(ID_VIEW_SHOWBLOCKNAMES, OnViewShowblocknames) + ON_COMMAND(ID_VPLOT, OnVplot) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_LBUTTONDBLCLK() +END_MESSAGE_MAP() + +void MyMessageBox(CString s); + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView construction/destruction + +CbelaviewView::CbelaviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // TODO: add construction code here + d_EditAction=0; + d_GridFlag=FALSE; + d_SnapFlag=FALSE; + d_MeshFlag=FALSE; + d_LegendFlag=TRUE; + d_GreyContours=FALSE; + d_NumContours=19; + d_ShowAr=FALSE; + d_ShowMask=FALSE; + d_DensityPlot=1; + d_VectorPlot=0; + d_PtsFlag=TRUE; + d_ResetOnReload=FALSE; + d_Smooth=TRUE; + d_PlotPoints=1500; + d_ShowNames=FALSE; + + ox=0.; oy=0.; mag=100.; // lower left corner is origin; 100 dpi + GridSize=0.25; // 1/4" grid + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + + ////////////////////////////// + // Default Colors // + ////////////////////////////// + + // Greyscale Colormap + Grey00=dGrey00; + Grey01=dGrey01; + Grey02=dGrey02; + Grey03=dGrey03; + Grey04=dGrey04; + Grey05=dGrey05; + Grey06=dGrey06; + Grey07=dGrey07; + Grey08=dGrey08; + Grey09=dGrey09; + Grey10=dGrey10; + Grey11=dGrey11; + Grey12=dGrey12; + Grey13=dGrey13; + Grey14=dGrey14; + Grey15=dGrey15; + Grey16=dGrey16; + Grey17=dGrey17; + Grey18=dGrey18; + Grey19=dGrey19; + + // BELA Colormap + Color19=dColor19; + Color18=dColor18; + Color17=dColor17; + Color16=dColor16; + Color15=dColor15; + Color14=dColor14; + Color13=dColor13; + Color12=dColor12; + Color11=dColor11; + Color10=dColor10; + Color09=dColor09; + Color08=dColor08; + Color07=dColor07; + Color06=dColor06; + Color05=dColor05; + Color04=dColor04; + Color03=dColor03; + Color02=dColor02; + Color01=dColor01; + Color00=dColor00; + + // Other colors + SelColor = dSelColor; + MeshColor = dMeshColor; + BlockColor = dBlockColor; + LineColor = dLineColor; + RegionColor = dRegionColor; + GridColor = dGridColor; + BackColor = dBackColor; + NodeColor = dNodeColor; + TextColor = dTextColor; + RealFluxLineColor = dRealFluxLineColor; + MaskLineColor = dMaskLineColor; + NameColor = dNameColor; + VectorColor = dRealVectorColor; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // Apply default behaviors + EditAction=d_EditAction; + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; +} + +CbelaviewView::~CbelaviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL CbelaviewView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView drawing +void CbelaviewView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +BOOL CbelaviewView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CbelaviewView::DoContours(CDC *pDC,int *p,int side,int Aflag) +{ + int i,j,k; + static double q[4][4]; + static double *m[4]; + static int u[4]; + double *swap; + double hi,lo,a,b,z,offset; + + CbelaviewDoc *pDoc=GetDocument(); + + switch(side) + { + case 0 : u[0]=p[0]; u[1]=p[1]; u[2]=p[1]; u[3]=p[2]; break; + case 1 : u[0]=p[1]; u[1]=p[2]; u[2]=p[2]; u[3]=p[0]; break; + default: u[0]=p[2]; u[1]=p[0]; u[2]=p[0]; u[3]=p[1]; break; + } + + for(i=0;i<4;i++){ + m[i]=q[i]; + m[i][0]=(double) pDoc->meshnode[u[i]].xs; + m[i][1]=(double) pDoc->meshnode[u[i]].ys; + m[i][3]=pDoc->meshnode[u[i]].x; + if (Aflag==0) m[i][2]=pDoc->meshnode[u[i]].V; + if (Aflag==1) m[i][2]=pDoc->meshnode[u[i]].V; + if (Aflag==2) m[i][2]=pDoc->meshnode[u[i]].msk; + } + + // scale A for easier analysis. Not necessary if mask is being displayed, + // since mask always varies between zero and one. + + if (Aflag<2) + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-pDoc->A_Low)/ + (pDoc->A_High-pDoc->A_Low); + offset=-NumContours*pDoc->A_Low/(pDoc->A_High-pDoc->A_Low); + } + else + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-MSKLO)/(MSKHI-MSKLO); + offset=-NumContours*MSKLO/(MSKHI-MSKLO); + } + + // swap around so that lowest magnitude is first point in + // each line... + if (m[0][2]>m[1][2]){ + swap=m[1]; + m[1]=m[0]; + m[0]=swap; + } + if (m[2][2]>m[3][2]){ + swap=m[3]; + m[3]=m[2]; + m[2]=swap; + } + + // figure out which contours lie in this section + lo=m[0][2]; if(m[2][2]>lo) lo=m[2][2]; + hi=m[1][2]; if(m[3][2]=0) && (iSetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), RealFluxLineColor ); + +// if(Aflag==1) +// pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), +// (int) ((m[3][1]-m[2][1])*b+m[2][1]), ImagFluxLineColor ); + + if(Aflag==2) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), MaskLineColor ); + } +} +//////////////// +void CbelaviewView::PlotFluxDensity(CDC *pDC,int elmnum,int flag) +{ + int i,j,k,n,lav; + double b,bn[3],bh,bl,y,z; + CComplex b1[3],b2[3]; + POINT ps[3]; + static double c[64][3],p[3][2]; + CElement elm; + CbelaviewDoc *pDoc=GetDocument(); + + elm=pDoc->meshelem[elmnum]; + + if (((pDoc->meshnode[elm.p[0]].xs == pDoc->meshnode[elm.p[1]].xs) && + (pDoc->meshnode[elm.p[1]].xs == pDoc->meshnode[elm.p[2]].xs)) || + ((pDoc->meshnode[elm.p[0]].ys == pDoc->meshnode[elm.p[1]].ys) && + (pDoc->meshnode[elm.p[1]].ys == pDoc->meshnode[elm.p[2]].ys) )) return; + + if(pDoc->blocklist[elm.lbl].IsSelected==TRUE) return; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + for(i=0;i<3;i++) + { + switch(DensityPlot) + { + case 2: + if (pDoc->Smooth==TRUE) bn[i]=abs(elm.d[i]); + else bn[i]=abs(elm.D); + break; + + case 3: + if (pDoc->Smooth==TRUE) bn[i]=abs(pDoc->e(elmnum,i)); + else bn[i]=abs(pDoc->E(elmnum)); + break; + + default: + bn[i]=pDoc->meshnode[elm.p[i]].V; + break; + } + } + + flag=1; + + bl=pDoc->PlotBounds[DensityPlot-1][0]; + bh=pDoc->PlotBounds[DensityPlot-1][1]; + + if(bh==bl) return; + else for(i=0;i<3;i++) bn[i]=20.*(bn[i]-bl)/(bh-bl); + + // find subtriangle edges; + for(i=0,n=0;i<3;i++) + { + c[n][0]=(double) pDoc->meshnode[elm.p[i]].xs; + c[n][1]=(double) pDoc->meshnode[elm.p[i]].ys; + c[n][2]=bn[i]; + n++; if(n>=64) return; + j=i+1; if(j==3) j=0; + p[0][0]=(double) pDoc->meshnode[elm.p[i]].xs; + p[0][1]=(double) pDoc->meshnode[elm.p[i]].ys; + p[1][0]=(double) pDoc->meshnode[elm.p[j]].xs; + p[1][1]=(double) pDoc->meshnode[elm.p[j]].ys; + p[2][0]=bn[i]; + p[2][1]=bn[j]; + if(p[2][0]=0) && (z<20)) n++; + if(n>=64) return; + } + else + for(z=floor(p[2][0]);z>p[2][1];z--) + { + y=(z-p[2][0])/(p[2][1]-p[2][0]); + c[n][0]=(1.-y)*p[0][0] + y*p[1][0]; + c[n][1]=(1.-y)*p[0][1] + y*p[1][1]; + c[n][2]=(1.-y)*p[2][0] + y*p[2][1]; + if ((z>=0) && (z<20)) n++; + if(n>=64) return; + } + + } + + // subtriangle vertices are now listed in the c[][] array. + // there are n vertices. Now, plot out these subtriangles; + + do{ + // find lowest vertex & neighbors; + for(i=1,j=0;i=n) k=0; + + // plot triangle; + b=(c[i][2]+c[j][2]+c[k][2])/3.; + lav=19-((int) b); + if(lav>19) lav=19; + if(lav<0) lav=0; + + { + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + BOOL DrawIt=TRUE; + + if (GreyContours==FALSE){ + if(mymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(mymap[lav]); + FillPen.CreatePen(PS_SOLID,1,mymap[lav]); + } + } + else{ + if(greymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(greymap[lav]); + FillPen.CreatePen(PS_SOLID,1,greymap[lav]); + } + } + if(DrawIt==TRUE) + { + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + ps[0].x=(long) c[i][0]; ps[0].y=(long) c[i][1]; + ps[1].x=(long) c[j][0]; ps[1].y=(long) c[j][1]; + ps[2].x=(long) c[k][0]; ps[2].y=(long) c[k][1]; + pDC->Polygon(ps,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); + } + } + + // remove middle point from the list; + for(i=j;i2); +} + +/////////////// + +void CbelaviewView::PlotSelectedElm(CDC *pDC,CElement &elm) +{ + int i; + POINT p[3]; + CbelaviewDoc *pDoc=GetDocument(); + + if (elm.lbl!=DrawSelected) + if (pDoc->blocklist[elm.lbl].IsSelected==FALSE) return; + + for(i=0;i<3;i++){ + p[i].x=pDoc->meshnode[elm.p[i]].xs; + p[i].y=pDoc->meshnode[elm.p[i]].ys; + } + + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + if (pDoc->blocklist[elm.lbl].IsSelected==TRUE) + { + FillBrush.CreateSolidBrush(RegionColor); + FillPen.CreatePen(PS_SOLID,1,RegionColor); + } + else{ + FillBrush.CreateSolidBrush(0x00ffffff); + FillPen.CreatePen(PS_SOLID,1,0x00ffffff); + } + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + pDC->Polygon(p,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); +} + +void CbelaviewView::DrawUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CbelaviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,FALSE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,FALSE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,FALSE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CbelaviewView::EraseUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CbelaviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,TRUE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,TRUE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,TRUE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CbelaviewView::OnDraw(CDC* pDC) +{ + CbelaviewDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + RECT r; + static RECT oldr; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,dt,R; + double xss,yss,rss,rt; + CComplex p,c,s; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if(pDoc->FirstDraw<0) + { + pDoc->Smooth=d_Smooth; + pDoc->FirstDraw=FALSE; + } + + if(pDoc->FirstDraw==TRUE){ + // Apply default behaviors + ox=0.; oy=0.; mag=100.; + GridSize=0.25; + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + if(pDoc->bMultiplyDefinedLabels){ + EditAction=2; + ShowNames=TRUE; + } + else{ + EditAction=d_EditAction; + ShowNames=d_ShowNames; + } + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; + pDoc->Smooth=d_Smooth; + + OnZoomNatural(); + LinePix.RemoveAll(); + oldr=r; + OnViewInfo(); + } + + if((oldr.right!=r.right) || (oldr.bottom!=r.bottom)) + { + LinePix.RemoveAll(); + oldr=r; + } + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + // just give up and make sure that the right + // buttons are checked every time through OnDraw; + // otherwise, it's just too easy to get the buttons + // so that they don't match the actual mode. + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen, + penMesh,penReal,penImag,penMask, + penNode,penText,penArrow; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penReal.CreatePen(PS_SOLID,1,RealFluxLineColor); + penMask.CreatePen(PS_SOLID,1,MaskLineColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penText.CreatePen(PS_SOLID,1,TextColor); + penArrow.CreatePen(PS_SOLID,1,VectorColor); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=2.; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // get center and radius of the screen in drawing coords. + // can then use to find out whether elements are off the screen. + xs=(r.right+r.left)/2; + ys=(r.top+r.bottom)/2; + ScreenToDwg(xs,ys, &xss, &yss, &r); + rss=sqrt(pow((double)r.bottom,2.) + pow((double)r.right,2.))/(2.*mag); + + // Draw selected area... + if (EditAction==2) + { + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + PlotSelectedElm(pDC,pDoc->meshelem[i]); + } + } + } + + // Draw flux densities if they are enabled... + if(DensityPlot!=0){ + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=abs(CComplex(xss,yss)-pDoc->meshelem[i].ctr); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + { + PlotFluxDensity(pDC,i,DensityPlot); + } + } + } + } + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + int pi,po,OnBoundary; + + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshelem.GetSize();i++) + { + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + + OnBoundary=FALSE; + for(j=0;j<3;j++) + if (pDoc->meshelem[i].n[j] == 1) + OnBoundary=TRUE; + + for(j=0;j<3;j++) + { + k=j+1; if (k==3) k=0; + pi=pDoc->meshelem[i].p[j]; + po=pDoc->meshelem[i].p[k]; + + if((po>pi) || (OnBoundary==TRUE)) + { + MyMoveTo(pDC,pDoc->meshnode[pi].xs, + pDoc->meshnode[pi].ys); + MyLineTo(pDC,pDoc->meshnode[po].xs, + pDoc->meshnode[po].ys); + } + } + } + } + pDC->SelectObject( pOldPen ); + } + + // Draw contour lines, if they are enabled. + pOldPen = pDC->SelectObject( &penReal ); + if (ShowAr==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,0); + } + } + + pDC->SelectObject(&penMask); + if (ShowMask==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,2); + } + } + + pDC->SelectObject( pOldPen ); + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].Hidden==FALSE){ + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].Hidden==FALSE){ + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].MaxSideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + if(PtsFlag==TRUE) for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + + // Draw vectors + if ((VectorPlot>0) && (pDoc->nodelist.GetSize()>0)) + { + CPointVals u; + BOOL drawgrid=TRUE; + double MaxVal; + int xp,yp; + CComplex vr,va,c0,c1; + int ilo,ihi,jlo,jhi; + + MaxVal=pDoc->d_PlotBounds[VectorPlot][1]; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Vectors too dense to display.",TRUE); + } + else{ + pOldPen = pDC->SelectObject( &penArrow ); + for(k=0;kmeshelem.GetSize();k++) + { + rt=abs(CComplex(xss,yss)-pDoc->meshelem[k].ctr); + if( rt < ( sqrt(pDoc->meshelem[k].rsqr) + rss) ) + { + c0=pDoc->meshelem[k].ctr-sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c1=pDoc->meshelem[k].ctr+sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c0/=GridSize; + c1/=GridSize; + ilo=(int) floor(Re(c0)); + ihi=(int) ceil (Re(c1)); + jlo=(int) floor(Im(c0)); + jhi=(int) ceil (Im(c1)); + for(i=ilo;i<=ihi;i++) + { + for(j=jlo;j<=jhi;j++) + { + xd=GridSize*((double) i); + yd=GridSize*((double) j); + if(pDoc->InTriangleTest(xd,yd,k)) + { + pDoc->GetPointValues(xd,yd,k,u); + + if (VectorPlot==1) vr=(u.D)*GridSize*VectorScaleFactor/MaxVal; + else vr=(u.E)*GridSize*VectorScaleFactor/MaxVal; + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, VectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + } + } + } + } // end of if(rt<... + } + pDC->SelectObject( pOldPen ); + } + } + + if(EditAction==1) DrawUserContour(TRUE); + + // draw block names/labels + if(ShowNames){ + pDC->SetTextColor(NameColor); + pOldPen = pDC->SelectObject( &penGreen ); + CString lbl; + for(i=0;iblocklist.GetSize();i++) + { + + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + lbl=pDoc->blockproplist[pDoc->blocklist[i].BlockType].BlockName; + pDC->TextOut(xs+5,ys,lbl); + } + pDC->SelectObject( pOldPen ); + } + + // Draw Legend if it is enabled; + if((LegendFlag==TRUE) && (DensityPlot!=0)) + { + CBrush *pOldBrush; + char cc[80]; + double dta; + CBrush BackBrush; + + pOldPen = pDC->SelectObject( &penText ); + pDC->SetTextColor(TextColor); + pDC->SetBkMode(TRANSPARENT); + pDC->SetTextAlign(TA_TOP); + pDC->SetTextAlign(TA_LEFT); + BackBrush.CreateSolidBrush(BackColor); + pOldBrush = pDC->SelectObject( &BackBrush ); + pDC->Rectangle(r.right-212-6,r.top+6,r.right-6,r.top+24+21*16 ); + pDC->SelectObject(pOldBrush); + + if (DensityPlot==1) sprintf(cc,"Density Plot: V, Volts"); + if (DensityPlot==2) sprintf(cc,"Density Plot: |D|, C/m^2"); + if (DensityPlot==3) sprintf(cc,"Density Plot: |E|, V/m"); + pDC->TextOut(r.right-212,r.top+16*20+16,cc,(int) strlen(cc)); + + dta=(pDoc->PlotBounds[DensityPlot-1][1]- + pDoc->PlotBounds[DensityPlot-1][0])/20.; + + for(i=0;i<20;i++){ + + { + CBrush FillBrush; + + if (GreyContours==FALSE) FillBrush.CreateSolidBrush(mymap[i]); + else FillBrush.CreateSolidBrush(greymap[i]); + pOldBrush = pDC->SelectObject( &FillBrush ); + pDC->Rectangle(r.right-212,r.top+16*i+12,r.right-187,r.top+12+16*(i+1) ); + pDC->SelectObject(pOldBrush); + } + + double Blb=pDoc->PlotBounds[DensityPlot-1][0]; + double Bub=pDoc->PlotBounds[DensityPlot-1][1]; + if(i==0) + sprintf(cc,"%.3e : >%.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else if(i==19) + sprintf(cc,"<%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else + sprintf(cc,"%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + pDC->TextOut(r.right-182,r.top+16*i+12,cc,(int) strlen(cc)); + } + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView printing + +BOOL CbelaviewView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CbelaviewView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CbelaviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView diagnostics + +#ifdef _DEBUG +void CbelaviewView::AssertValid() const +{ + CView::AssertValid(); +} + +void CbelaviewView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CbelaviewDoc* CbelaviewView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CbelaviewDoc))); + return (CbelaviewDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CbelaviewView message handlers + +void CbelaviewView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CbelaviewDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ((SnapFlag==TRUE) && (EditAction!=2) && (ZoomWndFlag==0)){ + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + // draw box for window zoom; + if(ZoomWndFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + } + + + // update mouse position; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CbelaviewView::OnZoomIn() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + RedrawView(); +} + +void CbelaviewView::OnZoomOut() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + RedrawView(); +} + +void CbelaviewView::OnZoomNatural() +{ + CbelaviewDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else RedrawView(); +} + + +void CbelaviewView::OnKbdZoom() +{ + CbelaviewDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + RedrawView(); +} + +void CbelaviewView::OnSetGrid() +{ + CGridMod pDlg; + CbelaviewDoc *pDoc=GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + RedrawView(); + } +} + +void CbelaviewView::OnSnapGrid() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CbelaviewView::OnShowMesh() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + } + + RedrawView(); +} + + +void CbelaviewView::OnCplot() +{ + CbelaviewDoc *pDoc=GetDocument(); + + bvCCPlotDlg2 dlg; + dlg.m_showa=ShowAr; + dlg.m_showmask=ShowMask; + dlg.m_numcontours=NumContours; + dlg.m_alow=pDoc->A_Low; + dlg.m_ahigh=pDoc->A_High; + dlg.Alb=pDoc->A_lb; + dlg.Aub=pDoc->A_ub; + if(dlg.DoModal()==IDOK){ + ShowAr=dlg.m_showa; + ShowMask=dlg.m_showmask; + pDoc->A_Low=dlg.m_alow; + pDoc->A_High=dlg.m_ahigh; + NumContours=dlg.m_numcontours; + RedrawView(); + } + +} + +void CbelaviewView::OnDplot() +{ + CbelaviewDoc *pDoc=GetDocument(); + int i,k; + + bvCDPlotDlg2 dlg; + + if(!DensityPlot) dlg.m_showit=FALSE; + else dlg.m_showit=TRUE; + dlg.m_showlegend=LegendFlag; + dlg.m_gscale=GreyContours; + dlg.DensityPlot=DensityPlot; + + for(i=0;i<4;i++) + for(k=0;k<2;k++) + { + dlg.PlotBounds[i][k]=pDoc->PlotBounds[i][k]; + dlg.d_PlotBounds[i][k]=pDoc->d_PlotBounds[i][k]; + } + + if(dlg.DoModal()==IDOK){ + if(dlg.m_showit) DensityPlot=dlg.DensityPlot; + else DensityPlot=0; + LegendFlag=dlg.m_showlegend; + GreyContours=dlg.m_gscale; + for(i=0;i<4;i++) + for(k=0;k<2;k++) + pDoc->PlotBounds[i][k]=dlg.PlotBounds[i][k]; + RedrawView(); + } +} + +void CbelaviewView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame"); + else{ + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + Dspl=&MFrm->m_dlgBar; + } + + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); +} + +void CbelaviewView::DisplayPointProperties(double px, double py) +{ + CbelaviewDoc* pDoc = GetDocument(); + CPointVals u; + CComplex Jtot; + if (pDoc->nodelist.GetSize()==0) return; + if(pDoc->GetPointValues(px, py, u)==TRUE) + { + CString outbox,s; + if (pDoc->ProblemType>=0) + { + if (pDoc->ProblemType==0) + { + s.Format("Point: x=%g, y=%g",px,py); + outbox=s; + s.Format("V = %g V",u.V); + outbox+="\r\n"+s; + s.Format("|D| = %g C/m^2",abs(u.D)); + outbox+="\r\n"+s; + s.Format("Dx = %g C/m^2",u.D.re); + outbox+="\r\n"+s; + s.Format("Dy = %g C/m^2",u.D.im); + outbox+="\r\n"+s; + s.Format("|E| = %g V/m",abs(u.E)); + outbox+="\r\n"+s; + s.Format("Ex = %g V/m",u.E.re); + outbox+="\r\n"+s; + s.Format("Ey = %g V/m",u.E.im); + outbox+="\r\n"+s; + s.Format("ex = %g (rel)",u.e.re); + outbox+="\r\n"+s; + s.Format("ey = %g (rel)",u.e.im); + outbox+="\r\n"+s; + s.Format("nrg = %g J/m^3",u.nrg); + outbox+="\r\n"+s; + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + else{ + s.Format("Point: r=%g, z=%g",px,py); + outbox=s; + s.Format("V = %g V",u.V); + outbox+="\r\n"+s; + s.Format("|D| = %g C/m^2",abs(u.D)); + outbox+="\r\n"+s; + s.Format("Dr = %g C/m^2",u.D.re); + outbox+="\r\n"+s; + s.Format("Dz = %g C/m^2",u.D.im); + outbox+="\r\n"+s; + s.Format("|E| = %g V/m",abs(u.E)); + outbox+="\r\n"+s; + s.Format("Er = %g V/m",u.E.re); + outbox+="\r\n"+s; + s.Format("Ez = %g V/m",u.E.im); + outbox+="\r\n"+s; + s.Format("er = %g (rel)",u.e.re); + outbox+="\r\n"+s; + s.Format("ez = %g (rel)",u.e.im); + outbox+="\r\n"+s; + s.Format("nrg = %g J/m^3",u.nrg); + outbox+="\r\n"+s; + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + } +} +} + +void CbelaviewView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonDown(nFlags, point); + return; + } + + int i,j,k,m; + + if (ZoomWndFlag==1) + { + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0) DisplayPointProperties(mx,my); + + if (EditAction==1){ + CbelaviewDoc *pDoc=GetDocument(); + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + DrawUserContour(FALSE); + return; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(y); + DrawUserContour(FALSE); + } + } + } + } + + if (EditAction==2){ + CbelaviewDoc *pDoc=GetDocument(); + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + pDoc->blocklist[pDoc->meshelem[k].lbl].ToggleSelect(); + DrawSelected=pDoc->meshelem[k].lbl; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + + } + + CView::OnLButtonDown(nFlags, point); +} + +void CbelaviewView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag>0){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + RedrawView(); + return; + } + RECT r; + double z,cmag,m[2]; + if (mxcontour.GetSize(); + if(i>0){ + if (z!=pDoc->contour[i-1]) + pDoc->contour.Add(z); + } + else pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(EditAction==2){ + CbelaviewDoc *pDoc=GetDocument(); + int clnode,clseg,claseg,i,j; + double dnode,dseg,daseg,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InConductor; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InConductor; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InConductor; + } + + if (j<0) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + pDoc->bHasMask=FALSE; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InConductor==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InConductor==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InConductor==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (pDoc->meshnode[i].Q==j) + { + pDoc->meshnode[i].IsSelected=1-pDoc->meshnode[i].IsSelected; + } + } + // DrawPSLG(); + RedrawView(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CbelaviewView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CbelaviewView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void CbelaviewView::OnReload() +{ + CbelaviewDoc *pDoc=GetDocument(); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->OnReload(); + if (bLinehook==FALSE) EndWaitCursor(); + if (d_ResetOnReload==FALSE) pDoc->FirstDraw=FALSE; + RedrawView(); + OnViewInfo(); +} + +void CbelaviewView::OnMenuArea() +{ + CbelaviewDoc *pDoc=GetDocument(); + if(EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, TRUE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CbelaviewView::OnMenushowpts() +{ + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(PtsFlag==FALSE){ + PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + } + else{ + PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + } + RedrawView(); +} + +void CbelaviewView::OnMenuContour() +{ + CbelaviewDoc *pDoc=GetDocument(); + + if(EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + + RedrawView(); + } + + EditAction=1; + + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, TRUE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CbelaviewView::OnMenuPoint() +{ + CbelaviewDoc *pDoc=GetDocument(); + + if (EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + if (EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + RedrawView(); + } + + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_BV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, TRUE); + +} + +void CbelaviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CbelaviewDoc *pDoc=GetDocument(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if ((nChar==VK_TAB) && (EditAction!=2)) EnterPoint(); + + if ((nChar==VK_DELETE) && (EditAction==1)){ + int k; + k=(int) pDoc->contour.GetSize(); + + if(k>1){ + EraseUserContour(FALSE); + pDoc->contour.RemoveAt(k-1); + DrawUserContour(TRUE); + } + else if(k!=0){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAt(0); + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==1)){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + + if ((nChar==VK_SHIFT) && (EditAction==1)){ + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==2)){ + UnselectAll(); + RedrawView(); + } + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CbelaviewView::UnselectAll() +{ + CbelaviewDoc *pDoc=GetDocument(); + int i; + + pDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) pDoc->blocklist[i].IsSelected=FALSE; + for(i=0;imeshnode.GetSize();i++) pDoc->meshnode[i].IsSelected=FALSE; + for(i=0;inodelist.GetSize();i++) pDoc->nodelist[i].IsSelected=FALSE; + for(i=0;ilinelist.GetSize();i++) pDoc->linelist[i].IsSelected=FALSE; + for(i=0;iarclist.GetSize();i++) pDoc->arclist[i].IsSelected=FALSE; +} + +void CbelaviewView::EnterPoint() +{ + CEnterPt pDlg; + double x,y,t; + CbelaviewDoc* pDoc = GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + if (EditAction==0) DisplayPointProperties(x,y); + if (EditAction==1){ + CComplex z; + z.Set(x,y); + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + } +} + +void CbelaviewView::SpecialLine(CDC *pDC, int X0, int Y0, int X1, int Y1, int flag) +{ + double l; + int i,j,k,p,x,y,z; + int hi,lo,zj; + BOOL InLine,DrawIt; + COLORREF c; + COLORREF Red; + RECT r; + + GetClientRect(&r); + Red=SelColor; + + int x0,y0,x1,y1,xb,yb; + + x0=X0; y0=Y0; + x1=X1; y1=Y1; + xb=r.right; + yb=r.bottom; + DrawIt=TRUE; + + // test to see if any of the endpoints are offscreen. + // if they are, crop them to the screen size + if ((x0<0) || (x0>xb) || (x1<0) || (x1>xb) || + (y0<0) || (y0>yb) || (y1<0) || (y1>yb)) + { + DrawIt=FALSE; + double z,dx0,dx1,dy0,dy1,dxb,dyb; + dx0=(double) x0; + dy0=(double) y0; + dx1=(double) x1; + dy1=(double) y1; + dxb=(double) xb; + dyb=(double) yb; + + + if ((x1-x0)!=0) + { + // test left side; + z=(-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0<0) + { + dx0=0; + x0=0; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=0; + x1=0; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + // test right side; + z=(dxb-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0>xb) + { + dx0=dxb; + x0=xb; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=dxb; + x1=xb; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + } + + if ((y1-y0)!=0) + { + // test top side; + z=(-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0<0) + { + dy0=0; + y0=0; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=0; + y1=0; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + + // test bottom side; + z=(dyb-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0>dyb) + { + dy0=dyb; + y0=yb; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=dyb; + y1=yb; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + } + } + + if(!DrawIt) return; + + l=(double)((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + l=sqrt(l); + k=(int) l; + for(i=0;i<=k;i++) + { + if(k!=0){ + x=x0+((x1-x0)*i)/k; + y=y0+((y1-y0)*i)/k; + } + else{ + x=x0; + y=y0; + } + + z=x+y*r.right; + + // check if this point is already in the line + // in the case that a red line is supposed to be drawn; + + if(flag==FALSE) + { + // bisection search to see if the pixel under + // consideration is already in LinePix + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj) InLine=TRUE; + } + zj=LinePix[hi].z; + if(z>=zj){ + hi+=1; + lo=hi; + if(z==zj) InLine=TRUE; + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + break; + } + else if(zjGetPixel(x,y); + if (hi==(int) LinePix.GetSize()) LinePix.Add(NewPixel); + else LinePix.InsertAt(hi,NewPixel); + } + } + + // if line is to be erased, get entry out of the pixel list + if(flag!=FALSE){ + // bisection search to find the pixel + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj){ + InLine=TRUE; + p=0; + } + } + zj=LinePix[hi].z; + if(z>=zj){ + lo=hi; + if(z==zj){ + InLine=TRUE; + p=hi; + } + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + p=j; + break; + } + else if(zjPtVisible(x,y)!=FALSE) + { + if(flag==FALSE) pDC->SetPixel(x,y,Red); + else if(InLine==TRUE) pDC->SetPixel(x,y,c); + } + } + +} + + +void CbelaviewView::OnMenuPlot() +{ + bvCXYPlotDlg dlg; + CbelaviewDoc *pDoc=GetDocument(); + int PlotType,npoints,FileFormat; + BOOL ToFile; + + if ((EditAction!=1) || (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot create a plot;\nNo contour has been defined"); + return; + } + + dlg.m_npoints=d_PlotPoints; + if (dlg.DoModal()==IDOK){ + PlotType=dlg.XYPlotType; + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + CXYPlot xyplot; + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->GetLineValues(xyplot,PlotType,npoints); + if (bLinehook==FALSE) EndWaitCursor(); + if(ToFile==FALSE){ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else xyplot.ToDisk(FileFormat); + } +} + +void CbelaviewView::OnMenuIntegrate() +{ + CbelaviewDoc *pDoc=GetDocument(); + int inttype; + + if (EditAction==0){ + MsgBox("Cannot integrate;\nNo contour or area\nhas been defined."); + return; + } + + if ((EditAction==1) && (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot integrate;\nNo contour has been defined"); + return; + } + + if (EditAction==2){ + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + for(i=0;imeshnode.GetSize();i++) + if (pDoc->meshnode[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE){ + MsgBox("Cannot integrate;\nNo area has been selected"); + return; + } + } + + if(EditAction==1){ + bvCLIntDlg dlg; + int inttype; + double z[4]; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.linttype; + char s[512]; + switch(inttype) + { + case 0: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Voltage drop = %g Volts",Re(z[0])); + MyMessageBox(s); + break; + + case 1: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + sprintf(s,"Electric Flux = %g Coulombs\nAverage D.n = %g C/m^2",z[0],z[1]); + MyMessageBox(s); + break; + + case 2: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Contour length = %g meters\nSurface Area = %g meter^2",z[0],z[1]); + MyMessageBox(s); + break; + case 3: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if (pDoc->ProblemType==0) + sprintf(s,"Force in x-direction = %g N\nForce in y-direction = %g N\n",z[0],z[1]); + else sprintf(s,"Force in z-direction = %g N",z[1]); + MyMessageBox(s); + break; + + case 4: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if (pDoc->ProblemType==0) + sprintf(s,"Torque about (0,0) = %g N*m",z[0]); + else sprintf(s,"No net torque in axisymmetric case."); + MyMessageBox(s); + break; + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + } + } + + if(EditAction==2){ + bvCBlockInt dlg; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.binttype; + CComplex z; + char s[512]; + + switch(inttype) + { + case 0: + z=pDoc->BlockIntegral(0); + sprintf(s,"%g Joules",Re(z)); + break; + + case 1: + z=pDoc->BlockIntegral(1); + sprintf(s,"%g meter^2",Re(z)); + break; + + case 2: + z=pDoc->BlockIntegral(2); + sprintf(s,"%g meter^3",Re(z)); + break; + + case 3: + z=pDoc->BlockIntegral(3); + if (pDoc->ProblemType==PLANAR) + sprintf(s,"Dx = %g C/m^2\nDy = %g C/m^2",Re(z),Im(z)); + else + sprintf(s,"Dr = %g C/m^2\nDz = %g C/m^2",Re(z),Im(z)); + break; + + case 4: + z=pDoc->BlockIntegral(4); + if (pDoc->ProblemType==PLANAR) + sprintf(s,"Ex = %g V/m\nEy = %g V/m",Re(z),Im(z)); + else + sprintf(s,"Er = %g V/m\nEz = %g V/m",Re(z),Im(z)); + break; + + // Henrotte Force + case 5: + if (!pDoc->MakeMask()) return; + z=pDoc->BlockIntegral(5); + + if(pDoc->ProblemType==0) + sprintf(s,"x-component: %e N\ny-component: %e N",Re(z),Im(z)); + if(pDoc->ProblemType==1) + sprintf(s,"r-component: %e N\nz-component: %e N",0.,Im(z)); + + if (ShowMask) InvalidateRect(NULL); + break; + + // Henrotte Torque + case 6: + if(pDoc->ProblemType==1){ + sprintf(s,"No torque possible in axisymmetric case"); + break; + } + if(!pDoc->MakeMask()) return; + z=pDoc->BlockIntegral(6); + sprintf(s,"Torque about (0,0): %e N*m",Re(z)); + if (ShowMask) InvalidateRect(NULL); + break; + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + MyMessageBox(s); + } + + } +} + + + +void CbelaviewView::OnSmooth() +{ + CbelaviewDoc *pDoc=GetDocument(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if (pDoc->Smooth==TRUE){ + pDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + } + else{ + pDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + RedrawView(); +} + +BOOL CbelaviewView::OnEraseBkgnd(CDC* pDC) +{ + + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + return TRUE; + +} + +void CbelaviewView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + CbelaviewDoc *pDoc=GetDocument(); + + if(EditAction==0){ + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + sprintf(s,"Closest input node:\n(%g,%g)",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + AfxMessageBox(s,MB_ICONINFORMATION); + } + } + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + CView::OnRButtonDblClk(nFlags, point); +} + + + + +void CbelaviewView::OnPanDown() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy-=0.25*y/mag; + + RedrawView(); +} + +void CbelaviewView::OnPanLeft() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; + + RedrawView(); +} + +void CbelaviewView::OnPanRight() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; + + RedrawView(); +} + +void CbelaviewView::OnPanUp() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy+=0.25*y/mag; + + RedrawView(); +} + +void CbelaviewView::OnViewCircprops() +{ + bvCCircDlg dlg; + + dlg.TheDoc=GetDocument(); + dlg.DoModal(); + +} + +void CbelaviewView::RedrawView() +{ + LinePix.RemoveAll(); + InvalidateRect(NULL); +} + +BOOL CbelaviewView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"belaview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + VectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowNames); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +BOOL CbelaviewView::WritePreferences() +{ + FILE *fp; + CString fname; + CbelaviewDoc *pDoc=GetDocument(); + + fname=BinDir+"belaview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorColor", VectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",d_EditAction); + fprintf(fp," = %i\n",d_DensityPlot); + fprintf(fp," = %i\n",d_VectorPlot); + fprintf(fp," = %i\n",d_GridFlag); + fprintf(fp," = %i\n",d_SnapFlag); + fprintf(fp," = %i\n",d_MeshFlag); + fprintf(fp," = %i\n",d_LegendFlag); + fprintf(fp," = %i\n",d_NumContours); + fprintf(fp," = %i\n",d_ShowAr); + fprintf(fp," = %i\n",d_ShowMask); + fprintf(fp," = %i\n",d_GreyContours); + fprintf(fp," = %i\n",d_PtsFlag); + fprintf(fp," = %i\n",d_ResetOnReload); + fprintf(fp," = %i\n",d_Smooth); + fprintf(fp," = %i\n",d_PlotPoints); + fprintf(fp," = %i\n",d_ShowNames); + fprintf(fp," = %i\n", + pDoc->d_LineIntegralPoints); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void CbelaviewView::CheckIt() +{ + // make sure all of the right things are checked + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar1,*pToolBar2; + pToolBar1=&MFrm->m_BV_toolBar1; + pToolBar2=&MFrm->m_leftbar; + CToolBarCtrl *tc1=&pToolBar1->GetToolBarCtrl(); + CToolBarCtrl *tc2=&pToolBar2->GetToolBarCtrl(); + + if(SnapFlag==FALSE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc2->PressButton(ID_SNAP_GRID,TRUE); + } + + + if(GridFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc2->PressButton(ID_SHOW_GRID,TRUE); + } + + if(MeshFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc1->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc1->PressButton(ID_SHOW_MESH,TRUE); + } + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc1->PressButton(ID_MENU_AREA, FALSE); + tc1->PressButton(ID_MENU_CONTOUR, FALSE); + tc1->PressButton(ID_MENU_POINT,FALSE); + + if (EditAction==2){ + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + tc1->PressButton(ID_MENU_AREA, TRUE); + } + if (EditAction==1){ + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + tc1->PressButton(ID_MENU_CONTOUR, TRUE); + } + if (EditAction==0){ + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc1->PressButton(ID_MENU_POINT,TRUE); + } + + if(PtsFlag==TRUE) + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + CbelaviewDoc *pDoc=GetDocument(); + if (pDoc->Smooth==FALSE) + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + + if (ShowNames==FALSE) + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_CHECKED); + + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + +} + +void CbelaviewView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + CbelaviewDoc *pDoc=GetDocument(); + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if(EditAction==2) + { + int i,k,grp,sel; + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + grp=pDoc->blocklist[pDoc->meshelem[k].lbl].InGroup; + sel=pDoc->blocklist[pDoc->meshelem[k].lbl].IsSelected; + for(i=0;iblocklist.GetSize();i++) + if ((pDoc->blocklist[i].InGroup==grp) && + (pDoc->blocklist[i].IsSelected!=sel)) + { + pDoc->blocklist[i].IsSelected=sel; + DrawSelected=i; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + } + } + + CView::OnLButtonDblClk(nFlags, point); +} + + + +void CbelaviewView::OnViewInfo() +{ + CbelaviewDoc *pDoc=GetDocument(); + CString s,z,outbox; + + // first line; + outbox.Format("Title: %s\r\n",pDoc->GetTitle()); + + // second line; + switch(pDoc->LengthUnits){ + case 0: + s="Length Units: Inches"; + z=" in"; + break; + case 1: + s="Length Units: Millimeters"; + z=" mm"; + break; + case 2: + s="Length Units: Centimeters"; + z=" cm"; + break; + case 4: + s="Length Units: Mils"; + z=" mil"; + break; + case 5: + s="Length Units: Micrometers"; + z=" um"; + break; + default: + s="Length Units: Meters"; + z=" m"; + break; + } + outbox+="\r\n" + s; + + // third line + if(pDoc->ProblemType==TRUE) s="Axisymmetric Solution"; + else{ + s.Format("2-D Planar (Depth: %g", + pDoc->Depth/pDoc->LengthConv[pDoc->LengthUnits]); + s=s+z+")"; + } + outbox+="\r\n" + s; + + // fourth line + s.Format(""); + outbox+="\r\n" + s; + + // fifth line + s.Format(""); + outbox+="\r\n" + s; + + // sixth line + s.Format("%i Nodes",pDoc->meshnode.GetSize()); + outbox+="\r\n" + s; + + // seventh line + s.Format("%i Elements",pDoc->meshelem.GetSize()); + outbox+="\r\n" + s; + + // display it + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; +} + +void CbelaviewView::OnViewShowblocknames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + RedrawView(); +} + +void CbelaviewView::OnVplot() +{ + // TODO: Add your command handler code here + bvCVPlotDlg dlg; + + dlg.m_vectorscalefactor=VectorScaleFactor; + dlg.m_plottype=VectorPlot; + if(dlg.DoModal()==IDOK) + { + VectorScaleFactor=dlg.m_vectorscalefactor; + VectorPlot=dlg.m_plottype; + InvalidateRect(NULL); + } +} + +void CbelaviewView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CbelaviewView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +BOOL CbelaviewView::IsMinimized() +{ + CChildFrame *pChildFrm = (CChildFrame *)GetParentFrame(); + if (pChildFrm->GetStyle() & WS_MINIMIZE) return TRUE; return FALSE; +} + +void CbelaviewView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if((bActivate) && (pActivateView==this)) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(4); + CheckIt(); + } + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CbelaviewView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CbelaviewView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + // The child frame makes a special effort to pass down the + // WM_SIZE message when a window is minimized. The view + // uses this message to minimize the output window, if it is visible. + if(nType==SIZE_MINIMIZED) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if(MFrm->m_dlgBar.GetStyle() & WS_VISIBLE) MFrm->m_dlgBar.ShowWindow(SW_HIDE); + } + + if((nType==SIZE_MAXIMIZED) || (nType==SIZE_RESTORED)) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + +} diff --git a/femm/belaviewView.h b/femm/belaviewView.h new file mode 100644 index 0000000..9910107 --- /dev/null +++ b/femm/belaviewView.h @@ -0,0 +1,230 @@ +// belaviewView.h : interface of the CbelaviewView class +// +///////////////////////////////////////////////////////////////////////////// + +class CbelaviewView : public CView +{ +protected: // create from serialization only + CbelaviewView(); + DECLARE_DYNCREATE(CbelaviewView) + +// Attributes +public: + + CbelaviewDoc* GetDocument(); + + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void EnterPoint(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL LegendFlag; + BOOL GreyContours; + BOOL PtsFlag; + BOOL Coords; // False=Cartesian; True=Polar + BOOL ShowNames; + double VectorScaleFactor; + int ZoomWndFlag; + int DrawSelected; + double wzx,wzy; + +// default behaviors + int d_EditAction; + BOOL d_GridFlag; + BOOL d_SnapFlag; + BOOL d_MeshFlag; + BOOL d_LegendFlag; + BOOL d_GreyContours; + int d_NumContours; + BOOL d_ShowAr; + BOOL d_ShowMask; + int d_DensityPlot; + int d_VectorPlot; + BOOL d_PtsFlag; + BOOL d_ResetOnReload; + BOOL d_Smooth; + BOOL d_PlotPoints; + BOOL d_ShowNames; + + COutBox *Dspl; + CString BinDir; // pathname for triangle.exe + + int NumContours; + BOOL ShowAr,ShowMask; + int DensityPlot; + int VectorPlot; + CString OutputWindowText; + + CArray< CPixel, CPixel& > LinePix; + CArray< CZPix, CZPix& > ZoomPix; + + // Greyscale Density Plot Colormap + COLORREF Grey00; + COLORREF Grey01; + COLORREF Grey02; + COLORREF Grey03; + COLORREF Grey04; + COLORREF Grey05; + COLORREF Grey06; + COLORREF Grey07; + COLORREF Grey08; + COLORREF Grey09; + COLORREF Grey10; + COLORREF Grey11; + COLORREF Grey12; + COLORREF Grey13; + COLORREF Grey14; + COLORREF Grey15; + COLORREF Grey16; + COLORREF Grey17; + COLORREF Grey18; + COLORREF Grey19; + + // Density Plot Colormap + COLORREF Color00; + COLORREF Color01; + COLORREF Color02; + COLORREF Color03; + COLORREF Color04; + COLORREF Color05; + COLORREF Color06; + COLORREF Color07; + COLORREF Color08; + COLORREF Color09; + COLORREF Color10; + COLORREF Color11; + COLORREF Color12; + COLORREF Color13; + COLORREF Color14; + COLORREF Color15; + COLORREF Color16; + COLORREF Color17; + COLORREF Color18; + COLORREF Color19; + + // Other colors + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF RegionColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF TextColor; + COLORREF NodeColor; + COLORREF RealFluxLineColor; + COLORREF NameColor; + COLORREF MaskLineColor; + COLORREF VectorColor; + +// Operations +public: + + void DoContours(CDC *pDC, int *p, int side, int Aflag); + void PlotFluxDensity(CDC *pDC,int elmnum,int flag); + void DisplayPointProperties(double px, double py); + void DrawUserContour(BOOL flag); + void EraseUserContour(BOOL flag); + void SpecialLine(CDC *pDC, int x0, int y0, int x1, int y1, BOOL flag); + void PlotSelectedElm(CDC *pDC,belaviewtype::CElement &elm); + void RedrawView(); + void UnselectAll(); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL IsMinimized(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void CheckIt(); + void LuaViewInfo(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CbelaviewView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CbelaviewView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CbelaviewView) + afx_msg void OnSmooth(); + afx_msg void OnZoomIn(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnCplot(); + afx_msg void OnDplot(); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomOut(); + afx_msg void OnZoomWindow(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnEditCopy(); + afx_msg void OnReload(); + afx_msg void OnMenuArea(); + afx_msg void OnMenuContour(); + afx_msg void OnMenuPoint(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMenuPlot(); + afx_msg void OnMenuIntegrate(); + afx_msg void OnMenushowpts(); + afx_msg void OnKbdZoom(); + afx_msg void Onintegral(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnHelpFinder(); + afx_msg void OnViewCircprops(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnHelpLicense(); + afx_msg void OnViewInfo(); + afx_msg void OnViewShowblocknames(); + afx_msg void OnVplot(); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); +}; + +#ifndef _DEBUG // debug version in belaviewView.cpp +inline CbelaviewDoc* CbelaviewView::GetDocument() + { return (CbelaviewDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + + diff --git a/femm/bhplot.cpp b/femm/bhplot.cpp new file mode 100644 index 0000000..906fb9c --- /dev/null +++ b/femm/bhplot.cpp @@ -0,0 +1,266 @@ +#include "stdafx.h" +#include "bhplot.h" + +CBHPlot::CBHPlot() +{ + NumRows=0; + NumCols=0; + NumPts=0; + M=NULL; + lbls=NULL; + Pts=NULL; + +} + +CBHPlot::~CBHPlot() +{ + if (NumRows==0) return; + + int i; + for(i=0;iHiY) HiY=M[i][j]; + if (M[i][j]SelectObject( &PlotPen ); + pDC->MoveTo(0,0); + pDC->LineTo(588,0); + pDC->LineTo(588,343); + pDC->LineTo(0,343); + pDC->LineTo(0,0); + + pDC->MoveTo((int) OffsetX,(int) OffsetY); + pDC->LineTo((int) OffsetX,(int) (OffsetY+Height)); + pDC->LineTo((int) (OffsetX+Width),(int) (OffsetY+Height)); + pDC->SelectObject(pOldPen); + PlotPen.DeleteObject(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(12,0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + // draw those suckers... + PlotPen.CreatePen(PS_SOLID,1,PenCols[1]); + pOldPen=pDC->SelectObject( &PlotPen ); + for(i=0;iMoveTo( (int)Pts[i].re-2, (int)Pts[i].im-2); + pDC->LineTo( (int)Pts[i].re-2, (int)Pts[i].im+2); + pDC->LineTo( (int)Pts[i].re+2, (int)Pts[i].im+2); + pDC->LineTo( (int)Pts[i].re+2, (int)Pts[i].im-2); + pDC->LineTo( (int)Pts[i].re-2, (int)Pts[i].im-2); + } + pDC->SelectObject(pOldPen); + PlotPen.DeleteObject(); + + for(i=1;iSelectObject( &PlotPen ); + pDC->MoveTo((int)M[0][0],(int)M[0][i]); + for(j=0;jLineTo((int)M[j][0],(int)M[j][i]); + pDC->SetTextColor(PenCols[i-1]); + pDC->TextOut((int)(OffsetX+Width+10.),((int) OffsetY)+14*i,lbls[i],(int) strlen(lbls[i])); + pDC->SelectObject(pOldPen); PlotPen.DeleteObject(); + } + pDC->SetTextColor(0x00000000); + pDC->TextOut(200,(int) (OffsetY+Height+30),lbls[0],(int) strlen(lbls[0])); + k=(int)((HiY-LoY)/dy + 0.5); + if(k<4){ + k*=2; + dy/=2.; + } + if(k==0) k++; + pDC->SetTextAlign(TA_RIGHT); + for(i=0;i<=k;i++){ + pDC->MoveTo((int) OffsetX,(i*(int)Height)/k +(int) OffsetY); + pDC->LineTo((int) OffsetX-5,(i*(int) Height)/k+ (int) OffsetY); + sprintf(s,"%.4g",HiY-((double) i)*dy); + pDC->TextOut(((int) OffsetX)-10,(i*(int)Height)/k +(int) OffsetY-6,s,(int) strlen(s)); + } + k=(int)((HiX-LoX)/dx); + if((k<4) && (!logscale)){ + dx/=2.; + k=(int)((HiX-LoX)/dx); + } + d=( ((double) Width) * dx/ (HiX-LoX)); + pDC->SetTextAlign(TA_CENTER); + for(i=0;i<=k;i++){ + pDC->MoveTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height)); + pDC->LineTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height)+5); + if(logscale) sprintf(s,"%g",pow((double)10,LoX+((double) i)*dx)); + else sprintf(s,"%.0f",LoX+((double) i)*dx); + pDC->TextOut((int)(((double) i)*d + OffsetX),(int) OffsetY+(int)Height+10,s,(int) strlen(s)); + } + pDC->SetTextAlign(TA_LEFT); + + + pDC->SelectObject(pOldFont); +} + +BOOL CBHPlot::ToDisk() +{ + FILE *fp; + int i,j; + CString dest_name; + + if((NumCols==0) || (NumRows==0)){ + MsgBox("No data to write to disk."); + return FALSE; + } + + CFileDialog *fname_dia=new CFileDialog( + FALSE, + "txt | * ", + dest_name, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Text Files (*.txt) | *.txt; *.TXT | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return FALSE; + } + + dest_name=fname_dia->GetPathName(); + + delete[] fname_dia; + + if((fp=fopen(dest_name,"wt"))!=NULL){ + for(i=0;i +#include "bv_problem.h" +#include "xyplot.h" +#include "belaviewdoc.h" +#include "bv_CircDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCCircDlg dialog + + +bvCCircDlg::bvCCircDlg(CWnd* pParent /*=NULL*/) + : CDialog(bvCCircDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCCircDlg) + //}}AFX_DATA_INIT +} + + +void bvCCircDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCCircDlg) + DDX_Control(pDX, IDC_BV_CIRCNAME, m_circname); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(bvCCircDlg, CDialog) + //{{AFX_MSG_MAP(bvCCircDlg) + ON_CBN_SELCHANGE(IDC_BV_CIRCNAME, OnSelchangeCircname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCCircDlg message handlers +////////////////////////////////////////////////////// +void bvCCircDlg::OnSelchangeCircname() +{ + if(NumCircuits==0) return; + + int k; + CString crslt; + + k=m_circname.GetCurSel(); + crslt.Format("Voltage = %g Volts\r\nCharge = %g Coulombs", + TheDoc->circproplist[k].V,TheDoc->circproplist[k].q); + SetDlgItemText(IDC_BV_CIRCRESULT,crslt); + +} + +BOOL bvCCircDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName); + + if(NumCircuits!=0){ + m_circname.SetCurSel(0); + OnSelchangeCircname(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/bv_CircDlg.h b/femm/bv_CircDlg.h new file mode 100644 index 0000000..850262a --- /dev/null +++ b/femm/bv_CircDlg.h @@ -0,0 +1,39 @@ +// CircDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCCircDlg dialog + +class bvCCircDlg : public CDialog +{ +// Construction +public: + bvCCircDlg(CWnd* pParent = NULL); // standard constructor + + CbelaviewDoc *TheDoc; + int NumCircuits; + +// Dialog Data + //{{AFX_DATA(bvCCircDlg) + enum { IDD = IDD_BV_CIRCPROPS }; + CComboBox m_circname; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCCircDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCCircDlg) + afx_msg void OnSelchangeCircname(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/bv_CplotDlg2.cpp b/femm/bv_CplotDlg2.cpp new file mode 100644 index 0000000..e3a8acd --- /dev/null +++ b/femm/bv_CplotDlg2.cpp @@ -0,0 +1,65 @@ +// CplotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bv_CplotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCCPlotDlg2 dialog + + +bvCCPlotDlg2::bvCCPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(bvCCPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCCPlotDlg2) + m_numcontours = 0; + m_showa = FALSE; + m_ahigh = 0.0; + m_alow = 0.0; + m_showmask = FALSE; + //}}AFX_DATA_INIT +} + + +void bvCCPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCCPlotDlg2) + DDX_Text(pDX, IDC_BV_NUMCONTOURS, m_numcontours); + DDV_MinMaxInt(pDX, m_numcontours, 4, 999); + DDX_Check(pDX, IDC_BV_SHOW_A, m_showa); + DDX_Text(pDX, IDC_BV_AHIGH, m_ahigh); + DDX_Text(pDX, IDC_BV_ALOW, m_alow); + DDX_Check(pDX, IDC_BV_SHOW_MASK2, m_showmask); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BV_NUMCONTOURS, m_IDC_numcontours); + DDX_Control(pDX, IDC_BV_AHIGH, m_IDC_ahigh); + DDX_Control(pDX, IDC_BV_ALOW, m_IDC_alow); +} + + +BEGIN_MESSAGE_MAP(bvCCPlotDlg2, CDialog) + //{{AFX_MSG_MAP(bvCCPlotDlg2) + ON_BN_CLICKED(IDC_BV_DFLT1, OnDflt1) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCCPlotDlg2 message handlers + +void bvCCPlotDlg2::OnDflt1() +{ + // TODO: Add your control notification handler code here + UpdateData(TRUE); + m_alow=Alb; + m_ahigh=Aub; + m_numcontours=19; + UpdateData(FALSE); +} diff --git a/femm/bv_CplotDlg2.h b/femm/bv_CplotDlg2.h new file mode 100644 index 0000000..03b281c --- /dev/null +++ b/femm/bv_CplotDlg2.h @@ -0,0 +1,42 @@ +// bv_CplotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCCPlotDlg2 dialog + +class bvCCPlotDlg2 : public CDialog +{ +// Construction +public: + bvCCPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Alb,Aub; + +// Dialog Data + //{{AFX_DATA(bvCCPlotDlg2) + enum { IDD = IDD_BV_CPLOTDLG2 }; + int m_numcontours; + BOOL m_showa; + double m_ahigh; + double m_alow; + BOOL m_showmask; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCCPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCCPlotDlg2) + afx_msg void OnDflt1(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_numcontours, m_IDC_ahigh, m_IDC_alow; +}; diff --git a/femm/bv_DPlotDlg2.cpp b/femm/bv_DPlotDlg2.cpp new file mode 100644 index 0000000..f4d44cf --- /dev/null +++ b/femm/bv_DPlotDlg2.cpp @@ -0,0 +1,99 @@ +// DPlotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bv_DPlotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCDPlotDlg2 dialog + + +bvCDPlotDlg2::bvCDPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(bvCDPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCDPlotDlg2) + m_showit = FALSE; + m_showlegend = FALSE; + m_lb2 = 0.0; + m_ub2 = 0.0; + m_gscale = FALSE; + //}}AFX_DATA_INIT +} + + +void bvCDPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCDPlotDlg2) + DDX_Control(pDX, IDC_BV_DPLOTTYPE, m_dplottype); + DDX_Check(pDX, IDC_BV_SHOWIT, m_showit); + DDX_Check(pDX, IDC_BV_SHOW_LEG2, m_showlegend); + DDX_Text(pDX, IDC_BV_LB2, m_lb2); + DDX_Text(pDX, IDC_BV_UB2, m_ub2); + DDX_Check(pDX, IDC_BV_GSCALE2, m_gscale); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BV_LB2, m_IDC_lb2); + DDX_Control(pDX, IDC_BV_UB2, m_IDC_ub2); +} + + +BEGIN_MESSAGE_MAP(bvCDPlotDlg2, CDialog) + //{{AFX_MSG_MAP(bvCDPlotDlg2) + ON_BN_CLICKED(IDC_BV_RESBTN2, OnResbtn2) + ON_CBN_SELCHANGE(IDC_BV_DPLOTTYPE, OnSelchangeDplottype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCDPlotDlg2 message handlers + +void bvCDPlotDlg2::OnResbtn2() +{ + // TODO: Add your control notification handler code here + UpdateData(); + m_ub2=d_PlotBounds[DensityPlot][1]; + m_lb2=d_PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} + +BOOL bvCDPlotDlg2::OnInitDialog() +{ + CDialog::OnInitDialog(); + + DensityPlot--; + if(DensityPlot<0) DensityPlot=0; + m_dplottype.SetCurSel(DensityPlot); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bvCDPlotDlg2::OnOK() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot++; + CDialog::OnOK(); +} + +void bvCDPlotDlg2::OnSelchangeDplottype() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot=m_dplottype.GetCurSel(); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} diff --git a/femm/bv_DPlotDlg2.h b/femm/bv_DPlotDlg2.h new file mode 100644 index 0000000..52e4d5b --- /dev/null +++ b/femm/bv_DPlotDlg2.h @@ -0,0 +1,49 @@ +// DPlotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCDPlotDlg2 dialog + +class bvCDPlotDlg2 : public CDialog +{ +// Construction +public: + bvCDPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Bm_l, Bm_h; + double d_PlotBounds[4][2]; + double PlotBounds[4][2]; + int DensityPlot; + +// Dialog Data + //{{AFX_DATA(bvCDPlotDlg2) + enum { IDD = IDD_BV_DPLOTDLG2 }; + CComboBox m_dplottype; + BOOL m_showit; + BOOL m_showlegend; + double m_lb2; + double m_ub2; + BOOL m_gscale; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCDPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCDPlotDlg2) + afx_msg void OnResbtn2(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeDplottype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_lb2, m_IDC_ub2; +}; diff --git a/femm/bv_LIntDlg.cpp b/femm/bv_LIntDlg.cpp new file mode 100644 index 0000000..56569d2 --- /dev/null +++ b/femm/bv_LIntDlg.cpp @@ -0,0 +1,59 @@ +// LIntDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bv_LIntDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCLIntDlg dialog + + +bvCLIntDlg::bvCLIntDlg(CWnd* pParent /*=NULL*/) + : CDialog(bvCLIntDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCLIntDlg) + //}}AFX_DATA_INIT +} + + +void bvCLIntDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCLIntDlg) + DDX_Control(pDX, IDC_BV_LINTTYPE, m_inttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(bvCLIntDlg, CDialog) + //{{AFX_MSG_MAP(bvCLIntDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCLIntDlg message handlers + +BOOL bvCLIntDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_inttype.SetCurSel(0); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bvCLIntDlg::OnOK() +{ + // TODO: Add extra validation here + linttype=m_inttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/bv_LIntDlg.h b/femm/bv_LIntDlg.h new file mode 100644 index 0000000..c33256c --- /dev/null +++ b/femm/bv_LIntDlg.h @@ -0,0 +1,38 @@ +// LIntDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCLIntDlg dialog + +class bvCLIntDlg : public CDialog +{ +// Construction +public: + bvCLIntDlg(CWnd* pParent = NULL); // standard constructor + + int linttype; + +// Dialog Data + //{{AFX_DATA(bvCLIntDlg) + enum { IDD = IDD_BV_LINEINT }; + CComboBox m_inttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCLIntDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCLIntDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/bv_Pref.cpp b/femm/bv_Pref.cpp new file mode 100644 index 0000000..e37fdf5 --- /dev/null +++ b/femm/bv_Pref.cpp @@ -0,0 +1,982 @@ +// Pref.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bv_Pref.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + #define SelColor clist[0] + #define BackColor clist[1] + #define MeshColor clist[2] + #define BlockColor clist[3] + #define LineColor clist[4] + #define GridColor clist[5] + #define NodeColor clist[6] + #define RegionColor clist[7] + #define TextColor clist[8] + #define RealFluxLineColor clist[9] + #define NameColor clist[10] + #define MaskLineColor clist[11] + #define VectorColor clist[12] + #define Color00 clist[13] + #define Color01 clist[14] + #define Color02 clist[15] + #define Color03 clist[16] + #define Color04 clist[17] + #define Color05 clist[18] + #define Color06 clist[19] + #define Color07 clist[20] + #define Color08 clist[21] + #define Color09 clist[22] + #define Color10 clist[23] + #define Color11 clist[24] + #define Color12 clist[25] + #define Color13 clist[26] + #define Color14 clist[27] + #define Color15 clist[28] + #define Color16 clist[29] + #define Color17 clist[30] + #define Color18 clist[31] + #define Color19 clist[32] + #define Grey00 clist[33] + #define Grey01 clist[34] + #define Grey02 clist[35] + #define Grey03 clist[36] + #define Grey04 clist[37] + #define Grey05 clist[38] + #define Grey06 clist[39] + #define Grey07 clist[40] + #define Grey08 clist[41] + #define Grey09 clist[42] + #define Grey10 clist[43] + #define Grey11 clist[44] + #define Grey12 clist[45] + #define Grey13 clist[46] + #define Grey14 clist[47] + #define Grey15 clist[48] + #define Grey16 clist[49] + #define Grey17 clist[50] + #define Grey18 clist[51] + #define Grey19 clist[52] + + + +///////////////////////////////////////////////////////////////////////////// +// bvCPref dialog + + +bvCPref::bvCPref(CWnd* pParent /*=NULL*/) + : CDialog(bvCPref::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCPref) + m_d_GreyContours = FALSE; + m_d_LegendFlag = TRUE; + m_d_NumContours = 19; + m_d_ResetOnReload = FALSE; + m_d_GridFlag = FALSE; + m_d_ShowAr = FALSE; + m_d_PtsFlag = TRUE; + m_d_MeshFlag = FALSE; + m_d_SnapFlag = FALSE; + m_d_Smooth = TRUE; + m_d_LineIntegralPoints = 400; + m_d_PlotPoints = 1500; + m_d_ShowMask = FALSE; + m_d_shownames = TRUE; + //}}AFX_DATA_INIT + + m_d_DensityPlot=1; + m_d_EditAction=0; + m_d_VectorPlot=0; + + clist=(COLORREF *)calloc(64,sizeof(COLORREF)); + int i=0; + + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + +} + +bvCPref::~bvCPref() +{ + free(clist); +} + +void bvCPref::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCPref) + DDX_Control(pDX, IDC_BV_VECTORPLOT, m_d_vplotlist); + DDX_Control(pDX, IDC_BV_DENSITYPLOT, m_d_dplotlist); + DDX_Control(pDX, IDC_BV_EDITACTION, m_d_editlist); + DDX_Control(pDX, IDC_BV_COLORS, m_d_color); + DDX_Check(pDX, IDC_BV_GREY, m_d_GreyContours); + DDX_Check(pDX, IDC_BV_LEGEND, m_d_LegendFlag); + DDX_Text(pDX, IDC_BV_NCONT, m_d_NumContours); + DDV_MinMaxInt(pDX, m_d_NumContours, 4, 999); + DDX_Check(pDX, IDC_BV_ONRELOAD, m_d_ResetOnReload); + DDX_Check(pDX, IDC_BV_SHOWGRID, m_d_GridFlag); + DDX_Check(pDX, IDC_BV_SHOWREAL, m_d_ShowAr); + DDX_Check(pDX, IDC_BV_SHOWPTS, m_d_PtsFlag); + DDX_Check(pDX, IDC_BV_SHOWMESH, m_d_MeshFlag); + DDX_Check(pDX, IDC_BV_SNAPGRID, m_d_SnapFlag); + DDX_Check(pDX, IDC_BV_SMOOTHING, m_d_Smooth); + DDX_Text(pDX, IDC_BV_LIPOINTS, m_d_LineIntegralPoints); + DDV_MinMaxInt(pDX, m_d_LineIntegralPoints, 10, 100000); + DDX_Text(pDX, IDC_BV_PLOTPOINTS, m_d_PlotPoints); + DDV_MinMaxInt(pDX, m_d_PlotPoints, 10, 100000); + DDX_Check(pDX, IDC_BV_SHOWMASK, m_d_ShowMask); + DDX_Check(pDX, IDC_BV_SHOWNAMES, m_d_shownames); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BV_NCONT, m_IDC_d_NumContours); + DDX_Control(pDX, IDC_BV_LIPOINTS, m_IDC_d_LineIntegralPoints); + DDX_Control(pDX, IDC_BV_PLOTPOINTS, m_IDC_d_PlotPoints); + + +} + + +BEGIN_MESSAGE_MAP(bvCPref, CDialog) + //{{AFX_MSG_MAP(bvCPref) + ON_BN_CLICKED(IDC_BV_MODBTN, OnModBtn) + ON_BN_CLICKED(IDC_BV_RESET, OnResetColors) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCPref message handlers + +void bvCPref::OnModBtn() +{ + CColorDialog dlg; + COLORREF cclist[16]; + int i,k; + + UpdateData(); + i=m_d_color.GetCurSel(); + for(k=0;k<16;k++) cclist[k]=RGB(190,190,190); + + if(i<11) for(k=0;k<11;k++) cclist[k]=clist[k]; + if((i>10)&&(i<23)) for(k=11;k<23;k++) cclist[k-11]=clist[k]; + if(i>22) for(k=23;k<35;k++) cclist[k-23]=clist[k]; + + dlg.m_cc.lpCustColors=cclist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + +} + +BOOL bvCPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_color.SetCurSel(0); + m_d_dplotlist.SetCurSel(m_d_DensityPlot); + m_d_editlist.SetCurSel(m_d_EditAction); + m_d_vplotlist.SetCurSel(m_d_VectorPlot); + + UpdateData(FALSE); + + return TRUE; +} + +void bvCPref::OnResetColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + int i=0; + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dNameColor; + clist[i++]=dMaskLineColor; + clist[i++]=dRealVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + } +} + +BOOL bvCPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void bvCPref::WritePrefs() +{ + UpdateData(); + m_d_DensityPlot=m_d_dplotlist.GetCurSel(); + m_d_EditAction=m_d_editlist.GetCurSel(); + m_d_VectorPlot=m_d_vplotlist.GetCurSel(); + + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "belaview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorColor", VectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",m_d_EditAction); + fprintf(fp," = %i\n",m_d_DensityPlot); + fprintf(fp," = %i\n",m_d_VectorPlot); + fprintf(fp," = %i\n",m_d_GridFlag); + fprintf(fp," = %i\n",m_d_SnapFlag); + fprintf(fp," = %i\n",m_d_MeshFlag); + fprintf(fp," = %i\n",m_d_LegendFlag); + fprintf(fp," = %i\n",m_d_NumContours); + fprintf(fp," = %i\n",m_d_ShowAr); + fprintf(fp," = %i\n",m_d_ShowMask); + fprintf(fp," = %i\n",m_d_GreyContours); + fprintf(fp," = %i\n",m_d_PtsFlag); + fprintf(fp," = %i\n",m_d_ResetOnReload); + fprintf(fp," = %i\n",m_d_Smooth); + fprintf(fp," = %i\n",m_d_PlotPoints); + fprintf(fp," = %i\n",m_d_shownames); + fprintf(fp," = %i\n",m_d_LineIntegralPoints); + + fclose(fp); + } +} + +char* StripKey(char *c); + +void bvCPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "belaview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LineIntegralPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + VectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + +} \ No newline at end of file diff --git a/femm/bv_Pref.h b/femm/bv_Pref.h new file mode 100644 index 0000000..85842b0 --- /dev/null +++ b/femm/bv_Pref.h @@ -0,0 +1,68 @@ +// Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCPref dialog + +class bvCPref : public CDialog +{ +// Construction +public: + bvCPref(CWnd* pParent = NULL); // standard constructor + ~bvCPref(); + + COLORREF *clist; + int m_d_EditAction; + int m_d_DensityPlot; + int m_d_VectorPlot; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(bvCPref) + enum { IDD = IDD_BV_PREF }; + CComboBox m_d_vplotlist; + CComboBox m_d_dplotlist; + CComboBox m_d_editlist; + CComboBox m_d_color; + BOOL m_d_GreyContours; + BOOL m_d_LegendFlag; + int m_d_NumContours; + BOOL m_d_ResetOnReload; + BOOL m_d_GridFlag; + BOOL m_d_ShowAr; + BOOL m_d_PtsFlag; + BOOL m_d_MeshFlag; + BOOL m_d_SnapFlag; + BOOL m_d_Smooth; + int m_d_LineIntegralPoints; + int m_d_PlotPoints; + BOOL m_d_ShowMask; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCPref) + afx_msg void OnModBtn(); + virtual BOOL OnInitDialog(); + afx_msg void OnResetColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_d_NumContours, m_IDC_d_LineIntegralPoints; + CLuaEdit m_IDC_d_PlotPoints; + +}; diff --git a/femm/bv_VPlotDlg.cpp b/femm/bv_VPlotDlg.cpp new file mode 100644 index 0000000..5803b2c --- /dev/null +++ b/femm/bv_VPlotDlg.cpp @@ -0,0 +1,61 @@ +// VPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "bv_VPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCVPlotDlg dialog + + +bvCVPlotDlg::bvCVPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(bvCVPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCVPlotDlg) + m_vectorscalefactor = 0.0; + //}}AFX_DATA_INIT +} + + +void bvCVPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCVPlotDlg) + DDX_Control(pDX, IDC_BV_VPLOTTYPE, m_vplottype); + DDX_Text(pDX, IDC_BV_SCALEFACTOR, m_vectorscalefactor); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BV_SCALEFACTOR, m_IDC_vectorscalefactor); +} + + +BEGIN_MESSAGE_MAP(bvCVPlotDlg, CDialog) + //{{AFX_MSG_MAP(bvCVPlotDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCVPlotDlg message handlers + +void bvCVPlotDlg::OnOK() +{ + m_plottype=m_vplottype.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL bvCVPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_vplottype.SetCurSel(m_plottype); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/bv_VPlotDlg.h b/femm/bv_VPlotDlg.h new file mode 100644 index 0000000..036ca6d --- /dev/null +++ b/femm/bv_VPlotDlg.h @@ -0,0 +1,51 @@ +#if !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) +#define AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// VPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCVPlotDlg dialog + +class bvCVPlotDlg : public CDialog +{ +// Construction +public: + bvCVPlotDlg(CWnd* pParent = NULL); // standard constructor + + int m_plottype; + CLuaEdit m_IDC_vectorscalefactor; + +// Dialog Data + //{{AFX_DATA(bvCVPlotDlg) + enum { IDD = IDD_BV_VPLOTDLG }; + CComboBox m_vplottype; + double m_vectorscalefactor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCVPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCVPlotDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) diff --git a/femm/bv_XYPlotDlg.cpp b/femm/bv_XYPlotDlg.cpp new file mode 100644 index 0000000..2d58530 --- /dev/null +++ b/femm/bv_XYPlotDlg.cpp @@ -0,0 +1,95 @@ +// XYPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "bv_problem.h" +#include "xyplot.h" +#include "belaviewDoc.h" +#include "belaviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#include "bv_XYPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// bvCXYPlotDlg dialog + + +bvCXYPlotDlg::bvCXYPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(bvCXYPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(bvCXYPlotDlg) + m_ToFile = FALSE; + m_npoints = 150; + //}}AFX_DATA_INIT + ListType=0; + XYPlotType=0; + FileFormat=0; +} + + +void bvCXYPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(bvCXYPlotDlg) + DDX_Control(pDX, IDC_BV_FILEFORMAT, m_fileformat); + DDX_Control(pDX, IDC_BV_XYPLOTTYPE, m_XYPlotType); + DDX_Check(pDX, IDC_BV_TOFILE, m_ToFile); + DDX_Text(pDX, IDC_BV_NPOINTS, m_npoints); + DDV_MinMaxInt(pDX, m_npoints, 10, 100000); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BV_NPOINTS, m_IDC_npoints); +} + + +BEGIN_MESSAGE_MAP(bvCXYPlotDlg, CDialog) + //{{AFX_MSG_MAP(bvCXYPlotDlg) + ON_BN_CLICKED(IDC_BV_TOFILE, OnToFileClicked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// bvCXYPlotDlg message handlers + +BOOL bvCXYPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_XYPlotType.AddString("V (Voltage)"); + m_XYPlotType.AddString("|D| (Magnitude of flux density)"); + m_XYPlotType.AddString("D . n (Normal flux density)"); + m_XYPlotType.AddString("D . t (Tangential flux density)"); + m_XYPlotType.AddString("|E| (Magnitude of field intensity)"); + m_XYPlotType.AddString("E . n (Normal field intensity)"); + m_XYPlotType.AddString("E . t (Tangential field intensity)"); + m_XYPlotType.SetCurSel(0); + + m_fileformat.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void bvCXYPlotDlg::OnOK() +{ + // TODO: Add extra validation here + XYPlotType=m_XYPlotType.GetCurSel(); + FileFormat=m_fileformat.GetCurSel(); + CDialog::OnOK(); +} + +void bvCXYPlotDlg::OnToFileClicked() +{ + UpdateData(); +} + diff --git a/femm/bv_XYPlotDlg.h b/femm/bv_XYPlotDlg.h new file mode 100644 index 0000000..d3d3e3f --- /dev/null +++ b/femm/bv_XYPlotDlg.h @@ -0,0 +1,46 @@ +// XYPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// bvCXYPlotDlg dialog + +class bvCXYPlotDlg : public CDialog +{ +// Construction +public: + bvCXYPlotDlg(CWnd* pParent = NULL); // standard constructor + int ListType; + int XYPlotType; + int FileFormat; + CbelaviewDoc *pDoc; + +// Dialog Data + //{{AFX_DATA(bvCXYPlotDlg) + enum { IDD = IDD_BV_XYPLOTDLG }; + CComboBox m_fileformat; + CComboBox m_XYPlotType; + BOOL m_ToFile; + int m_npoints; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(bvCXYPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(bvCXYPlotDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnToFileClicked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_npoints; +}; diff --git a/femm/bv_makemask.cpp b/femm/bv_makemask.cpp new file mode 100644 index 0000000..502d450 --- /dev/null +++ b/femm/bv_makemask.cpp @@ -0,0 +1,349 @@ +#include "stdafx.h" +#include +#include +#include "bv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "belaviewDoc.h" +#include "belaviewView.h" +#include "MainFrm.h" + +#include "maskprogress.h" +#include "lua.h" + +#include "spars.h" + +extern BOOL bLinehook; +extern CLuaConsoleDlg *LuaConsole; + +// #define SIMPLE + +#ifdef SIMPLE + +BOOL CbelaviewDoc::MakeMask() +{ + // Good placeholder mask generator + // This gives a valid mask that butts right up against the + // selected region. This mask yields the same results as the + // Coulomb virtual work method. + + int i,j; + + for(i=0;ibw) bw=d; + } + } + bw++; + + L.Create(NumNodes,bw); + + // if the problem is axisymmetric, does the selection lie along r=0? + if(ProblemType==1) + { + for(i=0;i0) + { + CComplex *p; + int npts; + + p=(CComplex *)calloc(nodelist.GetSize(),sizeof(CComplex)); + for(i=0,npts=0;i=0) + { + p[npts]=nodelist[i].CC(); + npts++; + } + + if(npts>0) + for(i=0;i0){ + p[j]=p[npts]; + j=npts; + } + else{ + j=npts; + i=NumNodes; + } + } + free(p); + } + + for(i=0;iToOutput(outmsg); + } + else{ + outmsg ="The selected region is invalid. A valid selection\n"; + outmsg+="cannot abut a region which is not free space."; + MsgBox(outmsg); + } + free(matflag); + free(lblflag); + return FALSE; + } + } + + // Each element weighted by its region's + // mesh size specification; + v=blocklist[meshelem[i].lbl].MaxArea; + if (v<=0) v=sqrt(a); else v=sqrt(v); + + // build element matrix; + for(j=0;j<3;j++) + for(k=0;k<3;k++) + Me[j][k]+=v*(p[j]*p[k]+q[j]*q[k])/a; + + // process any prescribed nodal values; + // doing it here saves a lot of time. + for(j=0;j<3;j++) + { + if(L.V[n[j]]>=0) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + for (k=j;k<3;k++) + if(Me[j][k]!=0) L.Put(L.Get(n[j],n[k])-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // solve the problem; + bLinehook=BuildMask; + if (L.PCGSolve(FALSE)==FALSE) return FALSE; + bLinehook=FALSE; + + // Process the results to get one row of elements + // that runs down the center of the gap away from boundaries. + for(i=0;i0.5) meshnode[i].msk = 1; + else meshnode[i].msk = 0; + + free(matflag); + free(lblflag); + bHasMask=TRUE; + + return TRUE; +} + +#endif + +BOOL CbelaviewDoc::IsKosher(int k) +{ + // If: + // 1) this is an axisymmetric problem; + // 2) the selected geometry lies along the r=0 axis, and + // 3) we have a node on the r=0 axis that we are trying to determine + // if we should set to zero. + // This routine determines whether the node is at the extents of + // the r=0 domain (or lies at a break in some sub-interval). + // + // Returns TRUE if it is OK to define the node as zero; + + if((ProblemType==0) || (meshnode[k].x>1.e-6)) return TRUE; + + int i,j,n; + int score=0; + + for(i=0;i1) return FALSE; + } + } + } + + return TRUE; +} diff --git a/femm/bv_problem.cpp b/femm/bv_problem.cpp new file mode 100644 index 0000000..1d8d456 --- /dev/null +++ b/femm/bv_problem.cpp @@ -0,0 +1,146 @@ +#include "stdafx.h" +#include "bv_problem.h" + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +CComplex CNode::CC() +{ + return (x+I*y); +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMeshNode construction + +CMeshNode::CMeshNode() +{ + x=y=V=0; + Q=FALSE; + msk=0; + IsSelected=FALSE; +} + +CComplex CMeshNode::CC() +{ + return (x+I*y); +} + +double CMeshNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + MaxSideLength=-1; + ArcLength=90.; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + InGroup=0; + BlockType=-1; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + ex=ey=1; + qv=0; +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; + V=qs=0; + InConductor=""; +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + InConductor=""; + V=qp=0; +} + +CCircuit::CCircuit() +{ + CircName="New Circuit"; + V=q=0; + CircType=0; +} diff --git a/femm/bv_problem.h b/femm/bv_problem.h new file mode 100644 index 0000000..b6b2f49 --- /dev/null +++ b/femm/bv_problem.h @@ -0,0 +1,193 @@ +namespace belaviewtype +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + int BoundaryMarker; + int InGroup,InConductor; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +class CMeshNode +{ + public: + CMeshNode(); + + double x,y,V; + double msk; + int xs,ys; + BOOL Q,IsSelected; + + double GetDistance(double xo, double yo); + CComplex CC(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + double MaxSideLength; + BOOL IsSelected; + BOOL Hidden; + int BoundaryMarker; + int InGroup,InConductor; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength; + int BoundaryMarker; + int InGroup, InConductor; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + double MagDir; + BOOL IsSelected; + int BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CString BlockName; + double ex,ey; // permittivity, relative + double qv; // volume charge density + + CMaterialProp(); + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + CString InConductor; + int BdryFormat; + double V,qs; + double c0,c1; + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + CString InConductor; + double V,qp; + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + double V,q; + int CircType; + + private: + +}; + +class CElement +{ + public: + + int p[3]; + int blk,lbl; + CComplex D; // elemental flux density + CComplex d[3]; // smoothed flux density at corners + CComplex ctr; + double rsqr; + int n[3]; // Add 3 ints to store elem's neigh. + + CComplex E(); + + private: +}; + +class CPointVals +{ + public: + + double V; // vector potential + CComplex D; // flux density + CComplex e; // permeability + CComplex E; // field intensity + double nrg; // energy stored in the field + + CPointVals(); + + private: +}; + +} + +using namespace belaviewtype; \ No newline at end of file diff --git a/femm/cd_BdryDlg.cpp b/femm/cd_BdryDlg.cpp new file mode 100644 index 0000000..7f5ea46 --- /dev/null +++ b/femm/cd_BdryDlg.cpp @@ -0,0 +1,127 @@ +// BdryDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cd_BdryDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCBdryDlg dialog + + +cdCBdryDlg::cdCBdryDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCBdryDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCBdryDlg) + m_BdryName = _T(""); + m_c0 = 0; + m_c1 = 0; + m_vs = 0; + m_qs = 0; + //}}AFX_DATA_INIT +} + + +void cdCBdryDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCBdryDlg) + DDX_Control(pDX, IDC_CD_BDRYFORMAT, m_BdryFormat); + DDX_Text(pDX, IDC_CD_BDRYNAME, m_BdryName); + DDX_Text(pDX, IDC_CD_C0, m_c0); + DDX_Text(pDX, IDC_CD_C1, m_c1); + DDX_Text(pDX, IDC_CD_VBDRY, m_vs); + DDX_Text(pDX, IDC_CD_QS, m_qs); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_VBDRY, m_IDC_VBDRY); + DDX_Control(pDX, IDC_CD_QS, m_IDC_QS); + DDX_Control(pDX, IDC_CD_BDRYNAME, m_IDC_BDRYNAME); + DDX_Control(pDX, IDC_CD_C0, m_IDC_c0); + DDX_Control(pDX, IDC_CD_C1, m_IDC_c1); +} + + +BEGIN_MESSAGE_MAP(cdCBdryDlg, CDialog) + //{{AFX_MSG_MAP(cdCBdryDlg) + ON_CBN_SELCHANGE(IDC_CD_BDRYFORMAT, OnSelchangeBdryformat) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCBdryDlg message handlers + +void cdCBdryDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(cdCBdryDlg) + enum { IDD = IDD_CD_BDRYDLG }; + CComboBox m_BdryFormat; + CString m_BdryName; + CComplex m_qs; + CComplex m_vs; + CComplex m_c0; + CComplex m_c1; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCBdryDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCBdryDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeBdryformat(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_IDC_VBDRY, m_IDC_QS, m_IDC_BDRYNAME; + CLuaEdit m_IDC_c0, m_IDC_c1; + +}; diff --git a/femm/cd_CircProp.cpp b/femm/cd_CircProp.cpp new file mode 100644 index 0000000..2d494a1 --- /dev/null +++ b/femm/cd_CircProp.cpp @@ -0,0 +1,102 @@ +// CircProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCCircProp dialog + + +cdCCircProp::cdCCircProp(CWnd* pParent /*=NULL*/) + : CDialog(cdCCircProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCCircProp) + m_circname = _T(""); + m_vc = 0; + m_qc = 0; + //}}AFX_DATA_INIT +} + + +void cdCCircProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCCircProp) + DDX_Text(pDX, IDC_CD_CIRCNAME, m_circname); + DDX_Text(pDX, IDC_CD_V, m_vc); + DDX_Text(pDX, IDC_CD_Q, m_qc); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_CIRCNAME, m_idc_circname); + DDX_Control(pDX, IDC_CD_V, m_idc_vc); + DDX_Control(pDX, IDC_CD_Q, m_idc_qc); +} + + +BEGIN_MESSAGE_MAP(cdCCircProp, CDialog) + //{{AFX_MSG_MAP(cdCCircProp) + ON_BN_CLICKED(IDC_CD_RADIOAMP, OnRadioamp) + ON_BN_CLICKED(IDC_CD_RADIOVOLT, OnRadiovolt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCCircProp message handlers + +void cdCCircProp::OnRadioamp() +{ + m_circtype=0; + m_idc_qc.EnableWindow(TRUE); + m_idc_vc.EnableWindow(FALSE); +} + +void cdCCircProp::OnRadiovolt() +{ + m_circtype=1; + m_idc_qc.EnableWindow(FALSE); + m_idc_vc.EnableWindow(TRUE); +} + +BOOL cdCCircProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + SetEm=IDC_CD_RADIOAMP; + if(m_circtype==1){ + SetEm=IDC_CD_RADIOVOLT; + OnRadiovolt(); + } + else OnRadioamp(); + + CheckRadioButton( + IDC_CD_RADIOVOLT,// identifier of first radio button in group + IDC_CD_RADIOAMP, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cdCCircProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(cdCCircProp) + enum { IDD = IDD_CD_CIRCPROP }; + CString m_circname; + CComplex m_vc; + CComplex m_qc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCCircProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCCircProp) + afx_msg void OnRadioamp(); + afx_msg void OnRadiovolt(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_idc_circname, m_idc_vc, m_idc_qc; +}; diff --git a/femm/cd_MatDlg.cpp b/femm/cd_MatDlg.cpp new file mode 100644 index 0000000..c8b364e --- /dev/null +++ b/femm/cd_MatDlg.cpp @@ -0,0 +1,112 @@ +// MatDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cd_MatDlg.h" +#include "KCurve.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCMatDlg dialog + + +cdCMatDlg::cdCMatDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCMatDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCMatDlg) + m_BlockName = _T(""); + m_ex = 1.0; + m_ey = 1.0; + m_ltx = 0.0; + m_lty = 0.0; + m_ox = 0.0; + m_oy = 0.0; + m_mu1label = _T("x"); + m_mu2label = _T("y"); + m_mu1label2 = _T("x"); + m_mu2label2 = _T("y"); + m_mu1label3 = _T("x-dir"); + m_mu2label3 = _T("y-dir"); + //}}AFX_DATA_INIT +} + + +void cdCMatDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCMatDlg) + DDX_Control(pDX, IDC_STATIC_SYMBOL4, m_static4); + DDX_Control(pDX, IDC_STATIC_SYMBOL3, m_static3); + DDX_Control(pDX, IDC_STATIC_SYMBOL7, m_static7); + DDX_Control(pDX, IDC_STATIC_SYMBOL8, m_static8); + DDX_Text(pDX, IDC_CD_BLOCKNAME, m_BlockName); + DDX_Text(pDX, IDC_CD_EX, m_ex); + DDX_Text(pDX, IDC_CD_EY, m_ey); + DDX_Text(pDX, IDC_CD_LTX, m_ltx); + DDX_Text(pDX, IDC_CD_LTY, m_lty); + DDX_Text(pDX, IDC_CD_OX, m_ox); + DDX_Text(pDX, IDC_CD_OY, m_oy); + DDX_Text(pDX, IDC_CD_MU1LABEL, m_mu1label); + DDX_Text(pDX, IDC_CD_MU2LABEL, m_mu2label); + DDX_Text(pDX, IDC_CD_MU1LABEL2, m_mu1label2); + DDX_Text(pDX, IDC_CD_MU2LABEL2, m_mu2label2); + DDX_Text(pDX, IDC_CD_MU1LABEL3, m_mu1label3); + DDX_Text(pDX, IDC_CD_MU2LABEL3, m_mu2label3); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_BLOCKNAME, m_IDC_BlockName); + DDX_Control(pDX, IDC_CD_EX, m_IDC_EX); + DDX_Control(pDX, IDC_CD_EY, m_IDC_EY); + DDX_Control(pDX, IDC_CD_OX, m_IDC_OX); + DDX_Control(pDX, IDC_CD_OY, m_IDC_OY); + DDX_Control(pDX, IDC_CD_LTX, m_IDC_LTX); + DDX_Control(pDX, IDC_CD_LTY, m_IDC_LTY); +} + + +BEGIN_MESSAGE_MAP(cdCMatDlg, CDialog) + //{{AFX_MSG_MAP(cdCMatDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCMatDlg message handlers + +BOOL cdCMatDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + symbfont.CreateFont(0, 0, 0, 0, FW_BOLD, TRUE, 0, 0, + SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, DEFAULT_PITCH | FF_DECORATIVE, "Symbol"); + + m_static3.SetFont(&symbfont); + m_static4.SetFont(&symbfont); + m_static7.SetFont(&symbfont); + m_static8.SetFont(&symbfont); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cdCMatDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + + CFont symbfont; + CFont bfont; + +// Dialog Data + //{{AFX_DATA(cdCMatDlg) + enum { IDD = IDD_CD_MATDLG }; + CString m_BlockName; + double m_ox; + double m_oy; + double m_ex; + double m_ey; + double m_ltx; + double m_lty; + CString m_mu1label; + CString m_mu2label; + CString m_mu1label2; + CString m_mu2label2; + CString m_mu1label3; + CString m_mu2label3; + CStatic m_static4; + CStatic m_static3; + CStatic m_static7; + CStatic m_static8; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCMatDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCMatDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_EX, m_IDC_EY, m_IDC_BlockName, m_IDC_OX, m_IDC_OY, m_IDC_LTX, m_IDC_LTY; + +}; diff --git a/femm/cd_NodeProp.cpp b/femm/cd_NodeProp.cpp new file mode 100644 index 0000000..4fedd5a --- /dev/null +++ b/femm/cd_NodeProp.cpp @@ -0,0 +1,107 @@ +// NodeProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cd_NodeProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCNodeProp dialog + + +cdCNodeProp::cdCNodeProp(CWnd* pParent /*=NULL*/) + : CDialog(cdCNodeProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCNodeProp) + m_nodename = _T(""); + m_qp = 0; + m_vp = 0; + //}}AFX_DATA_INIT +} + + +void cdCNodeProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCNodeProp) + DDX_Text(pDX, IDC_CD_NODENAME, m_nodename); + DDX_Text(pDX, IDC_CD_QP, m_qp); + DDX_Text(pDX, IDC_CD_VP, m_vp);; + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_VP, m_IDC_vpr); + DDX_Control(pDX, IDC_CD_QP, m_IDC_qpr); + DDX_Control(pDX, IDC_CD_NODENAME, m_IDC_nodename); +} + + +BEGIN_MESSAGE_MAP(cdCNodeProp, CDialog) + //{{AFX_MSG_MAP(cdCNodeProp) + ON_BN_CLICKED(IDC_CD_SETA, OnSetA) + ON_BN_CLICKED(IDC_CD_SETI, OnSetI) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCNodeProp message handlers + +void cdCNodeProp::OnSetA() +{ + // TODO: Add your control notification handler code here + m_IDC_qpr.EnableWindow(FALSE); + m_IDC_vpr.EnableWindow(TRUE); + SetDlgItemText(IDC_CD_QP,"0"); m_qp=0; +} + +void cdCNodeProp::OnSetI() +{ + // TODO: Add your control notification handler code here + m_IDC_vpr.EnableWindow(FALSE); + m_IDC_qpr.EnableWindow(TRUE); + SetDlgItemText(IDC_CD_VP,"0"); m_vp=0; +} + +BOOL cdCNodeProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + if(abs(m_qp)>0){ + SetEm=IDC_CD_SETI; + OnSetI(); + } + else{ + SetEm=IDC_CD_SETA; + OnSetA(); + } + + + CheckRadioButton( + IDC_CD_SETA,// identifier of first radio button in group + IDC_CD_SETI, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cdCNodeProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(cdCNodeProp) + enum { IDD = IDD_CD_NODEPROP }; + CString m_nodename; + CComplex m_qp; + CComplex m_vp; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCNodeProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCNodeProp) + afx_msg void OnSetA(); + afx_msg void OnSetI(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_vpr, m_IDC_qpr, m_IDC_nodename; +}; diff --git a/femm/cd_OpArcSegDlg.cpp b/femm/cd_OpArcSegDlg.cpp new file mode 100644 index 0000000..bd945e9 --- /dev/null +++ b/femm/cd_OpArcSegDlg.cpp @@ -0,0 +1,86 @@ +// OpArcSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_OpArcSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCOpArcSegDlg dialog + + +cdCOpArcSegDlg::cdCOpArcSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCOpArcSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCOpArcSegDlg) + m_MaxSeg = 0.0; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void cdCOpArcSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCOpArcSegDlg) + DDX_Control(pDX, IDC_CD_ARCSEG_COND, m_arcsegcond); + DDX_Control(pDX, IDC_CD_ARCSEGBDRY2, m_ArcSegBdry); + DDX_Text(pDX, IDC_CD_MAXSEG2, m_MaxSeg); + DDX_Check(pDX, IDC_CD_ARCHIDE, m_hide); + DDX_Text(pDX, IDC_CD_ARCGRP, m_ingroup); + DDV_MinMaxDouble(pDX, m_MaxSeg, 1.e-002, 10.); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_ARCGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_CD_MAXSEG2, m_IDC_MaxSeg); +} + + +BEGIN_MESSAGE_MAP(cdCOpArcSegDlg, CDialog) + //{{AFX_MSG_MAP(cdCOpArcSegDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCOpArcSegDlg message handlers + +BOOL cdCOpArcSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ArcSegBdry.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_arcsegcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(cdCOpArcSegDlg) + enum { IDD = IDD_CD_OPARCSEGDLG }; + CComboBox m_arcsegcond; + CComboBox m_ArcSegBdry; + double m_MaxSeg; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCOpArcSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCOpArcSegDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_MaxSeg; +}; diff --git a/femm/cd_OpBlkDlg.cpp b/femm/cd_OpBlkDlg.cpp new file mode 100644 index 0000000..04cab07 --- /dev/null +++ b/femm/cd_OpBlkDlg.cpp @@ -0,0 +1,118 @@ +// OpBlkDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_OpBlkDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCOpBlkDlg dialog + + +cdCOpBlkDlg::cdCOpBlkDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCOpBlkDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCOpBlkDlg) + m_sidelength = 0.0; + m_ingroup = 0; + m_isexternal = FALSE; + m_isdefault = FALSE; + //}}AFX_DATA_INIT + ProblemType=0; +} + + +void cdCOpBlkDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCOpBlkDlg) + DDX_Control(pDX, IDC_CD_AUTOMESHCHECK, m_automesh); + DDX_Control(pDX, IDC_CD_ACKBLK, m_ackblk); + DDX_Check(pDX, IDC_CD_EXTERNAL, m_isexternal); + DDX_Check(pDX, IDC_CD_ISDEFAULT, m_isdefault); + DDX_Text(pDX, IDC_CD_SIDELENGTH, m_sidelength); + DDX_Text(pDX, IDC_CD_BLKGROUP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_SIDELENGTH, m_IDC_sidelength); + DDX_Control(pDX, IDC_CD_BLKGROUP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(cdCOpBlkDlg, CDialog) + //{{AFX_MSG_MAP(cdCOpBlkDlg) + ON_CBN_SELCHANGE(IDC_CD_ACKBLK, OnSelchangeAckblk) + ON_BN_CLICKED(IDC_CD_AUTOMESHCHECK, OnAutomeshcheck) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCOpBlkDlg message handlers + +void cdCOpBlkDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackblk.GetCurSel(); + CDialog::OnOK(); +} + +BOOL cdCOpBlkDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CArray &blockproplist=*pblockproplist; + CArray &circproplist=*pcircproplist; + + int i; + + // TODO: Add extra initialization here + m_ackblk.AddString(""); + m_ackblk.AddString(""); + for(i=0;iEnableWindow(ProblemType); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cdCOpBlkDlg::OnSelchangeAckblk() +{ + CArray &blockproplist=*pblockproplist; + BOOL bEnable=FALSE; + + cursel=m_ackblk.GetCurSel(); +} + +void cdCOpBlkDlg::OnAutomeshcheck() +{ + // TODO: Add your control notification handler code here + int k=m_automesh.GetCheck(); + if (k==TRUE) k=FALSE; + else k=TRUE; + + SendDlgItemMessage( + IDC_CD_SIDELENGTH, // identifier of control + WM_ENABLE, // message to send + (WPARAM) k, // first message parameter + (LPARAM) 0 // second message parameter + ); + if (k==FALSE){ + m_sidelength=0; + SetDlgItemText(IDC_CD_SIDELENGTH, "0" ); + } +} diff --git a/femm/cd_OpBlkDlg.h b/femm/cd_OpBlkDlg.h new file mode 100644 index 0000000..1ac3868 --- /dev/null +++ b/femm/cd_OpBlkDlg.h @@ -0,0 +1,50 @@ +// cd_OpBlkDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cdCOpBlkDlg dialog + +class cdCOpBlkDlg : public CDialog +{ +// Construction +public: + cdCOpBlkDlg(CWnd* pParent = NULL); // standard constructor + int cursel; + int ProblemType; + CArray *pblockproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(cdCOpBlkDlg) + enum { IDD = IDD_CD_OPBLKDLG }; + CButton m_automesh; + CComboBox m_ackblk; + BOOL m_isexternal; + BOOL m_isdefault; + double m_sidelength; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCOpBlkDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCOpBlkDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAckblk(); + afx_msg void OnAutomeshcheck(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_sidelength; + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/cd_OpNodeDlg.cpp b/femm/cd_OpNodeDlg.cpp new file mode 100644 index 0000000..c40ed30 --- /dev/null +++ b/femm/cd_OpNodeDlg.cpp @@ -0,0 +1,80 @@ +// OpNodeDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_OpNodeDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCOpNodeDlg dialog + + +cdCOpNodeDlg::cdCOpNodeDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCOpNodeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCOpNodeDlg) + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void cdCOpNodeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCOpNodeDlg) + DDX_Control(pDX, IDC_CD_NODE_COND, m_nodecond); + DDX_Control(pDX, IDC_CD_ACKNODE, m_acknode); + DDX_Text(pDX, IDC_CD_PTGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_PTGRP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(cdCOpNodeDlg, CDialog) + //{{AFX_MSG_MAP(cdCOpNodeDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCOpNodeDlg message handlers + +BOOL cdCOpNodeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &nodeproplist=*pnodeproplist; + + int i; + + // TODO: Add extra initialization here + m_acknode.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_nodecond.AddString(""); + for(i=0;i *pnodeproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(cdCOpNodeDlg) + enum { IDD = IDD_CD_OPNODEDLG }; + CComboBox m_nodecond; + CComboBox m_acknode; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCOpNodeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCOpNodeDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/cd_OpSegDlg.cpp b/femm/cd_OpSegDlg.cpp new file mode 100644 index 0000000..3be65f4 --- /dev/null +++ b/femm/cd_OpSegDlg.cpp @@ -0,0 +1,126 @@ +// OpSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_OpSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCOpSegDlg dialog + + +cdCOpSegDlg::cdCOpSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCOpSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCOpSegDlg) + m_linemeshsize = 0.0; + m_automesh = FALSE; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void cdCOpSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCOpSegDlg) + DDX_Control(pDX, IDC_CD_SEG_COND, m_segcond); + DDX_Control(pDX, IDC_CD_ACKSEG, m_ackseg); + DDX_Text(pDX, IDC_CD_LINEMESHSIZE, m_linemeshsize); + DDX_Check(pDX, IDC_CD_AUTOMESH, m_automesh); + DDX_Check(pDX, IDC_CD_SEGHIDE, m_hide); + DDX_Text(pDX, IDC_CD_SEGGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_SEGGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_CD_LINEMESHSIZE, m_IDC_linemeshsize); +} + + +BEGIN_MESSAGE_MAP(cdCOpSegDlg, CDialog) + //{{AFX_MSG_MAP(cdCOpSegDlg) + ON_BN_CLICKED(IDC_CD_AUTOMESH, OnAutomesh) + ON_CBN_SELCHANGE(IDC_CD_ACKSEG, OnSelchangeAckseg) + ON_CBN_SELCHANGE(IDC_CD_SEG_COND, OnSelchangeSegCond) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCOpSegDlg message handlers + +void cdCOpSegDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackseg.GetCurSel(); + condsel=m_segcond.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL cdCOpSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ackseg.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_segcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(cdCOpSegDlg) + enum { IDD = IDD_CD_OPSEGDLG }; + CComboBox m_segcond; + CComboBox m_ackseg; + double m_linemeshsize; + BOOL m_automesh; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCOpSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCOpSegDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnAutomesh(); + afx_msg void OnSelchangeAckseg(); + afx_msg void OnSelchangeSegCond(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_linemeshsize; +}; diff --git a/femm/cd_PtProp.cpp b/femm/cd_PtProp.cpp new file mode 100644 index 0000000..8a955b5 --- /dev/null +++ b/femm/cd_PtProp.cpp @@ -0,0 +1,416 @@ +// PtProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_PtProp.h" +#include "cd_NodeProp.h" +#include "cd_MatDlg.h" +#include "cd_BdryDlg.h" +#include "cd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCPtProp dialog + + +cdCPtProp::cdCPtProp(CWnd* pParent /*=NULL*/) + : CDialog(cdCPtProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCPtProp) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void cdCPtProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCPtProp) + DDX_Control(pDX, IDC_NAME_LIST, m_namelist); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(cdCPtProp, CDialog) + //{{AFX_MSG_MAP(cdCPtProp) + ON_BN_CLICKED(IDC_ADD_PROP, OnAddProp) + ON_BN_CLICKED(IDC_DEL_PROP, OnDelProp) + ON_BN_CLICKED(IDC_MOD_PROP, OnModProp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCPtProp message handlers + +void cdCPtProp::OnAddProp() +{ + + // Code to deal with adding a Point Property. + if (PropType==0){ + CPointProp PProp; + CArray &nodeproplist=*pnodeproplist; + cdCNodeProp zDlg; + + for(int nn=0;nn &circproplist=*pcircproplist; + cdCCircProp zDlg; + for(int nn=0;nn &lineproplist=*plineproplist; + cdCBdryDlg zDlg; + for(int nn=0;nn &blockproplist=*pblockproplist; + cdCMatDlg zDlg; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (nodeproplist.GetSize()!=0)) + { + nodeproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (circproplist.GetSize()!=0)) + { + circproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (lineproplist.GetSize()!=0)) + { + lineproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (blockproplist.GetSize()!=0)) + { + blockproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } +} + +void cdCPtProp::OnModProp() +{ + // TODO: Add your control notification handler code here + if (PropType==0){ + CArray &nodeproplist=*pnodeproplist; + cdCNodeProp zDlg; + + if (nodeproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_vp=nodeproplist[k].vp; + zDlg.m_qp=nodeproplist[k].qp; + zDlg.m_nodename=nodeproplist[k].PointName; + + for(int nn=0;nn &circproplist=*pcircproplist; + + if (circproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + cdCCircProp zDlg; + + zDlg.m_circname = circproplist[k].CircName; + zDlg.m_circtype = circproplist[k].CircType; + zDlg.m_qc = circproplist[k].qc; + zDlg.m_vc = circproplist[k].vc; + for(int nn=0;nn &lineproplist=*plineproplist; + cdCBdryDlg zDlg; + + if (lineproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_vs = lineproplist[k].vs; + zDlg.m_qs = lineproplist[k].qs; + zDlg.m_c0 = lineproplist[k].c0; + zDlg.m_c1 = lineproplist[k].c1; + zDlg.BdryFormat=lineproplist[k].BdryFormat; + zDlg.m_BdryName=lineproplist[k].BdryName; + for(int nn=0;nn &blockproplist=*pblockproplist; + cdCMatDlg zDlg; + + if (blockproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_ox=blockproplist[k].ox; + zDlg.m_oy=blockproplist[k].oy; + zDlg.m_ex=blockproplist[k].ex; + zDlg.m_ey=blockproplist[k].ey; + zDlg.m_ltx=blockproplist[k].ltx; + zDlg.m_lty=blockproplist[k].lty; + zDlg.m_BlockName=blockproplist[k].BlockName; + + for(int nn=0;nn &nodeproplist=*pnodeproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/cd_PtProp.h b/femm/cd_PtProp.h new file mode 100644 index 0000000..490ff65 --- /dev/null +++ b/femm/cd_PtProp.h @@ -0,0 +1,48 @@ +// cd_PtProp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cdCPtProp dialog + +class cdCPtProp : public CDialog +{ +// Construction +public: + cdCPtProp(CWnd* pParent = NULL); // standard constructor + + // variables CPrProp needs; + int PropType; + int ProblemType; + CArray *pnodeproplist; + CArray *plineproplist; + CArray *pblockproplist; + CArray *pcircproplist; + + +// Dialog Data + //{{AFX_DATA(cdCPtProp) + enum { IDD = IDD_PTPROP }; + CComboBox m_namelist; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCPtProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCPtProp) + afx_msg void OnAddProp(); + afx_msg void OnDelProp(); + afx_msg void OnModProp(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/cd_libdlg.cpp b/femm/cd_libdlg.cpp new file mode 100644 index 0000000..ffd9bed --- /dev/null +++ b/femm/cd_libdlg.cpp @@ -0,0 +1,1207 @@ +// treetestDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_MatDlg.h" +#include "cd_libdlg.h" +#include "libfolderinfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cdCLibDlg dialog + + +// CLuaConsoleDlg dialog + +cdCLibDlg::cdCLibDlg(CWnd* pParent /*=NULL*/) + : CResizableDialog(cdCLibDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCLibDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + // m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void cdCLibDlg::DoDataExchange(CDataExchange* pDX) +{ + CResizableDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCLibDlg) + DDX_Control(pDX, IDC_MYLIST, m_mylist); + DDX_Control(pDX, IDC_MYTREE, m_mytree); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(cdCLibDlg, CResizableDialog) + //{{AFX_MSG_MAP(cdCLibDlg) + ON_WM_QUERYDRAGICON() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYTREE, OnBegindragMytree) + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYLIST, OnBegindragMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYLIST, OnRclickMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYTREE, OnRclickMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYTREE, OnDblclkMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYLIST, OnDblclkMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYLIST, OnKeydownMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYTREE, OnKeydownMytree) + ON_WM_TIMER() + //}}AFX_MSG_MAP + ON_COMMAND(ID_EDIT_CUT, Zappit) + ON_COMMAND(ID_EDIT_COPY, AddNewProperty) + ON_COMMAND(ID_EDIT_PASTE, AddNewFolder) + ON_COMMAND(ID_EDIT_REPLACE, MouseModify) + ON_COMMAND(ID_EDIT_PASTE_LINK, VendorLink) + ON_COMMAND(ID_EDIT_FIND, ImportMaterials) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cdCLibDlg message handlers + +BOOL cdCLibDlg::OnInitDialog() +{ + CResizableDialog::OnInitDialog(); + + // TODO: Add extra initialization here + ////////////////////////////////////////////////////////////////// + + // preset layout + AddAnchor(IDOK,BOTTOM_RIGHT); + AddAnchor(IDCANCEL,BOTTOM_RIGHT); + AddAnchor(IDC_MYTREE,TOP_LEFT,BOTTOM_CENTER); + AddAnchor(IDC_MYLIST,TOP_CENTER,BOTTOM_RIGHT); + + CString LibName=BinDir+"condlib.dat"; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int i,k; + + Ancestors.RemoveAll(); + Parent=NULL; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + + // set up materials library tree control + m_bIsDragging = FALSE; + m_dragTargetTree = NULL; + m_dragTargetList = NULL; + m_dragItem = NULL; + m_imageList.Create( IDB_TREE, 16, 1, RGB(255,0,0) ); + m_mytree.SetImageList( &m_imageList, TVSIL_NORMAL ); + m_mylist.SetImageList( &m_imageList, TVSIL_NORMAL ); + + LibParent = m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Library Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + Parent=LibParent; + ModelParent = m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Model Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + + // Put Model's properties into the InModel edit box; + LibProps.RemoveAll(); + HTREEITEM hResult; + CArray &blockproplist=pDoc->blockproplist; + for(i=0;i=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + break; + + default: + + break; + } + } + + fclose(fp); + +/* + // tutorial example + HTREEITEM hChapter; + hChapter = m_mytree.InsertItem( "Chapter 1", 0, 1 ); + m_mytree.InsertItem( "What", 2, 2, hChapter ); +*/ + + Focus=NULL; + + return TRUE; // return TRUE unless you set the focus to a control +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR cdCLibDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + + + + + +/////////////////////////////////////////////////// +// Implementation of library-specific file I/O +/////////////////////////////////////////////////// + +char* cdCLibDlg::StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderName=v; + m_mytree.SetItemText(Parent,v); + 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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderURL=v; + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderVendor=v; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.ex=1.; + MProp.ey=1.; + MProp.ltx=0.; + MProp.lty=0.; + MProp.ox=0.; + MProp.oy=0.; + q[0]=NULL; + } + + // Library Hierarchy + if( _strnicmp(q,"",11)==0){ + q[0]=NULL; + return 3; + } + + 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.ex); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ey); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ltx); + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.lty); + q[0]=NULL; + } + + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.ox); + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.oy); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + q[0]=NULL; + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////// +// Drag-n-Drop Implementation + +void cdCLibDlg::OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=LibParent) // can't drag top-level folder + { + CImageList* pDragImage; + pDragImage = m_mytree.CreateDragImage( m_dragItem ); + m_mytree.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + SetTimer ( 1, 75, NULL ) ; + bDragFromLibrary=TRUE; + } + + *pResult = 0; + +} + +void cdCLibDlg::OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=ModelParent) + { + CImageList* pDragImage; + pDragImage = m_mylist.CreateDragImage( m_dragItem ); + m_mylist.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + bDragFromLibrary=FALSE; + SetTimer ( 1, 75, NULL ) ; + } + + *pResult = 0; +} + +void cdCLibDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + CPoint ptDrag( point ); + CPoint ptTree( point ); + CPoint ptList( point ); + UINT uHitTest = TVHT_ONITEM; + + MapWindowPoints( this, &ptDrag, 1 ); + MapWindowPoints( &m_mytree, &ptTree, 1 ); + MapWindowPoints( &m_mylist, &ptList, 1 ); + + CImageList::DragMove( ptDrag ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + } + + CResizableDialog::OnMouseMove(nFlags, point); +} + +void cdCLibDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + KillTimer ( 1 ) ; + CImageList::DragLeave( &m_mytree ); + CImageList::EndDrag(); + ReleaseCapture(); + m_bIsDragging = FALSE; + + // Do some logic to drop onto the main tree if the property is + // dropped onto the tree's window, but not exactly on the list + if((m_dragTargetTree==NULL) && (m_dragTargetList==NULL)) + { + POINT point; + GetCursorPos(&point); + void* pVoid = (void*)GetDesktopWindow()->WindowFromPoint(point); + if((void *) &m_mytree==pVoid) m_dragTargetTree=LibParent; + if((void *) &m_mylist==pVoid) m_dragTargetList=ModelParent; + } + + // Drop onto the Library tree + if( m_dragTargetTree != NULL ) + { + if(!IsTailChasing(m_dragItem,m_dragTargetTree)) + { + CopyItemToLibrary(m_dragItem,m_dragTargetTree); + if(bDragFromLibrary) m_mytree.DeleteItem( m_dragItem ); + } + } + + // Drop onto the model materials + if( m_dragTargetList != NULL ) + { + CopyItemToModel(m_dragItem,m_dragTargetList); + if(!bDragFromLibrary) m_mylist.DeleteItem( m_dragItem ); + } + } + else CResizableDialog::OnLButtonUp(nFlags, point); +} + +BOOL cdCLibDlg::IsFolder(HTREEITEM hItem) +{ + int nImage1, nImage2, nSelImage; + m_mytree.GetItemImage(hItem,nImage1,nSelImage); + m_mylist.GetItemImage(hItem,nImage2,nSelImage); + if ((nImage1!=2) && (nImage2!=2)) return TRUE; + return FALSE; +} + +HTREEITEM cdCLibDlg::CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(IsFolder(hTarget)) + { + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hTarget, TVI_LAST ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hTarget, TVI_LAST); + m_mytree.SetItemData(hResult,ItemData); + } + } + else + { + hParent = m_mytree.GetParentItem(hTarget); + + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + } + } + + + return hResult; +} + +HTREEITEM cdCLibDlg::CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + if (IsFolder(hItem)) + { + hChild=m_mytree.GetChildItem(hItem) ; + hParent=hTarget; + while (hChild!=NULL) + { + hParent=CopyItemToModel(hChild,hParent) ; + hChild = m_mytree.GetNextSiblingItem(hChild); + } + hResult=hParent; + } + else{ + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + + hParent = m_mylist.GetParentItem( hTarget ); + if( hParent != NULL ) + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, hTarget); + else + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, TVI_LAST ); + m_mylist.SetItemData(hResult,ItemData); + } + + return hResult; +} + +void cdCLibDlg::AddNewProperty() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetList!=NULL) + { + hParent = m_mylist.GetParentItem(m_dragTargetList); + if( hParent != NULL ) + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, m_dragTargetList); + else + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mylist.SetItemData(hResult,LibProps.GetUpperBound()); + } + + if(m_dragTargetTree!=NULL) + { + if(IsFolder(m_dragTargetTree)) hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Material", 2, 2, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Material", 2, 2, LibParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mytree.SetItemData(hResult,LibProps.GetUpperBound()); + } +} + +void cdCLibDlg::AddNewFolder() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetTree!=NULL) + { + if (IsFolder(m_dragTargetTree)) + hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Folder", 0, 1, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Folder", 0, 1, LibParent, TVI_LAST ); + + CFolderProp FProp; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(hResult,FoldProps.GetUpperBound()); + } +} + +void cdCLibDlg::Zappit() +{ + if ((m_dragTargetTree!=NULL) && (m_dragTargetTree!=LibParent)) + m_mytree.DeleteItem(m_dragTargetTree); + if ((m_dragTargetList!=NULL) && (m_dragTargetList!=ModelParent)) + m_mylist.DeleteItem(m_dragTargetList); +} + +void cdCLibDlg::OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptTree(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptTree, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree==NULL) m_dragTargetTree=LibParent; + + VERIFY(pMenu->CreatePopupMenu()); + if(m_dragTargetTree!=LibParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Add New Folder")); + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)) + { + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + HTREEITEM hParent=m_mytree.GetParentItem(m_dragTargetTree); + if(hParent!=LibParent) + { + int k=(int) m_mytree.GetItemData(hParent); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + else if(m_dragTargetTree!=LibParent){ + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Edit Folder Info")); + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("cdCLibDlg::OnRclickMytree failed to destroy menu resource\n"); + pMenu = FALSE; + } + + + *pResult = 0; +} + +void cdCLibDlg::OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList==NULL) m_dragTargetList=ModelParent; + + VERIFY(pMenu->CreatePopupMenu()); + if (m_dragTargetList!=ModelParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("cdCLibDlg::OnRclickMylist failed to destroy menu resource\n"); + pMenu = FALSE; + } + + *pResult = 0; +} + +void cdCLibDlg::OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + + *pResult = 0; +} + +void cdCLibDlg::OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptList, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptList, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + } + + *pResult = 0; +} + +void cdCLibDlg::ModifyMaterial(int k) +{ + cdCMatDlg zDlg; + + zDlg.m_ex=LibProps[k].ex; + zDlg.m_ey=LibProps[k].ey; + zDlg.m_ltx=LibProps[k].ltx; + zDlg.m_lty=LibProps[k].lty; + zDlg.m_ox=LibProps[k].ox; + zDlg.m_oy=LibProps[k].oy; + zDlg.m_BlockName=LibProps[k].BlockName; + +// for(int nn=0;nnProblemType==0){ + zDlg.m_mu1label="x"; + zDlg.m_mu2label="y"; + } + else{ + zDlg.m_mu1label="r"; + zDlg.m_mu2label="z"; + } + if(zDlg.DoModal()==IDOK){ + LibProps[k].BlockName=zDlg.m_BlockName; + LibProps[k].ex=zDlg.m_ex; + LibProps[k].ey=zDlg.m_ey; + LibProps[k].ltx=zDlg.m_ltx; + LibProps[k].lty=zDlg.m_lty; + LibProps[k].ox=zDlg.m_ox; + LibProps[k].oy=zDlg.m_oy; + } +} + +void cdCLibDlg::MouseModify() +{ + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + else{ + CLibFolderInfo dlg; + + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + dlg.m_foldername =FoldProps[k].FolderName; + dlg.m_folderurl =FoldProps[k].FolderURL; + dlg.m_foldervendor=FoldProps[k].FolderVendor; + if (dlg.DoModal()==IDOK) + { + m_mytree.SetItemText(m_dragTargetTree,dlg.m_foldername); + FoldProps[k].FolderName =dlg.m_foldername; + FoldProps[k].FolderURL =dlg.m_folderurl; + FoldProps[k].FolderVendor=dlg.m_foldervendor; + } + } + } +} + +void cdCLibDlg::OnOK() +{ + HTREEITEM hChild; + CArray &blockproplist=pDoc->blockproplist; + int k; + + // copy Model Materials into the model + blockproplist.RemoveAll(); + hChild=m_mylist.GetChildItem(ModelParent) ; + while (hChild!=NULL) + { + k=(int) m_mylist.GetItemData(hChild); + blockproplist.Add(LibProps[k]); + hChild = m_mylist.GetNextSiblingItem(hChild) ; + } + + // write Library Materials to disk + + CString LibName=BinDir+"condlib.dat"; + FILE *fp; + + if ((fp=fopen(LibName,"wt"))==NULL) return; + + hChild=m_mytree.GetChildItem(LibParent); + while(hChild!=NULL) + { + CopyItemToDisk(hChild,fp); + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fclose(fp); + + + CResizableDialog::OnOK(); +} + +void cdCLibDlg::CopyItemToDisk(HTREEITEM hItem, FILE *fp) +{ + HTREEITEM hChild; + int i =(int) m_mytree.GetItemData(hItem); + + if (IsFolder(hItem)) + { + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderName); + if(FoldProps[i].FolderURL!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderURL); + if(FoldProps[i].FolderVendor!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderVendor); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToDisk(hChild,fp) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fprintf(fp,"\n"); + } + else{ + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) LibProps[i].BlockName); + fprintf(fp," = %.17g\n",LibProps[i].ox); + fprintf(fp," = %.17g\n",LibProps[i].oy); + fprintf(fp," = %.17g\n",LibProps[i].ex); + fprintf(fp," = %.17g\n",LibProps[i].ey); + fprintf(fp," = %.17g\n",LibProps[i].ltx); + fprintf(fp," = %.17g\n",LibProps[i].lty); + fprintf(fp,"\n\n"); + } +} + +void cdCLibDlg::VendorLink() +{ + if (VendorURL!="") + ShellExecute(m_hWnd,"open",VendorURL,"","",SW_SHOWMAXIMIZED); + else + MsgBox("No URL available for %s",VendorName); +} + +void cdCLibDlg::ImportMaterials() +{ + CFileDialog *fname_dia; + CString SourceFile; + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Magnetostatic Input File (*.fem) | *.fem; *.FEM | All Files (*.*) | *.*||", + NULL); + + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + + SourceFile=fname_dia->GetPathName(); + delete[] fname_dia; + + // Add selected properties to the library; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int k; + BOOL bToLibrary=TRUE; + + if ((fp=fopen(SourceFile,"rt"))==NULL) return; + + Ancestors.RemoveAll(); + if(m_dragTargetTree!=NULL){ + // importing into the library + // put the imported materials in a new folder + Parent=m_mytree.InsertItem("Imported Materials", 0, 1, LibParent, TVI_FIRST ); + FProp.FolderName="Imported Materials"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(Parent,FoldProps.GetUpperBound()); + } + else if(m_dragTargetList!=NULL){ + Parent=ModelParent; + bToLibrary=FALSE; + } + else return; + + while (fgets(s,1024,fp)!=NULL) + { + switch(ParseLine(s,fp,MProp)) + { + case 1: + + // add a material to library + k=(int) LibProps.GetSize(); + LibProps.Add(MProp); + if(bToLibrary) + m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + else + m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + break; + + case 2: + if (bToLibrary) + { + // open a new folder + if (Parent!=NULL) Ancestors.Add(Parent); + k=(int) FoldProps.GetSize(); + FoldProps.Add(FProp); + Parent=m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + FProp.FolderName,0,1,NULL,NULL,k,Parent,NULL); + } + + break; + + case 3: + if (bToLibrary) + { + // close a folder + k=(int) Ancestors.GetUpperBound(); + if (k>=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + } + break; + + default: + + break; + } + } + + fclose(fp); +} + +BOOL cdCLibDlg::IsTailChasing(HTREEITEM hSource, HTREEITEM hDest) +{ + HTREEITEM hItem; + + hItem=hDest; + while(hItem!=NULL) + { + if(hSource==hItem) return TRUE; + hItem=m_mytree.GetParentItem(hItem); + } + + return FALSE; +} + +void cdCLibDlg::OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mylist.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=ModelParent)) + m_mylist.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetList=m_mylist.GetSelectedItem(); + m_dragTargetTree=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + +void cdCLibDlg::OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mytree.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=LibParent)) + m_mytree.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetTree=m_mytree.GetSelectedItem(); + m_dragTargetList=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + + +void cdCLibDlg::OnTimer(UINT_PTR nIDEvent) +{ + POINT pt ; + GetCursorPos ( &pt ) ; + RECT rect ; + + + // check if Library needs to be scrolled and do it; + m_mytree.GetClientRect ( &rect ) ; + m_mytree.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mytree.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + // check if Model Materials needs to be scrolled and do it; + m_mylist.GetClientRect ( &rect ) ; + m_mylist.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mylist.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + CResizableDialog::OnTimer(nIDEvent); +} + + + + + diff --git a/femm/cd_libdlg.h b/femm/cd_libdlg.h new file mode 100644 index 0000000..c621052 --- /dev/null +++ b/femm/cd_libdlg.h @@ -0,0 +1,105 @@ +#pragma once + +#include "ResizableDialog.h" + +// treetestDlg.h : header file +// + +#if !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) +#define AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// cdCLibDlg dialog + +class cdCLibDlg : public CResizableDialog +{ +// Construction +public: + cdCLibDlg(CWnd* pParent = NULL); // standard constructor + + CcdrawDoc *pDoc; + CArray LibProps; + CArray FoldProps; + CArray Ancestors; + HTREEITEM Parent; + HTREEITEM ModelParent; + HTREEITEM LibParent; + BOOL bDragFromLibrary; + CString BinDir; + CString VendorURL; + CString VendorName; + int Focus; + + int ParseLine(char *s, FILE *fp, CMaterialProp &MProp); + char* StripKey(char *c); + BOOL IsFolder(HTREEITEM hItem); + HTREEITEM CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget); + HTREEITEM CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget); + void CopyItemToDisk(HTREEITEM hItem, FILE *fp); + void VendorLink(); + void Zappit(); + void MouseModify(); + void AddNewProperty(); + void AddNewFolder(); + void ImportMaterials(); + void ModifyMaterial(int k); + BOOL IsTailChasing(HTREEITEM hSource, HTREEITEM hDest); + +// Dialog Data + //{{AFX_DATA(cdCLibDlg) + enum { IDD = IDD_TREETEST_DIALOG }; + CTreeCtrl m_mylist; + CTreeCtrl m_mytree; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCLibDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + HICON m_hIcon; + + // stuff needed to do CTreeCtrl properly + CImageList m_imageList; + BOOL m_bIsDragging; + HTREEITEM m_dragItem; + HTREEITEM m_dragTargetTree; + HTREEITEM m_dragTargetList; + + // Generated message map functions + //{{AFX_MSG(cdCLibDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTimer(UINT_PTR nIDEvent); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) + + + + + diff --git a/femm/cd_movecopy.cpp b/femm/cd_movecopy.cpp new file mode 100644 index 0000000..071ea27 --- /dev/null +++ b/femm/cd_movecopy.cpp @@ -0,0 +1,2274 @@ +// cdrawDoc.cpp : implementation of the CcdrawDoc class (continued...) +// + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cdrawView.h" +#include "cd_probdlg.h" +#include "cd_PtProp.h" +#include "cd_OpBlkDlg.h" +#include "cd_OpNodeDlg.h" +#include "cd_OpSegDlg.h" +#include "cd_OpArcSegDlg.h" +#include "ArcDlg.h" +#include "DXFImport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern BOOL bLinehook; +//----------------------------------------------------------------- + +BOOL CcdrawDoc::ReadDXF(CString fname,double DefTol) +{ + FILE *fp; + int j,k; + CArray layerlist; + CString myLayer; + + if( (fp=fopen(fname,"rt"))==NULL ) return FALSE; + NoDraw=TRUE; + + // clear out any old drawing that we might have; +// 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(); + + char s[256]; + char v[256]; + BOOL PolylineFlag=FALSE; + CNode n[4]; + CSegment segm; + CArcSegment asegm; + CComplex c,p,q; + double R,a0,a1; + int xx,PolyLineClosed,firstpoint; + double angle=0; + + while (fgets(s,256,fp)!=NULL) + { + if (strncmp(s,"LAYER",5)==0) + { + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==2){ + sscanf(v,"%s",s); + myLayer=s; + layerlist.Add(myLayer); + } + } while(1>0); + } + + if (strncmp(s,"POINT",5)==0) + { + xx=0; + n[0].InGroup=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==10) { n[0].x=atof(v); xx=xx | 1; } + if (k==20) { n[0].y=atof(v); xx=xx | 2; } + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + if (xx==3) nodelist.Add(n[0]); + } + + if (strncmp(s,"LWPOLYLINE",10)==0) + { + int segs=0; + PolyLineClosed=FALSE; + firstpoint=-1; + angle = 0; + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + int n0,n1; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) angle=360.; + } + if (k==70) PolyLineClosed=TRUE; + if (xx==3){ + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + xx=0; + if(segs==0) firstpoint=j; + else{ + if(angle==0) + { + segm.n0=j; + segm.n1=j-1; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j-1; n1=j; } + else{ n0=j; n1=j-1; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + if ((PolyLineClosed==TRUE) && (firstpoint>=0) && (segs>0)) + { + // take care of closing the contour, if required. + j=(int) nodelist.GetSize()-1; + if(angle==0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + angle=0; + } + } + } + + + if (strncmp(s,"POLYLINE",8)==0) + { + PolylineFlag=-1; + firstpoint=-1; + PolyLineClosed=FALSE; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==70) { + j=atoi(v); + if (j==1) PolyLineClosed=TRUE; + } + } while(1>0); + + } + + if (strncmp(s,"SEQEND",6)==0) + { + PolylineFlag=FALSE; + int j = ((int) nodelist.GetSize())-1; + if ((PolyLineClosed==TRUE) && (firstpoint>=0)) + { + if (angle == 0.0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else + { + int n0, n1; + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + } + } + PolyLineClosed=FALSE; + angle = 0.0; + } + + if (strncmp(s,"VERTEX",6)==0) + { + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + double next_angle = 0.0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) next_angle=360.; + } + } while(1>0); + + if(xx==3) + { + nodelist.Add(n[0]); + if (angle != 0.0) + { + j = (int)nodelist.GetSize(); + + int n0, n1; + if(angle>0) { n0=j-2; n1=j-1; } + else{ n0=j-1; n1=j-2; angle=fabs(angle); } + + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + + if (xx==15) + { + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + segm.n0=j; segm.n1=j+1; + linelist.Add(segm); + } + } + + // catch ARCALIGNEDTEXT, which derails the ARC code... + if (strncmp(s,"ARCA",4)==0) s[0]=NULL; + + if (strncmp(s,"ARC",3)==0) + { + n[0].InGroup=0; + n[1].InGroup=0; + asegm.InGroup=0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + + if(xx==31) + { + if (a10); + + if(xx==7) + { + n[0].x=c.re+R; n[1].x=c.re-R; + n[0].y=c.im; n[1].y=c.im; + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + asegm.n0=j; asegm.n1=j+1; + asegm.MaxSideLength=5.; + asegm.ArcLength=180.; + arclist.Add(asegm); + asegm.n1=j; asegm.n0=j+1; + arclist.Add(asegm); + } + } + + } + + fclose(fp); + + // could be that nothing actually got read. We want to + // catch this case and tell the user about it. + if(nodelist.GetSize()==0) return FALSE; + + // suggest the proper tolerance + CComplex p0,p1; + CDXFImport dlg; + int i; + + p0=nodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=nodelist[i].x; + if(nodelist[i].yp1.im) p1.im=nodelist[i].y; + } + + R=abs(p1-p0)*1.e-04; + dlg.m_dxftol=floor(R/pow(10.,floor(log10(R))))*pow(10.,floor(log10(R))); + + if(DefTol<0) + { + dlg.DoModal(); + FancyEnforcePSLG(dlg.m_dxftol); + } + else + { + if (DefTol==0) DefTol=dlg.m_dxftol; + FancyEnforcePSLG(DefTol); + } + + NoDraw=FALSE; + + return TRUE; +} + +void CcdrawDoc::RotateMove(CComplex c, double t, int EditAction) +{ + int i; + CComplex x,z; + + z=exp(I*t*PI/180); + + if(EditAction==0) + { + for(i=0;i newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i; + CComplex p0,p1; + double d; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the nodes; + for(i=0;i newnodes; + + newnodes.RemoveAll(); + + n0=ClosestNode(p0.re,p0.im); + n1=ClosestNode(p1.re,p1.im); + + // 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;i 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;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;iextmaxx) extmaxx=nodelist[i].x; + if(nodelist[i].yextmaxy) extmaxy=nodelist[i].y; + } + + } + + for(i=0;iextmaxx) extmaxx=p.re; + if(p.imextmaxy) 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 newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i,k; + CComplex p0,p1; + double d; + + bLinehook=ImportDXF; // kludge to stop the program from giving a crash if + // the user tries to exit during a dxf import. + + CcdrawView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + pView=(CcdrawView *)GetNextView(pos); + + FirstDraw=TRUE; +// pView->lua_zoomnatural(); + dxf_line_hook(); + pView->EditAction=4; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;iInvalidateRect(NULL); + dxf_line_hook(); + + // find out what tolerance is so that there are not nodes right on + // top of each other; + if(tol==0){ + if (newnodelist.GetSize()<2) d=1.e-08; + else{ + p0=newnodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the lines; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + // put in all of the arcs; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + UnselectAll(); + + // do one last check to eliminate shallow arcs that + // link up the same two points as a line segment; + for(i=0;i +#include +#include "cd_nosebl.h" +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + InGroup=0; + BoundaryMarker=""; + InConductor=""; +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CComplex CNode::CC() +{ + return CComplex(x,y); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + MaxSideLength=-1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + ArcLength=90.; + MaxSideLength=10.; + mySideLength=1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; + NormalDirection=TRUE; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + BlockType=""; + InGroup=0; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + ox=oy=0.; // electrical conductivity, MS/m + ex=ey=1.; // electrical permittivity, relative + ltx=lty=0; // loss tangent of electrial permittivity +} + +CMaterialProp::~CMaterialProp() +{ + +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; // type of boundary condition we are applying + c0=0; + c1=0; + vs=0; + qs=0; + +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + vp=0; // nodal voltage + qp=0; // point current density +} + +CCircuit::CCircuit() +{ + CircName="New Conductor"; + vc=0; + qc=0; + CircType=0; +}; + +CPeriodicBoundary::CPeriodicBoundary() +{ + BdryName=""; + BdryFormat=0; + nseg=0; + narc=0; + seg[0]=0; + seg[1]=0; +} + +CCommonPoint::CCommonPoint() +{ + x=y=t=0; +} + +void CCommonPoint::Order() +{ + int z; + + if(x>y){ + z=y; + y=x; + x=z; + } +} diff --git a/femm/cd_nosebl.h b/femm/cd_nosebl.h new file mode 100644 index 0000000..2185d4c --- /dev/null +++ b/femm/cd_nosebl.h @@ -0,0 +1,185 @@ +namespace cdrawdata +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL NormalDirection; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength,mySideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + BOOL IsSelected; + CString BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CMaterialProp(); + ~CMaterialProp(); + + CString BlockName; + double ex,ey; // relative permittivity for (possibly anisotropic) regions + double ltx,lty; // loss tangent related to the permittivity + double ox,oy; // conductivity in MS/m + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + int BdryFormat; // type of boundary condition we are applying + // 0 = Fixed Voltage + // 1 = Mixed BC + // 2 = Surface Current Density + // 3 = Periodic + // 4 = Antiperiodic + + CComplex vs; // Fixed value of V for BdryFormat=0; + CComplex c0,c1; // Coefficients for BdryFormat=1; + CComplex qs; // Surface current density for Bdryformat=2; + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + CComplex vp; // prescribed nodal temperature + CComplex qp; // point heat generation + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + CComplex vc; + CComplex qc; + int CircType; + + private: + +}; + +class CPeriodicBoundary +{ + public: + + CPeriodicBoundary(); + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + int nseg; // number of segs with this bc + int narc; // number of arcs with this bc + int seg[2]; // (arc)segments to which is applied + + private: +}; + +class CCommonPoint +{ + public: + + CCommonPoint(); + void Order(); + + int x,y,t; + + private: +}; + +} + +using namespace cdrawdata; diff --git a/femm/cd_probdlg.cpp b/femm/cd_probdlg.cpp new file mode 100644 index 0000000..b9bbe56 --- /dev/null +++ b/femm/cd_probdlg.cpp @@ -0,0 +1,99 @@ +// probdlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cd_probdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// probdlg dialog + + +cdCProbDlg::cdCProbDlg(CWnd* pParent /*=NULL*/) + : CDialog(cdCProbDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cdCProbDlg) + m_problem_note = _T(""); + m_precision = 1.e-8; + m_depth = 1.0; + m_minangle=DEFAULT_MINIMUM_ANGLE; + m_frequency=0.; + //}}AFX_DATA_INIT +} + + +void cdCProbDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cdCProbDlg) + DDX_Control(pDX, IDC_CD_LENGTH_UNITS, m_length_units); + DDX_Control(pDX, IDC_BSMART, m_bsmart); + DDX_Control(pDX, IDC_CD_PROBTYPE, m_probtype); + DDX_Text(pDX, IDC_CD_PROBNOTE, m_problem_note); + DDX_Text(pDX, IDC_CD_EDIT_FREQ, m_frequency); + DDX_Text(pDX, IDC_CD_PRC, m_precision); + DDV_MinMaxDouble(pDX, m_precision, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_CD_MINANG, m_minangle); + DDV_MinMaxDouble(pDX, m_minangle, 1., MINANGLE_MAX); + DDX_Text(pDX, IDC_CD_EDIT_DEPTH, m_depth); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CD_EDIT_DEPTH, m_IDC_depth); + DDX_Control(pDX, IDC_CD_PROBNOTE, m_IDC_problem_note); + DDX_Control(pDX, IDC_CD_PRC, m_IDC_precision); + DDX_Control(pDX, IDC_CD_EDIT_FREQ, m_IDC_freq); +} + + +BEGIN_MESSAGE_MAP(cdCProbDlg, CDialog) + //{{AFX_MSG_MAP(cdCProbDlg) + ON_CBN_SELCHANGE(IDC_CD_LENGTH_UNITS, OnSelchangeLengthUnits) + ON_CBN_SELCHANGE(IDC_CD_PROBTYPE, OnSelchangeProbtype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// probdlg message handlers + +BOOL cdCProbDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_probtype.SetCurSel(probtype); + if(probtype) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); + + m_length_units.SetCurSel(lengthunits); + m_bsmart.SetCurSel(bsmart); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cdCProbDlg::OnOK() +{ + if (UpdateData()==FALSE) return; + probtype=m_probtype.GetCurSel(); + if(probtype) m_depth=1; + UpdateData(FALSE); + lengthunits=m_length_units.GetCurSel(); + bsmart=m_bsmart.GetCurSel(); + CDialog::OnOK(); +} + +void cdCProbDlg::OnSelchangeLengthUnits() +{ + +} + +void cdCProbDlg::OnSelchangeProbtype() +{ + if(m_probtype.GetCurSel()) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); +} diff --git a/femm/cd_probdlg.h b/femm/cd_probdlg.h new file mode 100644 index 0000000..02ab92b --- /dev/null +++ b/femm/cd_probdlg.h @@ -0,0 +1,52 @@ +// cd_CProbDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cdCProbDlg dialog + +class cdCProbDlg : public CDialog +{ +// Construction +public: + cdCProbDlg(CWnd* pParent = NULL); // standard constructor + + BOOL probtype; // variable denoting problem type + // so list entry can be correctly set + int lengthunits; // contains units of length; + int bsmart; + +// Dialog Data + //{{AFX_DATA(cdCProbDlg) + enum { IDD = IDD_CD_PROBDLG }; + CComboBox m_length_units; + CComboBox m_bsmart; + CComboBox m_probtype; + CString m_problem_note; + double m_precision; + double m_minangle; + double m_depth; + double m_frequency; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cdCProbDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cdCProbDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeLengthUnits(); + afx_msg void OnSelchangeProbtype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_problem_note, m_IDC_precision, m_IDC_depth, m_IDC_minangle, m_IDC_freq; +}; diff --git a/femm/cd_writepoly.cpp b/femm/cd_writepoly.cpp new file mode 100644 index 0000000..91e5d6a --- /dev/null +++ b/femm/cd_writepoly.cpp @@ -0,0 +1,1546 @@ +// implementation of various incarnations of calls +// to triangle from the CcdrawDoc class + +#include "stdafx.h" +#include "femm.h" +#include "cdrawDoc.h" +#include "cd_probdlg.h" +#include "cd_PtProp.h" +#include "cd_OpBlkDlg.h" +#include "cd_OpNodeDlg.h" +#include "cd_OpSegDlg.h" +#include "cd_OpArcSegDlg.h" +#include "OpGrp.h" +#include "ArcDlg.h" + +extern BOOL bLinehook; +extern lua_State *lua; +extern HANDLE hProc; + +double CcdrawDoc::LineLength(int i) +{ + return abs(nodelist[linelist[i].n0].CC()- + nodelist[linelist[i].n1].CC()); +} + + +BOOL CcdrawDoc::HasPeriodicBC() +{ + BOOL flag=FALSE; + int i,j,k; + + for(i=0;i=0){ + if ((lineproplist[k].BdryFormat==3) || + (lineproplist[k].BdryFormat==4)) + { + 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==3) || + (lineproplist[k].BdryFormat==4)) + { + 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 CcdrawDoc::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 CcdrawDoc::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 +#include +#include "cdrawDoc.h" +#include "cdrawView.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "GRIDDLG.h" +#include "EnterPt.h" +#include "KbdZoom.h" +#include "ArcDlg.h" +#include "CopyDlg.h" +#include "scaledlg.h" +#include "MirrorDlg.h" +#include "GroupNumber.h" +#include "cd_libdlg.h" +#include "PromptBox.h" +#include "MakeABCDlg.h" + +#include + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +extern lua_State * lua; +extern BOOL bLinehook; +extern HANDLE hProc; + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView + +IMPLEMENT_DYNCREATE(CcdrawView, CView) + +BEGIN_MESSAGE_MAP(CcdrawView, CView) + //{{AFX_MSG_MAP(CcdrawView) + ON_COMMAND(ID_NODE_OP, OnNodeOp) + ON_COMMAND(ID_SEGMENT_OP, OnSegmentOp) + ON_COMMAND(ID_BLOCK_OP, OnBlockOp) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_WM_KEYDOWN() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWnd) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_MAKE_MESH, OnMakeMesh) + ON_COMMAND(ID_MENU_ANALYZE, OnMenuAnalyze) + ON_COMMAND(ID_MENU_VIEWRES, OnMenuViewres) + ON_COMMAND(ID_ARCSEG_OP, OnArcsegOp) + ON_COMMAND(ID_UNDO, OnUndo) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_COMMAND(ID_MOVE_OBJECTS, OnMoveObjects) + ON_COMMAND(ID_COPY_OBJECTS, OnCopyObjects) + ON_COMMAND(ID_DXFIN, OnDxfin) + ON_COMMAND(ID_PURGEMESH, OnPurgemesh) + ON_COMMAND(ID_DXFWRITE, OnDxfwrite) + ON_COMMAND(ID_SELECTWND, OnSelectwnd) + ON_COMMAND(ID_SELECTCIRC, OnBDSelectCirc) + ON_WM_ERASEBKGND() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_MENU_MATLIB, OnMenuMatlib) + ON_COMMAND(ID_GROUP_OP, OnGroupOp) + ON_COMMAND(ID_OPEN_SELECTED, OnOpenSelected) + ON_COMMAND(ID_EDIT_SCALE, OnEditScale) + ON_COMMAND(ID_EDIT_MIRROR, OnEditMirror) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames) + ON_COMMAND(ID_VIEW_SHOWORPHANS, OnViewShowOrphans) + ON_COMMAND(ID_CREATERADIUS, OnCreateRadius) + ON_UPDATE_COMMAND_UI(ID_EDIT_EXTERIOR, OnUpdateEditExterior) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_COMMAND(ID_EDIT_CREATEOPENBOUNDARY, &CcdrawView::OnMakeABC) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView construction/destruction + +CcdrawView::CcdrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // Default Colors + SelColor = RGB(255,0,0); + MeshColor = RGB(213,228,20); + BlockColor = RGB(0,125,0); + LineColor = RGB(0,0,255); + GridColor = RGB(0,0,255); + NodeColor = RGB(0,0,0); + BackColor = RGB(255,255,255); + NameColor = RGB(0,0,0); + + // assume some default behaviors if they can't be + // loaded from disk + d_action=0; + d_mag=100.; + d_gridsize=0.25; + d_showgrid=TRUE; + d_snapgrid=FALSE; + d_showorigin=FALSE; + d_shownames=TRUE; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // now, set default look for the preprocessor; + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + MaxSeg = 1.0; + ArcAngle = 90.0; +} + +void CcdrawView::OnNewDocument() +{ + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) return; + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + if (StatBar==NULL) return; + + // update check boxes in the main menu... + EditAction=d_action; + GridFlag=d_showgrid; + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(d_action==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(d_action==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(d_action==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(d_action==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(d_action==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(d_showgrid==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(d_snapgrid==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(d_shownames==TRUE) + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); +} + +CcdrawView::~CcdrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL CcdrawView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView drawing + +void CcdrawView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +void CcdrawView::DrawPSLG() +{ + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen,penMesh; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penBlack.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + + CcdrawDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + + // make sure all the right boxes are checked. + { + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r); + if(d_showorigin==TRUE) + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penBlack ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlack ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw node block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + + ReleaseDC(pDC); +} + +BOOL CcdrawView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CcdrawView::OnDraw(CDC* pDC) +{ + CcdrawDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if(pDoc->NoDraw==TRUE) return; + + // TODO: add draw code for native data here + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + if (pDoc->FirstDraw==TRUE) OnZoomNatural(); + + CPen *pOldPen; + CPen penBlue,penRed,penNode,penGreen,penMesh,penGrey; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penGrey.CreatePen(PS_SOLID,1,RGB(220,220,220)); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=1.1; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + if(MeshFlag==TRUE) + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penNode ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->meshline[i].x].xs, + pDoc->meshnode[pDoc->meshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->meshline[i].y].xs, + pDoc->meshnode[pDoc->meshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + + pOldPen = pDC->SelectObject( &penGrey ); + for(i=0;igreymeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].x].xs, + pDoc->meshnode[pDoc->greymeshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].y].xs, + pDoc->meshnode[pDoc->greymeshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + } + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +void CcdrawView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + EditAction=d_action; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + CheckIt(); +} + +void CcdrawView::CheckIt() +{ + // once again, this is sort of a punt + // to make sure that the right buttons + // are checked. It can be relatively + // easy to change the internal flags + // associated with the buttons without + // taking the time to service the button + // state otherwise. + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame()"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + + // update check boxes in the main menu... + + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(EditAction==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(EditAction==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(EditAction==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(EditAction==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(EditAction==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(GridFlag==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(SnapFlag==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(ShowNames==TRUE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView printing + +BOOL CcdrawView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CcdrawView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CcdrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView diagnostics + +#ifdef _DEBUG +void CcdrawView::AssertValid() const +{ + CView::AssertValid(); +} + +void CcdrawView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CcdrawDoc* CcdrawView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CcdrawDoc))); + return (CcdrawDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CcdrawView message handlers + +void CcdrawView::OnNodeOp() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,TRUE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CcdrawView::OnSegmentOp() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=1; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,TRUE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CcdrawView::OnArcsegOp() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=3; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,TRUE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} +void CcdrawView::OnBlockOp() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,TRUE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + + +void CcdrawView::OnGroupOp() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=4; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,TRUE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void CcdrawView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CcdrawDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ( (SnapFlag==TRUE) && ((EditAction==0) || (EditAction==2)) ) + { + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + if((ZoomWndFlag==2) || (SelectWndFlag==2)){ + + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + + } + + if(SelectCircFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + double R; + CComplex q; + + int xso,yso,xsi,ysi,xsn,ysn,i,k; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old circle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + R=abs((xso-xsn)+I*(yso-ysn)); + for(i=1;i<=(int)(2.*PI*R);i++){ + q=R*exp(I*((double) i)/R)+(xso+I*yso); + ocol=pDC->GetPixel((int) Re(q),(int) Im(q)); + p.c=ocol; p.x=(int) Re(q); p.y=(int) Im(q); + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel((int) Re(q),(int) Im(q),ocol); + } + + ReleaseDC(pDC); + + } + + // update mouse location; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CcdrawView::OnZoomIn() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + InvalidateRect(NULL); +} + +void CcdrawView::OnZoomOut() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + InvalidateRect(NULL); +} + +BOOL CcdrawView::GetBoundingBox(double *x, double *y) +{ + // look at points, block labels, and arcs to get bounding box. + CcdrawDoc *pDoc=GetDocument(); + int i,j,k; + double R,dt; + CComplex p,s,c; + + if (pDoc->nodelist.GetSize()<2) return FALSE; + + x[0]=pDoc->nodelist[0].x; x[1]=pDoc->nodelist[0].x; + y[0]=pDoc->nodelist[0].y; y[1]=pDoc->nodelist[0].y; + for(i=1;inodelist.GetSize();i++) + { + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + { + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;iarclist.GetSize();i++) + { + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + return TRUE; +} + +void CcdrawView::OnZoomNatural() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + + if (GetBoundingBox(x,y)==FALSE) return; + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0]) > (y[1]-y[0])) w=(x[1]-x[0]); + else w=(y[1]-y[0]); + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-0.5)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) + pDoc->FirstDraw=FALSE; + else InvalidateRect(NULL); +} + +void CcdrawView::OnBDSelectCirc() +{ + SelectCircFlag=TRUE; + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,TRUE); +} + +void CcdrawView::OnZoomWnd() +{ + // TODO: Add your command handler code here + ZoomWndFlag=TRUE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; +} + +void CcdrawView::OnSelectwnd() +{ + // TODO: Add your command handler code here + SelectWndFlag=TRUE; + SelectCircFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,TRUE); +} + +void CcdrawView::OnShowGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + + InvalidateRect(NULL); +} + +void CcdrawView::OnSetGrid() +{ + // TODO: Add your command handler code here + GRIDDLG pDlg; + CcdrawDoc *pDoc=GetDocument(); + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + InvalidateRect(NULL); + } +} + +void CcdrawView::OnSnapGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CcdrawView::OnShowMesh() +{ + // TODO: Add your command handler code here + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + } + else if(MeshUpToDate==TRUE){ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + } + InvalidateRect(NULL); +} + +void CcdrawView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CcdrawView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void CcdrawView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Add your message handler code here and/or call default + // VK_TAB, VK_DELETE -- ones that we want to catch + CcdrawDoc *pDoc=GetDocument(); + + if (((nChar=='z') || (nChar=='Z')) && (GetKeyState(VK_CONTROL))) OnUndo(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if (nChar==VK_TAB) + { + if ((EditAction==0) || (EditAction==2)) EnterPoint(); + if (EditAction==4) + { + CGroupNumber dlg; + dlg.m_groupnumber=0; + if(dlg.DoModal()==IDOK) + { + int i,j; + j=dlg.m_groupnumber; + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + } + + if (nChar==VK_DELETE) OnEditCut(); + + if (nChar==VK_SPACE) OnOpenSelected(); + + if (nChar==VK_ESCAPE){ + pDoc->UnselectAll(); + FirstPoint=-1; + ZoomWndFlag=0; + SelectWndFlag=0; + SelectCircFlag=0; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + DrawPSLG(); + } + + if (nChar==VK_F3) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if (GetBoundingBox(x,y)!=FALSE) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + for (i=0;iblocklist.GetSize();i++) + { + if (pDoc->blocklist[i].MaxArea>0) pDoc->blocklist[i].MaxArea/=4.; + else if (pDoc->SmartMesh) pDoc->blocklist[i].MaxArea=DefaultMeshSize/4.; + } + InvalidateRect(NULL); + } + + if (nChar==VK_F4) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if ((GetBoundingBox(x,y)!=FALSE) && (pDoc->SmartMesh)) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + + for (i=0;iblocklist.GetSize();i++) + { + pDoc->blocklist[i].MaxArea*=4.; + if ((pDoc->blocklist[i].MaxArea>DefaultMeshSize) && (DefaultMeshSize>0)) + pDoc->blocklist[i].MaxArea=DefaultMeshSize; + } + InvalidateRect(NULL); + } + + // Call to base class... + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CcdrawView::EnterPoint() +{ + // TODO: Add your command handler code here + CEnterPt pDlg; + double x,y,t,d; + int i; + CcdrawDoc* pDoc = GetDocument(); + BOOL flag; + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + pDoc->UpdateUndo(); + + if (pDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=pDoc->nodelist[0].CC(); + p1=p0; + for(i=1;inodelist.GetSize();i++) + { + p2=pDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(x,y,d); + } + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(x,y,d); + } + + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } +} + +void CcdrawView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonDown(nFlags, point); + return; + } + + BOOL flag; + CcdrawDoc* pDoc = GetDocument(); + + if (CreateRadiusFlag==TRUE) + { + int k; + double r; + + CreateRadiusFlag=FALSE; + if ((k=pDoc->ClosestNode(mx,my))<0) return; // catch case where no nodes have been drawn yet; + if (pDoc->CanCreateRadius(k)==FALSE) + { + MsgBox("The specified point is not suitable for\nconversion into a radius"); + return; + } + + CPromptBox dlg; + dlg.mytitle = "Enter desired radius dimension:"; + if (dlg.DoModal()==IDOK) + { + r=dlg.ParseDouble(); + if (r>0){ + if (pDoc->CreateRadius(k,r)) + { + InvalidateRect(NULL); + MeshUpToDate=FALSE; + } + else MsgBox("Could not make a radius of the prescribed dimension"); + } + } + + return; + } + + if (SelectWndFlag==1) + { + ZoomPix.RemoveAll(); + SelectWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectWndFlag==2) return; + + if (SelectCircFlag==1) + { + ZoomPix.RemoveAll(); + SelectCircFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectCircFlag==2) return; + + if (ZoomWndFlag==1) + { + ZoomPix.RemoveAll(); + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(mx,my,1./mag); + if (flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==1){ + if (FirstPoint<0){ + if(pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + pDoc->nodelist[FirstPoint].ToggleSelect(); + pDoc->UpdateUndo(); + flag=pDoc->AddSegment(FirstPoint,pDoc->ClosestNode(mx,my)); + FirstPoint=-1; + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(mx,my,1./mag); + if(flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==3){ + if (FirstPoint<0){ + if (pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + CArcSegment asegm; + CArcDlg dlg; + asegm.n0=FirstPoint; + asegm.n1=pDoc->ClosestNode(mx,my); + pDoc->nodelist[asegm.n1].ToggleSelect(); + DrawPSLG(); + + for(int k=0;klineproplist.GetSize();k++) + dlg.namelist.Add(pDoc->lineproplist[k].BdryName); + + dlg.cursel=0; + dlg.m_MaxSeg=MaxSeg; + dlg.m_ArcAngle=ArcAngle; + if (dlg.DoModal()==IDCANCEL){ + FirstPoint=-1; + pDoc->UnselectAll(); + DrawPSLG(); + return; + } + MaxSeg = asegm.MaxSideLength = dlg.m_MaxSeg; + ArcAngle = asegm.ArcLength=dlg.m_ArcAngle; + if (dlg.cursel==0) asegm.BoundaryMarker=""; + else asegm.BoundaryMarker=pDoc->lineproplist[dlg.cursel-1].BdryName; + + pDoc->UpdateUndo(); + flag=pDoc->AddArcSegment(asegm); + flag=FALSE; + FirstPoint=-1; + pDoc->UnselectAll(); + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + CView::OnLButtonDown(nFlags, point); +} + +void CcdrawView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag==2){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + RECT r; + double z,m[2]; + if (mxGetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + int i,k; + double x,y,z; + CcdrawDoc *pDoc=GetDocument(); + SelectWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + if (SelectCircFlag==2){ + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,FALSE); + + int i,k; + double R; + CComplex c,q; + CcdrawDoc *pDoc=GetDocument(); + SelectCircFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + + R=abs((mx-wzx)+I*(my-wzy)); + c=wzx+I*wzy; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + CView::OnLButtonUp(nFlags, point); +} + +void CcdrawView::OnRButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnRButtonDown(nFlags, point); + return; + } + + CcdrawDoc* pDoc = GetDocument(); + int i,j; + + //toggle select of nearest point + if(EditAction==0){ + j=pDoc->ClosestNode(mx,my); + if(j>=0) pDoc->nodelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest segment + if(EditAction==1){ + j=pDoc->ClosestSegment(mx,my); + if(j>=0) pDoc->linelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest arc segment + if(EditAction==3){ + j=pDoc->ClosestArcSegment(mx,my); + if(j>=0) pDoc->arclist[j].ToggleSelect(); + DrawPSLG(); + } + //toggle select of nearest blocklabel + if(EditAction==2){ + j=pDoc->ClosestBlockLabel(mx,my); + if(j>=0) pDoc->blocklist[j].ToggleSelect(); + DrawPSLG(); + } + + if(EditAction==4){ + int clnode,clseg,claseg,cllbl; + double dnode,dseg,daseg,dlbl,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // find distance to closest block label; + cllbl=pDoc->ClosestBlockLabel(mx,my); + if(cllbl>=0) dlbl=pDoc->blocklist[cllbl].GetDistance(mx,my); + else dlbl=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InGroup; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InGroup; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InGroup; + } + if ((dlbl=0)){ + d=dlbl; + j=pDoc->blocklist[cllbl].InGroup; + } + + if (j<1) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CcdrawView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CView::OnLButtonDblClk(nFlags, point); +} + +void CcdrawView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + + CcdrawDoc *pDoc=GetDocument(); + if (EditAction==0) + { + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + int j; + CString ss; + + sprintf(s,"Closest node: (%g,%g)\n",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + ss+=s; + + ss+="Nodal Property: "; + sprintf(s,"\n"); + for(j=0;jnodeproplist.GetSize();j++) + { + if(pDoc->nodeproplist[j].PointName== + pDoc->nodelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->nodelist[i].BoundaryMarker); + } + } + ss+=s; + + sprintf(s,"In Group: %i\n",pDoc->nodelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->nodelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->nodelist[i].InConductor); + } + } + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->nodelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==1) + { + int i=pDoc->ClosestSegment(mx,my); + int j; + CString ss; + + if(i>=0){ + char s[256]; + sprintf(s,"Length of closest segment: %g\n", + pDoc->LineLength(i)); + + ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->linelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->linelist[i].BoundaryMarker); + } + } + ss+=s; + + ss+="Grid spacing: "; + if (pDoc->linelist[i].MaxSideLength<=0) + sprintf(s,"\n"); + else sprintf(s,"%g\n",pDoc->linelist[i].MaxSideLength); + ss+=s; + sprintf(s,"In Group: %i\n",pDoc->linelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->linelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->linelist[i].InConductor); + } + } + ss+=s; + + if(pDoc->linelist[i].Hidden==TRUE) + ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->linelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==2) + { + int i=pDoc->ClosestBlockLabel(mx,my); + int j,k; + if(i>=0){ + char s[256]; + sprintf(s,"Closest block label: (%g,%g)\n",pDoc->blocklist[i].x, + pDoc->blocklist[i].y); + CString ss=s; + ss+="Block Material: "; + k=-1; + sprintf(s,"\n"); + if (pDoc->blocklist[i].BlockType=="") + { + sprintf(s,"\n"); + } + else for(j=0;jblockproplist.GetSize();j++) + { + if(pDoc->blockproplist[j].BlockName== + pDoc->blocklist[i].BlockType) + { + sprintf(s,"%s\n", (const char *) pDoc->blocklist[i].BlockType); + k=j; + } + } + ss+=s; + + ss+="Mesh size: "; + if (pDoc->blocklist[i].MaxArea==0) + sprintf(s,"\n"); + else sprintf(s,"%g\n", + floor(2.e07*sqrt(pDoc->blocklist[i].MaxArea/PI) + +0.5)/1.e07 ); + ss+=s; + + sprintf(s,"In Group: %i",pDoc->blocklist[i].InGroup); + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==3) + { + int i=pDoc->ClosestArcSegment(mx,my); + if(i>=0){ + char s[256]; + CString ss; + int j; + double R; + CComplex c; + + sprintf(s,"Angle spanned by closest arc: %g deg\n", + pDoc->arclist[i].ArcLength); ss+=s; + pDoc->GetCircle(pDoc->arclist[i],c,R); + c=Chop(c); + sprintf(s,"Radius of associated circle: %g\n",R); ss+=s; + sprintf(s,"Center of associated circle: (%g,%g)\n",Re(c),Im(c)); ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->arclist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->arclist[i].BoundaryMarker); + } + } + ss+=s; + sprintf(s,"Grid spacing: %g deg\n",pDoc->arclist[i].MaxSideLength); ss+=s; + sprintf(s,"In Group: %i\n",pDoc->arclist[i].InGroup); ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->arclist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->arclist[i].InConductor); + } + } + ss+=s; + + if(pDoc->arclist[i].Hidden==TRUE) ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->arclist[i].ToggleSelect(); + DrawPSLG(); + } + } + CView::OnRButtonDblClk(nFlags, point); +} + +void CcdrawView::OnMakeMesh() +{ + CcdrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved."); + return; + } + + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + BOOL LoadMesh=TheDoc->LoadMesh(); + if (bLinehook==FALSE) EndWaitCursor(); + + if(LoadMesh==TRUE){ + MeshUpToDate=TRUE; + if(MeshFlag==FALSE) OnShowMesh(); + else InvalidateRect(NULL); + CString s; + s.Format("Created mesh with %i nodes",TheDoc->meshnode.GetSize()); + if (TheDoc->greymeshline.GetSize()!=0) + s+="\nGrey mesh lines denote regions\nthat have no block label."; + if(bLinehook==FALSE) AfxMessageBox(s,MB_ICONINFORMATION); + else lua_pushnumber(lua,(int) TheDoc->meshnode.GetSize()); + } + +} + +void CcdrawView::OnMenuAnalyze() +{ + + int i,j,k; + CcdrawDoc *TheDoc = GetDocument(); + BOOL bFlag=FALSE; + BOOL bExteriorDefined=TRUE; + + ASSERT_VALID(TheDoc); + + // check to see if all blocklabels are kosher... + if (TheDoc->blocklist.GetSize()==0){ + MsgBox("No block information has been defined\nCannot analyze the problem"); + return; + } + + for(i=0,bFlag=FALSE;iblocklist.GetSize();i++) + { + for(k=0,j=0;kblockproplist.GetSize();k++) + if (TheDoc->blocklist[i].BlockType!=TheDoc->blockproplist[k].BlockName) j++; + if((j==TheDoc->blockproplist.GetSize()) && (TheDoc->blocklist[i].BlockType!="")) + { + if(bFlag==FALSE) OnBlockOp(); + bFlag=TRUE; + TheDoc->blocklist[i].IsSelected=TRUE; + } + } + + if(bFlag==TRUE){ + InvalidateRect(NULL); + CString ermsg="Material properties have not\n"; + ermsg+= "been defined for all block labels\n"; + ermsg+= "cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + + + + // check to see if all of the input points are on r>=0 for axisymmetric problems. + if(TheDoc->ProblemType==1) + { + for(k=0;knodelist.GetSize();k++) + if(TheDoc->nodelist[k].x<-(1.e-6)) + { + InvalidateRect(NULL); + CString ermsg="The problem domain must lie in\n"; + ermsg+= "r>=0 for axisymmetric problems.\n"; + ermsg+= "Cannot analyze the problem."; + MsgBox(ermsg); + return; + } + + + // check to see if all block defined to be in an axisymmetric external region are isotropic + for(k=0;kblocklist.GetSize();k++) + { + if(TheDoc->blocklist[k].IsExternal){ + if ((TheDoc->extRi==0) || (TheDoc->extRo==0)) bExteriorDefined=FALSE; + for(i=0;iblockproplist.GetSize();i++) + if(TheDoc->blocklist[k].BlockType==TheDoc->blockproplist[i].BlockName) + { + if(TheDoc->blockproplist[i].ox!=TheDoc->blockproplist[i].oy) bFlag=TRUE; + if(TheDoc->blockproplist[i].ex!=TheDoc->blockproplist[i].ey) bFlag=TRUE; + if(TheDoc->blockproplist[i].ltx!=TheDoc->blockproplist[i].lty) bFlag=TRUE; + } + } + } + if(bFlag) + { + InvalidateRect(NULL); + CString ermsg="Only istropic materials are allowed\n"; + ermsg+= "in axisymmetric external regions.\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + if(!bExteriorDefined) + { + InvalidateRect(NULL); + CString ermsg="Some block labels have been specific as placed in\n"; + ermsg+= "an axisymmetric exterior region, but no properties\n"; + ermsg+= "have been adequately defined for the exterior region\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + } + + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved.",MB_OK | MB_ICONEXCLAMATION,0); + return; + } + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + if (bLinehook==FALSE) EndWaitCursor(); + + char CommandLine[512]; + CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; + + if(bLinehook==FALSE) + sprintf(CommandLine,"\"%scsolv.exe\" %s", (const char *) BinDir, (const char *) rootname); + else + sprintf(CommandLine,"\"%scsolv.exe\" %s bLinehook", (const char *) BinDir, (const char *) rootname); + + CString MyPath=pn.Left(pn.ReverseFind('\\')); + + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + StartupInfo2.dwFlags = STARTF_FORCEOFFFEEDBACK; + if(bLinehook==HiddenLua){ + StartupInfo2.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK; + // SHOWNOACTIVATE doesn't steal focus to others + StartupInfo2.wShowWindow = SW_SHOWMINNOACTIVE; + } + if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, + 0, NULL, MyPath, &StartupInfo2, &ProcessInfo2)) + { + if(bLinehook!=FALSE) + { + DWORD ExitCode; + hProc=ProcessInfo2.hProcess; + do{ + GetExitCodeProcess(ProcessInfo2.hProcess,&ExitCode); + ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); + Sleep(1); + } while(ExitCode==STILL_ACTIVE); + hProc=NULL; + + if (ExitCode==1) + MsgBox("Material properties have not been defined for all regions"); + if (ExitCode==2) + MsgBox("problem loading mesh"); + if (ExitCode==3) + MsgBox("problem renumbering node points"); + if (ExitCode==4) + MsgBox("couldn't allocate enough space for matrices"); + if (ExitCode==5) + MsgBox("Couldn't solve the problem"); + if (ExitCode==6) + MsgBox("couldn't write results to disk"); + if (ExitCode==7) + MsgBox("problem loading input file"); + } + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } + else + { + MsgBox("Problem executing the solver"); + return; + } + +} + +void CcdrawView::OnMenuViewres() +{ + // TODO: Add your command handler code here + CcdrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("No results to display"); + return; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".anc\""; + ((CFemmApp *) AfxGetApp())->COCheckIfAlreadyOpen(rootname); + AfxGetApp( )->OpenDocumentFile(rootname); + +} + +void CcdrawView::OnUndo() +{ + CcdrawDoc *TheDoc = GetDocument(); + TheDoc->Undo(); + TheDoc->UnselectAll(); + InvalidateRect(NULL); +} + +void CcdrawView::OnKbdZoom() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]UpdateUndo(); + pDoc->RotateMove(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateMove(dlg.m_deltax,dlg.m_deltay,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CcdrawView::OnCopyObjects() +{ + // TODO: Add your command handler code here + CCopyDlg dlg; + CcdrawDoc *pDoc=GetDocument(); + + dlg.m_aboutx=0; + dlg.m_abouty=0; + dlg.m_shiftangle=0; + dlg.m_deltax=0; + dlg.m_deltay=0; + dlg.IsMove=FALSE; + dlg.m_ncopies=1; + + if(dlg.DoModal()==IDOK) + { + if(dlg.BtnState==0) // Rotate + { + pDoc->UpdateUndo(); + pDoc->RotateCopy(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateCopy(dlg.m_deltax,dlg.m_deltay,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void CcdrawView::OnDxfin() +{ + // TODO: Add your command handler code here + CString dxffile; + CFileDialog *fname_dia; + CcdrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + TRUE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if(pDoc->ReadDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't read specified DXF file\nMake sure the the specified file\nis in ASCII DXF r12 format"); + pDoc->NoDraw=FALSE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } +} + +void CcdrawView::OnPurgemesh() +{ + // TODO: Add your command handler code here + CcdrawDoc *pDoc=GetDocument(); + pDoc->meshnode.RemoveAll(); + pDoc->meshnode.FreeExtra(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + pDoc->meshline.FreeExtra(); + pDoc->greymeshline.FreeExtra(); + MeshUpToDate=FALSE; + if (MeshFlag==TRUE){ + MeshFlag=FALSE; + InvalidateRect(NULL); + } + +} + +void CcdrawView::OnDxfwrite() +{ + CString dxffile; + CFileDialog *fname_dia; + CcdrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + FALSE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if (bLinehook==FALSE) BeginWaitCursor(); + if(pDoc->WriteDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + pDoc->FirstDraw=TRUE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't write specified DXF file"); + if (bLinehook==FALSE) EndWaitCursor(); + } +} + + +BOOL CcdrawView::OnEraseBkgnd(CDC* pDC) +{ + + // idea is to always make the background white. + // source code copied from: + // Frequently Asked Questions About Foundation Classes + + // Set brush to desired background color + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + return TRUE; + +} + +void CcdrawView::OnPanDown() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox=ox-0.25*x/mag; + oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CcdrawView::OnPanLeft() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CcdrawView::OnPanRight() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CcdrawView::OnPanUp() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox+=0.25*x/mag; + oy+=0.25*y/mag; + + InvalidateRect(NULL); +} + +void CcdrawView::OnMenuMatlib() +{ + cdCLibDlg dlg; + + dlg.pDoc=GetDocument(); + dlg.BinDir=BinDir; + + dlg.DoModal(); +} + +void CcdrawView::OnOpenSelected() +{ + CcdrawDoc *pDoc=GetDocument(); + + if(EditAction==1) pDoc->OpSegDlg(); + if(EditAction==2){ + if (pDoc->OpBlkDlg()==TRUE) + InvalidateRect(NULL); + } + if(EditAction==3){ + pDoc->OpArcSegDlg(); + InvalidateRect(NULL); + } + if(EditAction==0) pDoc->OpNodeDlg(); + + if(EditAction==4) pDoc->OpGrpDlg(); + + pDoc->UnselectAll(); + DrawPSLG(); +} + +void CcdrawView::OnEditScale() +{ + // TODO: Add your command handler code here + CScaleDlg dlg; + CcdrawDoc *pDoc=GetDocument(); + double x[2],y[2],R,dt; + int i,j,k; + CComplex p,s,c; + BOOL bFlag=FALSE; + + // look at points, block labels, and arcs to get bounding box. + for(i=0;inodelist.GetSize();i++) + if(pDoc->nodelist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[i].x; x[1]=x[0]; + y[0]=pDoc->nodelist[i].y; y[1]=y[0]; + } + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + if(pDoc->blocklist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->blocklist[i].x; x[1]=x[0]; + y[0]=pDoc->blocklist[i].y; y[1]=y[0]; + } + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;ilinelist.GetSize();i++) + if(pDoc->linelist[i].IsSelected==TRUE){ + for(j=0;j<2;j++){ + if(j==0) k=pDoc->linelist[i].n0; + else k=pDoc->linelist[i].n1; + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[k].x; x[1]=x[0]; + y[0]=pDoc->nodelist[k].y; y[1]=y[0]; + } + if(pDoc->nodelist[k].xnodelist[k].x; + if(pDoc->nodelist[k].x>x[1]) x[1]=pDoc->nodelist[k].x; + if(pDoc->nodelist[k].ynodelist[k].y; + if(pDoc->nodelist[k].y>y[1]) y[1]=pDoc->nodelist[k].y; + } + } + + + for(i=0;iarclist.GetSize();i++) + if(pDoc->arclist[i].IsSelected==TRUE){ + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + if(bFlag==FALSE) return; + + dlg.m_scalefactor=1.; + dlg.m_basex=(x[1]+x[0])/2.; + dlg.m_basey=(y[1]+y[0])/2.; + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->ScaleMove(dlg.m_basex,dlg.m_basey,dlg.m_scalefactor,EditAction); + InvalidateRect(NULL); + } +} + +void CcdrawView::OnEditMirror() +{ + // TODO: Add your command handler code here + CMirrorDlg dlg; + CcdrawDoc *pDoc=GetDocument(); + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->MirrorSelected(dlg.m_pax,dlg.m_pay, + dlg.m_pbx,dlg.m_pby,EditAction); + InvalidateRect(NULL); + } +} + +void CcdrawView::OnEditCut() +{ + CcdrawDoc *pDoc=GetDocument(); + BOOL flag; + + pDoc->UpdateUndo(); + if(EditAction==0) flag=pDoc->DeleteSelectedNodes(); + if(EditAction==1) flag=pDoc->DeleteSelectedSegments(); + if(EditAction==2) flag=pDoc->DeleteSelectedBlockLabels(); + if(EditAction==3) flag=pDoc->DeleteSelectedArcSegments(); + if(EditAction==4){ + flag=FALSE; + if (pDoc->DeleteSelectedSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedArcSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedNodes()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedBlockLabels()==TRUE) flag=TRUE; + } + if (flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else InvalidateRect(NULL); + } + +} + + +BOOL CcdrawView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"cdraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_mag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_shownames); + q[0]=NULL; + } + } + fclose(fp); + return TRUE; + } + + return FALSE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + + +BOOL CcdrawView::WritePreferences() +{ + FILE *fp; + CString fname; + CcdrawDoc *pDoc=GetDocument(); + + fname=BinDir+"cdraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",d_action); + fprintf(fp," = %g\n",d_mag); + fprintf(fp," = %g\n",d_gridsize); + fprintf(fp," = %i\n",d_showgrid); + fprintf(fp," = %i\n",d_snapgrid); + fprintf(fp," = %i\n",d_shownames); + fprintf(fp," = %i\n",d_showorigin); + fprintf(fp," = %i\n",pDoc->d_type); + fprintf(fp," = %i\n",pDoc->d_length); + fprintf(fp," = %g\n",pDoc->d_prec); + fprintf(fp," = %g\n",pDoc->d_minangle); + fprintf(fp," = %g\n",pDoc->d_depth); + fprintf(fp," = %g\n",pDoc->d_frequency); + fprintf(fp," = %i\n",pDoc->d_coord); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void CcdrawView::OnViewShownames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + InvalidateRect(NULL); +} + +void CcdrawView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CcdrawView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +void CcdrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if (bActivate && pActivateView==this) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(7); + + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + CheckIt(); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CcdrawView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CcdrawView::OnViewShowOrphans() +{ + CcdrawDoc *pDoc=GetDocument(); + + OnGroupOp(); + pDoc->SelectOrphans(); + InvalidateRect(NULL); +} + +void CcdrawView::OnUpdateEditExterior(CCmdUI* pCmdUI) +{ + if(GetDocument()->ProblemType) pCmdUI->Enable ( TRUE); + else pCmdUI->Enable ( FALSE ); +} + +void CcdrawView::OnCreateRadius() +{ + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=TRUE; + + StatBar->SetPaneText(0,"SELECT POINT AT WHICH A RADIUS IS DESIRED",TRUE); +} + +void CcdrawView::OnMakeABC() +{ + CMakeABCDlg dlg; + CcdrawDoc *pDoc=GetDocument(); + + double xx[2],yy[2]; + if (GetBoundingBox(xx,yy)==0) return; + + if(pDoc->ProblemType == 0) // 2D planar case + { + dlg.abcr=0.75*abs((xx[0]+I*yy[0])-(xx[1]+I*yy[1])); + dlg.abcx=(xx[0]+xx[1])/2.0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.n=1; + } + else{ //Axi case + dlg.abcx=0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.abcr=1.5*abs(xx[1]+I*(yy[1]-yy[0])/2.0); + dlg.n=0; + } + + dlg.abcn=7; // suggested default number of layers + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + CString LuaCmd; + LuaCmd.Format("ci_makeABC(%i,%g,%g,%g,%i)",dlg.abcn,dlg.abcr,dlg.abcx,dlg.abcy,dlg.n); + lua_dostring(lua,LuaCmd); + } +} diff --git a/femm/cdrawView.h b/femm/cdrawView.h new file mode 100644 index 0000000..87d27da --- /dev/null +++ b/femm/cdrawView.h @@ -0,0 +1,167 @@ +// cdrawView.h : interface of the CcdrawView class +// +///////////////////////////////////////////////////////////////////////////// + +class CcdrawView : public CView +{ +protected: // create from serialization only + CcdrawView(); + DECLARE_DYNCREATE(CcdrawView) + +// Attributes +public: + CcdrawDoc* GetDocument(); + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void DrawPSLG(); + void EnterPoint(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void OnNewDocument(); + void CheckIt(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL ShowNames; + BOOL MeshUpToDate; + int FirstPoint; + int ZoomWndFlag; + int SelectWndFlag; + int SelectCircFlag; + int CreateRadiusFlag; + double wzx,wzy; + double MaxSeg,ArcAngle; + + + // Colors used to render the view + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF NodeColor; + COLORREF NameColor; + + // default view properties + int d_action; //=0; + double d_mag; //=100.; + double d_gridsize; //=0.25; + BOOL d_showgrid; //=TRUE; + BOOL d_snapgrid; //=FALSE; + BOOL d_shownames; //=FALSE; + BOOL d_showorigin; + + CString BinDir; // pathname for other FEMM executables + CArray ZoomPix; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CcdrawView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual void OnInitialUpdate(); // called first time after construct + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + void lua_zoomin(); + void lua_zoomout(); + void lua_zoomnatural(); + void lnu_show_mesh(); + void lnu_purge_mesh(); + void lnuMakeMesh(); + void lnu_analyze(int bShow); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL GetBoundingBox(double *x, double *y); + + virtual ~CcdrawView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CcdrawView) + afx_msg void OnNodeOp(); + afx_msg void OnSegmentOp(); + afx_msg void OnBlockOp(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnZoomIn(); + afx_msg void OnZoomOut(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnEditCopy(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomWnd(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMakeMesh(); + afx_msg void OnMenuAnalyze(); + afx_msg void OnMenuViewres(); + afx_msg void OnArcsegOp(); + afx_msg void OnUndo(); + afx_msg void OnKbdZoom(); + afx_msg void OnMoveObjects(); + afx_msg void OnCopyObjects(); + afx_msg void OnDxfin(); + afx_msg void OnPurgemesh(); + afx_msg void OnDxfwrite(); + afx_msg void OnSelectwnd(); + afx_msg void OnBDSelectCirc(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnMenuMatlib(); + afx_msg void OnGroupOp(); + afx_msg void OnOpenSelected(); + afx_msg void OnEditScale(); + afx_msg void OnEditMirror(); + afx_msg void OnEditCut(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnViewShownames(); + afx_msg void OnViewShowOrphans(); + afx_msg void OnCreateRadius(); + afx_msg void OnUpdateEditExterior(CCmdUI* pCmdUI); + afx_msg void OnMakeABC(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +#ifndef _DEBUG // debug version in cdrawView.cpp +inline CcdrawDoc* CcdrawView::GetDocument() + { return (CcdrawDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/femm/cv_BlockInt.cpp b/femm/cv_BlockInt.cpp new file mode 100644 index 0000000..73bd4d3 --- /dev/null +++ b/femm/cv_BlockInt.cpp @@ -0,0 +1,67 @@ +// BlockInt.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_BlockInt.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCBlockInt dialog + + +cvCBlockInt::cvCBlockInt(CWnd* pParent /*=NULL*/) + : CDialog(cvCBlockInt::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCBlockInt) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void cvCBlockInt::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCBlockInt) + DDX_Control(pDX, IDC_CV_BINTTYPE, m_binttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(cvCBlockInt, CDialog) + //{{AFX_MSG_MAP(cvCBlockInt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCBlockInt message handlers + +BOOL cvCBlockInt::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if (Frequency!=0) + { + m_binttype.AddString("Force via Stress Tensor"); + m_binttype.AddString("Torque via Stress Tensor"); + } + + binttype=0; + m_binttype.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cvCBlockInt::OnOK() +{ + // TODO: Add extra validation here + binttype=m_binttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/cv_BlockInt.h b/femm/cv_BlockInt.h new file mode 100644 index 0000000..4909264 --- /dev/null +++ b/femm/cv_BlockInt.h @@ -0,0 +1,39 @@ +// BlockInt.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCBlockInt dialog + +class cvCBlockInt : public CDialog +{ +// Construction +public: + cvCBlockInt(CWnd* pParent = NULL); // standard constructor + + int binttype; + double Frequency; + +// Dialog Data + //{{AFX_DATA(cvCBlockInt) + enum { IDD = IDD_CV_BLOCKINT }; + CComboBox m_binttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCBlockInt) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCBlockInt) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/cv_CircDlg.cpp b/femm/cv_CircDlg.cpp new file mode 100644 index 0000000..91b41d5 --- /dev/null +++ b/femm/cv_CircDlg.cpp @@ -0,0 +1,97 @@ +// CircDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "cv_problem.h" +#include "xyplot.h" +#include "cviewdoc.h" +#include "cv_CircDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCCircDlg dialog + + +cvCCircDlg::cvCCircDlg(CWnd* pParent /*=NULL*/) + : CDialog(cvCCircDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCCircDlg) + //}}AFX_DATA_INIT +} + + +void cvCCircDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCCircDlg) + DDX_Control(pDX, IDC_CV_CIRCNAME, m_circname); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(cvCCircDlg, CDialog) + //{{AFX_MSG_MAP(cvCCircDlg) + ON_CBN_SELCHANGE(IDC_CV_CIRCNAME, OnSelchangeCircname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCCircDlg message handlers +////////////////////////////////////////////////////// +void cvCCircDlg::OnSelchangeCircname() +{ + if(NumCircuits==0) return; + + int k; + CString crslt,s; + CComplex x,V,q; + char c[80]; + + k=m_circname.GetCurSel(); + V=TheDoc->circproplist[k].V; + q=TheDoc->circproplist[k].q; + + crslt.Format("Voltage = %s V\r\n",V.ToStringAlt(c)); + + s.Format("Current = %s A\r\n",q.ToStringAlt(c)); crslt=crslt+s; + + if(q!=0){ + x=V/q; + s.Format("Volt/Curr = %s Ohms\r\n",x.ToStringAlt(c)); crslt=crslt+s; + } + + if(V!=0){ + x=q/V; + s.Format("Curr/Volt = %s S\r\n",x.ToStringAlt(c)); crslt=crslt+s; + } + + + SetDlgItemText(IDC_CV_CIRCRESULT,crslt); + +} + +BOOL cvCCircDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName); + + if(NumCircuits!=0){ + m_circname.SetCurSel(0); + OnSelchangeCircname(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/cv_CircDlg.h b/femm/cv_CircDlg.h new file mode 100644 index 0000000..58282f1 --- /dev/null +++ b/femm/cv_CircDlg.h @@ -0,0 +1,39 @@ +// CircDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCCircDlg dialog + +class cvCCircDlg : public CDialog +{ +// Construction +public: + cvCCircDlg(CWnd* pParent = NULL); // standard constructor + + CcviewDoc *TheDoc; + int NumCircuits; + +// Dialog Data + //{{AFX_DATA(cvCCircDlg) + enum { IDD = IDD_CV_CIRCPROPS }; + CComboBox m_circname; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCCircDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCCircDlg) + afx_msg void OnSelchangeCircname(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/cv_CplotDlg2.cpp b/femm/cv_CplotDlg2.cpp new file mode 100644 index 0000000..9e54c68 --- /dev/null +++ b/femm/cv_CplotDlg2.cpp @@ -0,0 +1,67 @@ +// CplotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_CplotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCCPlotDlg2 dialog + + +cvCCPlotDlg2::cvCCPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(cvCCPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCCPlotDlg2) + m_numcontours = 0; + m_showa = FALSE; + m_showa2 = FALSE; + m_ahigh = 0.0; + m_alow = 0.0; + m_showmask = FALSE; + //}}AFX_DATA_INIT +} + + +void cvCCPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCCPlotDlg2) + DDX_Text(pDX, IDC_CV_NUMCONTOURS, m_numcontours); + DDV_MinMaxInt(pDX, m_numcontours, 4, 999); + DDX_Check(pDX, IDC_CV_SHOW_A, m_showa); + DDX_Check(pDX, IDC_CV_SHOW_A2, m_showa2); + DDX_Text(pDX, IDC_CV_AHIGH, m_ahigh); + DDX_Text(pDX, IDC_CV_ALOW, m_alow); + DDX_Check(pDX, IDC_CV_SHOW_MASK2, m_showmask); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CV_NUMCONTOURS, m_IDC_numcontours); + DDX_Control(pDX, IDC_CV_AHIGH, m_IDC_ahigh); + DDX_Control(pDX, IDC_CV_ALOW, m_IDC_alow); +} + + +BEGIN_MESSAGE_MAP(cvCCPlotDlg2, CDialog) + //{{AFX_MSG_MAP(cvCCPlotDlg2) + ON_BN_CLICKED(IDC_CV_DFLT1, OnDflt1) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCCPlotDlg2 message handlers + +void cvCCPlotDlg2::OnDflt1() +{ + // TODO: Add your control notification handler code here + UpdateData(TRUE); + m_alow=Alb; + m_ahigh=Aub; + m_numcontours=19; + UpdateData(FALSE); +} diff --git a/femm/cv_CplotDlg2.h b/femm/cv_CplotDlg2.h new file mode 100644 index 0000000..57900df --- /dev/null +++ b/femm/cv_CplotDlg2.h @@ -0,0 +1,43 @@ +// cv_CplotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCCPlotDlg2 dialog + +class cvCCPlotDlg2 : public CDialog +{ +// Construction +public: + cvCCPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Alb,Aub; + +// Dialog Data + //{{AFX_DATA(cvCCPlotDlg2) + enum { IDD = IDD_CV_CPLOTDLG2 }; + int m_numcontours; + BOOL m_showa; + BOOL m_showa2; + double m_ahigh; + double m_alow; + BOOL m_showmask; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCCPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCCPlotDlg2) + afx_msg void OnDflt1(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_numcontours, m_IDC_ahigh, m_IDC_alow; +}; diff --git a/femm/cv_DPlotDlg2.cpp b/femm/cv_DPlotDlg2.cpp new file mode 100644 index 0000000..99d76bd --- /dev/null +++ b/femm/cv_DPlotDlg2.cpp @@ -0,0 +1,133 @@ +// DPlotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_DPlotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCDPlotDlg2 dialog + + +cvCDPlotDlg2::cvCDPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(cvCDPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCDPlotDlg2) + m_showit = FALSE; + m_showlegend = FALSE; + m_lb2 = 0.0; + m_ub2 = 0.0; + m_gscale = FALSE; + //}}AFX_DATA_INIT +} + + +void cvCDPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCDPlotDlg2) + DDX_Control(pDX, IDC_CV_DPLOTTYPE, m_dplottype); + DDX_Check(pDX, IDC_CV_SHOWIT, m_showit); + DDX_Check(pDX, IDC_CV_SHOW_LEG2, m_showlegend); + DDX_Text(pDX, IDC_CV_LB2, m_lb2); + DDX_Text(pDX, IDC_CV_UB2, m_ub2); + DDX_Check(pDX, IDC_CV_GSCALE2, m_gscale); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CV_LB2, m_IDC_lb2); + DDX_Control(pDX, IDC_CV_UB2, m_IDC_ub2); +} + + +BEGIN_MESSAGE_MAP(cvCDPlotDlg2, CDialog) + //{{AFX_MSG_MAP(cvCDPlotDlg2) + ON_BN_CLICKED(IDC_CV_RESBTN2, OnResbtn2) + ON_CBN_SELCHANGE(IDC_CV_DPLOTTYPE, OnSelchangeDplottype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCDPlotDlg2 message handlers + +void cvCDPlotDlg2::OnResbtn2() +{ + // TODO: Add your control notification handler code here + UpdateData(); + m_ub2=d_PlotBounds[DensityPlot][1]; + m_lb2=d_PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} + +BOOL cvCDPlotDlg2::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if(listtype==0) + { + m_dplottype.AddString("|Voltage| (V)"); + m_dplottype.AddString("Re(Voltage) (V)"); + m_dplottype.AddString("Im(Voltage) (V)"); + m_dplottype.AddString("|J| (A/m^2)"); + m_dplottype.AddString("Re(J) (A/m^2)"); + m_dplottype.AddString("Im(J) (A/m^2)"); + m_dplottype.AddString("|E| (V/m)"); + m_dplottype.AddString("Re(E) (V/m)"); + m_dplottype.AddString("Im(E) (V/m)"); + } + + if (listtype==1) + { + m_dplottype.AddString("Flux Density (T)"); + m_dplottype.AddString("Field Intensity (A/m)"); + m_dplottype.AddString("Current Density (MA/m^2)"); + } + + if (listtype==2) + { + m_dplottype.AddString("|Flux Density| (T)"); + m_dplottype.AddString("Re(Flux Density) (T)"); + m_dplottype.AddString("Im(Flux Density) (T)"); + m_dplottype.AddString("|Field Intensity| (A/m)"); + m_dplottype.AddString("Re(Field Intensity) (A/m)"); + m_dplottype.AddString("Im(Field Intensity) (A/m)"); + m_dplottype.AddString("|Current Density| (MA/m^2)"); + m_dplottype.AddString("Re(Current Density) (MA/m^2)"); + m_dplottype.AddString("Im(Current Density) (MA/m^2)"); + + } + + DensityPlot--; + if(DensityPlot<0) DensityPlot=0; + m_dplottype.SetCurSel(DensityPlot); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cvCDPlotDlg2::OnOK() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot++; + CDialog::OnOK(); +} + +void cvCDPlotDlg2::OnSelchangeDplottype() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot=m_dplottype.GetCurSel(); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} diff --git a/femm/cv_DPlotDlg2.h b/femm/cv_DPlotDlg2.h new file mode 100644 index 0000000..2a5fe38 --- /dev/null +++ b/femm/cv_DPlotDlg2.h @@ -0,0 +1,49 @@ +// DPlotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCDPlotDlg2 dialog + +class cvCDPlotDlg2 : public CDialog +{ +// Construction +public: + cvCDPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Bm_l, Bm_h; + double d_PlotBounds[20][2]; + double PlotBounds[20][2]; + int DensityPlot,listtype; + +// Dialog Data + //{{AFX_DATA(cvCDPlotDlg2) + enum { IDD = IDD_CV_DPLOTDLG2 }; + CComboBox m_dplottype; + BOOL m_showit; + BOOL m_showlegend; + double m_lb2; + double m_ub2; + BOOL m_gscale; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCDPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCDPlotDlg2) + afx_msg void OnResbtn2(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeDplottype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_lb2, m_IDC_ub2; +}; diff --git a/femm/cv_LIntDlg.cpp b/femm/cv_LIntDlg.cpp new file mode 100644 index 0000000..e71ef4c --- /dev/null +++ b/femm/cv_LIntDlg.cpp @@ -0,0 +1,64 @@ +// LIntDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_LIntDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCLIntDlg dialog + + +cvCLIntDlg::cvCLIntDlg(CWnd* pParent /*=NULL*/) + : CDialog(cvCLIntDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCLIntDlg) + //}}AFX_DATA_INIT +} + + +void cvCLIntDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCLIntDlg) + DDX_Control(pDX, IDC_CV_LINTTYPE, m_inttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(cvCLIntDlg, CDialog) + //{{AFX_MSG_MAP(cvCLIntDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCLIntDlg message handlers + +BOOL cvCLIntDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + if (Frequency!=0) + { + m_inttype.AddString("Force via Stress Tensor"); + m_inttype.AddString("Torque via Stress Tensor"); + } + + m_inttype.SetCurSel(0); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cvCLIntDlg::OnOK() +{ + // TODO: Add extra validation here + linttype=m_inttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/cv_LIntDlg.h b/femm/cv_LIntDlg.h new file mode 100644 index 0000000..0143899 --- /dev/null +++ b/femm/cv_LIntDlg.h @@ -0,0 +1,39 @@ +// LIntDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCLIntDlg dialog + +class cvCLIntDlg : public CDialog +{ +// Construction +public: + cvCLIntDlg(CWnd* pParent = NULL); // standard constructor + + int linttype; + double Frequency; + +// Dialog Data + //{{AFX_DATA(cvCLIntDlg) + enum { IDD = IDD_CV_LINEINT }; + CComboBox m_inttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCLIntDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCLIntDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/cv_VPlotDlg.cpp b/femm/cv_VPlotDlg.cpp new file mode 100644 index 0000000..ed007ef --- /dev/null +++ b/femm/cv_VPlotDlg.cpp @@ -0,0 +1,61 @@ +// VPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "cv_VPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCVPlotDlg dialog + + +cvCVPlotDlg::cvCVPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(cvCVPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCVPlotDlg) + m_vectorscalefactor = 0.0; + //}}AFX_DATA_INIT +} + + +void cvCVPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCVPlotDlg) + DDX_Control(pDX, IDC_CV_VPLOTTYPE, m_vplottype); + DDX_Text(pDX, IDC_CV_SCALEFACTOR, m_vectorscalefactor); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CV_SCALEFACTOR, m_IDC_vectorscalefactor); +} + + +BEGIN_MESSAGE_MAP(cvCVPlotDlg, CDialog) + //{{AFX_MSG_MAP(cvCVPlotDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCVPlotDlg message handlers + +void cvCVPlotDlg::OnOK() +{ + m_plottype=m_vplottype.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL cvCVPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_vplottype.SetCurSel(m_plottype); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/cv_VPlotDlg.h b/femm/cv_VPlotDlg.h new file mode 100644 index 0000000..75c1221 --- /dev/null +++ b/femm/cv_VPlotDlg.h @@ -0,0 +1,51 @@ +#if !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) +#define AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// VPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCVPlotDlg dialog + +class cvCVPlotDlg : public CDialog +{ +// Construction +public: + cvCVPlotDlg(CWnd* pParent = NULL); // standard constructor + + int m_plottype; + CLuaEdit m_IDC_vectorscalefactor; + +// Dialog Data + //{{AFX_DATA(cvCVPlotDlg) + enum { IDD = IDD_CV_VPLOTDLG }; + CComboBox m_vplottype; + double m_vectorscalefactor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCVPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCVPlotDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) diff --git a/femm/cv_XYPlotDlg.cpp b/femm/cv_XYPlotDlg.cpp new file mode 100644 index 0000000..c771af4 --- /dev/null +++ b/femm/cv_XYPlotDlg.cpp @@ -0,0 +1,101 @@ +// XYPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "cv_problem.h" +#include "xyplot.h" +#include "cviewDoc.h" +#include "cviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#include "cv_XYPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// cvCXYPlotDlg dialog + + +cvCXYPlotDlg::cvCXYPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(cvCXYPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(cvCXYPlotDlg) + m_ToFile = FALSE; + m_npoints = 150; + //}}AFX_DATA_INIT + ListType=0; + XYPlotType=0; + FileFormat=0; +} + + +void cvCXYPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(cvCXYPlotDlg) + DDX_Control(pDX, IDC_CV_FILEFORMAT, m_fileformat); + DDX_Control(pDX, IDC_CV_XYPLOTTYPE, m_XYPlotType); + DDX_Check(pDX, IDC_CV_TOFILE, m_ToFile); + DDX_Text(pDX, IDC_CV_NPOINTS, m_npoints); + DDV_MinMaxInt(pDX, m_npoints, 10, 100000); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CV_NPOINTS, m_IDC_npoints); +} + + +BEGIN_MESSAGE_MAP(cvCXYPlotDlg, CDialog) + //{{AFX_MSG_MAP(cvCXYPlotDlg) + ON_BN_CLICKED(IDC_CV_TOFILE, OnToFileClicked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// cvCXYPlotDlg message handlers + +BOOL cvCXYPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_XYPlotType.AddString("V (Voltage)"); + m_XYPlotType.AddString("|J| (Magnitude of current density)"); + m_XYPlotType.AddString("J . n (Normal current density)"); + m_XYPlotType.AddString("J . t (Tangential current density)"); + m_XYPlotType.AddString("|E| (Magnitude of electric field intensity)"); + m_XYPlotType.AddString("E . n (Normal electric field intensity)"); + m_XYPlotType.AddString("E . t (Tangential electric field intensity)"); + m_XYPlotType.AddString("|Jc| (Magnitude of conduction current density)"); + m_XYPlotType.AddString("Jc . n (Normal conduction current density)"); + m_XYPlotType.AddString("Jc . t (Tangential conduction current density)"); + m_XYPlotType.AddString("|Jd| (Magnitude of displacment current density)"); + m_XYPlotType.AddString("Jd . n (Normal displacement current density)"); + m_XYPlotType.AddString("Jd . t (Tangential displacement current density)"); + m_XYPlotType.SetCurSel(0); + + m_fileformat.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void cvCXYPlotDlg::OnOK() +{ + // TODO: Add extra validation here + XYPlotType=m_XYPlotType.GetCurSel(); + FileFormat=m_fileformat.GetCurSel(); + CDialog::OnOK(); +} + +void cvCXYPlotDlg::OnToFileClicked() +{ + UpdateData(); +} + diff --git a/femm/cv_XYPlotDlg.h b/femm/cv_XYPlotDlg.h new file mode 100644 index 0000000..7b3da86 --- /dev/null +++ b/femm/cv_XYPlotDlg.h @@ -0,0 +1,46 @@ +// XYPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// cvCXYPlotDlg dialog + +class cvCXYPlotDlg : public CDialog +{ +// Construction +public: + cvCXYPlotDlg(CWnd* pParent = NULL); // standard constructor + int ListType; + int XYPlotType; + int FileFormat; + CcviewDoc *pDoc; + +// Dialog Data + //{{AFX_DATA(cvCXYPlotDlg) + enum { IDD = IDD_CV_XYPLOTDLG }; + CComboBox m_fileformat; + CComboBox m_XYPlotType; + BOOL m_ToFile; + int m_npoints; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(cvCXYPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(cvCXYPlotDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnToFileClicked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_npoints; +}; diff --git a/femm/cv_makemask.cpp b/femm/cv_makemask.cpp new file mode 100644 index 0000000..45c5081 --- /dev/null +++ b/femm/cv_makemask.cpp @@ -0,0 +1,348 @@ +#include "stdafx.h" +#include +#include +#include "cv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "cviewDoc.h" +#include "cviewView.h" +#include "MainFrm.h" + +#include "maskprogress.h" +#include "lua.h" + +#include "spars.h" + +extern BOOL bLinehook; +extern CLuaConsoleDlg *LuaConsole; + +// #define SIMPLE + +#ifdef SIMPLE + +BOOL CcviewDoc::MakeMask() +{ + // Good placeholder mask generator + // This gives a valid mask that butts right up against the + // selected region. This mask yields the same results as the + // Coulomb virtual work method. + + int i,j; + + for(i=0;ibw) bw=d; + } + } + bw++; + + L.Create(NumNodes,bw); + + // if the problem is axisymmetric, does the selection lie along r=0? + if(ProblemType==1) + { + for(i=0;i0) + { + CComplex *p; + int npts; + + p=(CComplex *)calloc(nodelist.GetSize(),sizeof(CComplex)); + for(i=0,npts=0;i=0) + { + p[npts]=nodelist[i].CC(); + npts++; + } + + if(npts>0) + for(i=0;i0){ + p[j]=p[npts]; + j=npts; + } + else{ + j=npts; + i=NumNodes; + } + } + free(p); + } + + for(i=0;iToOutput(outmsg); + } + else{ + outmsg ="The selected region is invalid. A valid selection\n"; + outmsg+="cannot abut a region which is not free space."; + MsgBox(outmsg); + } + free(matflag); + free(lblflag); + return FALSE; + } + } + + // Each element weighted by its region's + // mesh size specification; + v=blocklist[meshelem[i].lbl].MaxArea; + if (v<=0) v=sqrt(a); else v=sqrt(v); + + // build element matrix; + for(j=0;j<3;j++) + for(k=0;k<3;k++) + Me[j][k]+=v*(p[j]*p[k]+q[j]*q[k])/a; + + // process any prescribed nodal values; + // doing it here saves a lot of time. + for(j=0;j<3;j++) + { + if(L.V[n[j]]>=0) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + for (k=j;k<3;k++) + if(Me[j][k]!=0) L.Put(L.Get(n[j],n[k])-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // solve the problem; + bLinehook=BuildMask; + if (L.PCGSolve(FALSE)==FALSE) return FALSE; + bLinehook=FALSE; + + // Process the results to get one row of elements + // that runs down the center of the gap away from boundaries. + for(i=0;i0.5) meshnode[i].msk = 1; + else meshnode[i].msk = 0; + + free(matflag); + free(lblflag); + bHasMask=TRUE; + + return TRUE; +} + +#endif + +BOOL CcviewDoc::IsKosher(int k) +{ + // If: + // 1) this is an axisymmetric problem; + // 2) the selected geometry lies along the r=0 axis, and + // 3) we have a node on the r=0 axis that we are trying to determine + // if we should set to zero. + // This routine determines whether the node is at the extents of + // the r=0 domain (or lies at a break in some sub-interval). + // + // Returns TRUE if it is OK to define the node as zero; + + if((ProblemType==0) || (meshnode[k].x>1.e-6)) return TRUE; + + int i,j,n; + int score=0; + + for(i=0;i1) return FALSE; + } + } + } + + return TRUE; +} diff --git a/femm/cv_problem.cpp b/femm/cv_problem.cpp new file mode 100644 index 0000000..5e2674c --- /dev/null +++ b/femm/cv_problem.cpp @@ -0,0 +1,153 @@ +#include "stdafx.h" +#include "cv_problem.h" + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +CComplex CNode::CC() +{ + return (x+I*y); +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMeshNode construction + +CMeshNode::CMeshNode() +{ + x=y=0; + v=0; + Q=FALSE; + msk=0; + IsSelected=FALSE; +} + +CComplex CMeshNode::CC() +{ + return (x+I*y); +} + +double CMeshNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + MaxSideLength=-1; + ArcLength=90.; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + InGroup=0; + BlockType=-1; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + Kx=0; Ky=0; + ox=0; oy=0; + ex=0; ey=0; +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; // type of boundary condition we are applying + V=0; qs=0; + c0=0; + c1=0; + + InConductor=""; +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + InConductor=""; + V=0; + qp=0; +} + +CCircuit::CCircuit() +{ + CircName="New Circuit"; + V=0; + q=0; + CircType=0; +} diff --git a/femm/cv_problem.h b/femm/cv_problem.h new file mode 100644 index 0000000..cab89f1 --- /dev/null +++ b/femm/cv_problem.h @@ -0,0 +1,206 @@ +namespace cviewtype +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + int BoundaryMarker; + int InGroup,InConductor; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +class CMeshNode +{ + public: + CMeshNode(); + + CComplex v; + double x,y; + double msk; + int xs,ys; + BOOL Q,IsSelected; + + double GetDistance(double xo, double yo); + CComplex CC(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + double MaxSideLength; + BOOL IsSelected; + BOOL Hidden; + int BoundaryMarker; + int InGroup,InConductor; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength; + int BoundaryMarker; + int InGroup, InConductor; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + BOOL IsSelected; + int BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CString BlockName; + + CComplex Kx,Ky; // effective conductivity + double ox,oy; // dc conductivity + CComplex ex,ey; // electrical permittivity + CMaterialProp(); + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + CString InConductor; + + int BdryFormat; // type of boundary condition we are applying + // 0 = Fixed Voltage + // 1 = Mixed BC + // 2 = Surface Current Density + // 3 = Periodic + // 4 = Antiperiodic + + CComplex V ; // Fixed value of V for BdryFormat=0; + CComplex c0,c1; // Coefficients for BdryFormat=1; + CComplex qs; // Surface current density for Bdryformat=2; + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + CString InConductor; + CComplex V,qp; + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + CComplex V,q; + int CircType; + + private: + +}; + +class CElement +{ + public: + + int p[3]; + int blk,lbl; + CComplex Jx,Jy; // elemental AC current density + CComplex jx[3], jy[3]; // smoothed AC current density at corners + CComplex ctr; + double rsqr; + int n[3]; // Add 3 ints to store elem's neigh. + +// CComplex E(); + + private: +}; + +class CPointVals +{ + public: + + CComplex v; // voltage + CComplex Ex,Ey; // electric field intensity + CComplex Dx,Dy; // electric flux density + CComplex Jcx,Jcy; // conduction current density + CComplex Jdx,Jdy; // displacement current density + CComplex Jx,Jy; // AC current density + CComplex Kx,Ky; // effective conductivity + double ox,oy; // dc conductivity + CComplex ex,ey; // permittivity + + CPointVals(); + + private: +}; + +} + +using namespace cviewtype; \ No newline at end of file diff --git a/femm/cviewView.cpp b/femm/cviewView.cpp new file mode 100644 index 0000000..cba0ab5 --- /dev/null +++ b/femm/cviewView.cpp @@ -0,0 +1,3911 @@ +// cviewView.cpp : implementation of the CcviewView class +// + +#include "stdafx.h" +#include +#include +#include "femm.h" +#include "cv_problem.h" +#include "xyplot.h" +#include "cviewDoc.h" +#include "cviewView.h" +#include "GridMod.h" +#include "EnterPt.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "KbdZoom.h" +#include "cv_CPlotDlg2.h" +#include "cv_DPlotDlg2.h" +#include "cv_VPlotDlg.h" +#include "MyMsgBox.h" +#include "cv_XYPlotDlg.h" +#include "cv_LIntDlg.h" +#include "cv_BlockInt.h" +#include "cv_CircDlg.h" +#include "BendContourDlg.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +#define MSKHI (1. + 1.e-08) +#define MSKLO (0. - 1.e-08) + +extern lua_State * lua; +extern BOOL bLinehook; + +///////////////////////////////////////////////////////////////////////////// +// CcviewView + +IMPLEMENT_DYNCREATE(CcviewView, CView) + +BEGIN_MESSAGE_MAP(CcviewView, CView) + //{{AFX_MSG_MAP(CcviewView) + ON_COMMAND(ID_SMOOTH, OnSmooth) + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_CPLOT, OnCplot) + ON_COMMAND(ID_DPLOT, OnDplot) + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWindow) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_RELOAD, OnReload) + ON_COMMAND(ID_MENU_AREA, OnMenuArea) + ON_COMMAND(ID_MENU_CONTOUR, OnMenuContour) + ON_COMMAND(ID_MENU_POINT, OnMenuPoint) + ON_WM_KEYDOWN() + ON_COMMAND(ID_MENU_PLOT, OnMenuPlot) + ON_COMMAND(ID_MENU_INTEGRATE, OnMenuIntegrate) + ON_COMMAND(ID_MENUSHOWPTS, OnMenushowpts) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_WM_ERASEBKGND() + ON_WM_RBUTTONDBLCLK() + ON_WM_SIZE() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_VIEW_CIRCPROPS, OnViewCircprops) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_INFO, OnViewInfo) + ON_COMMAND(ID_VIEW_SHOWBLOCKNAMES, OnViewShowblocknames) + ON_COMMAND(ID_VPLOT, OnVplot) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_LBUTTONDBLCLK() +END_MESSAGE_MAP() + +void MyMessageBox(CString s); + +///////////////////////////////////////////////////////////////////////////// +// CcviewView construction/destruction + +CcviewView::CcviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // TODO: add construction code here + d_EditAction=0; + d_GridFlag=FALSE; + d_SnapFlag=FALSE; + d_MeshFlag=FALSE; + d_LegendFlag=TRUE; + d_GreyContours=FALSE; + d_NumContours=19; + d_ShowAr=FALSE; + d_ShowAi=FALSE; + d_ShowMask=FALSE; + d_DensityPlot=1; + d_VectorPlot=0; + d_PtsFlag=TRUE; + d_ResetOnReload=FALSE; + d_Smooth=TRUE; + d_PlotPoints=1500; + d_ShowNames=FALSE; + + ox=0.; oy=0.; mag=100.; // lower left corner is origin; 100 dpi + GridSize=0.25; // 1/4" grid + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + + ////////////////////////////// + // Default Colors // + ////////////////////////////// + + // Greyscale Colormap + Grey00=dGrey00; + Grey01=dGrey01; + Grey02=dGrey02; + Grey03=dGrey03; + Grey04=dGrey04; + Grey05=dGrey05; + Grey06=dGrey06; + Grey07=dGrey07; + Grey08=dGrey08; + Grey09=dGrey09; + Grey10=dGrey10; + Grey11=dGrey11; + Grey12=dGrey12; + Grey13=dGrey13; + Grey14=dGrey14; + Grey15=dGrey15; + Grey16=dGrey16; + Grey17=dGrey17; + Grey18=dGrey18; + Grey19=dGrey19; + + // BELA Colormap + Color19=dColor19; + Color18=dColor18; + Color17=dColor17; + Color16=dColor16; + Color15=dColor15; + Color14=dColor14; + Color13=dColor13; + Color12=dColor12; + Color11=dColor11; + Color10=dColor10; + Color09=dColor09; + Color08=dColor08; + Color07=dColor07; + Color06=dColor06; + Color05=dColor05; + Color04=dColor04; + Color03=dColor03; + Color02=dColor02; + Color01=dColor01; + Color00=dColor00; + + // Other colors + SelColor = dSelColor; + MeshColor = dMeshColor; + BlockColor = dBlockColor; + LineColor = dLineColor; + RegionColor = dRegionColor; + GridColor = dGridColor; + BackColor = dBackColor; + NodeColor = dNodeColor; + TextColor = dTextColor; + RealFluxLineColor = dRealFluxLineColor; + ImagFluxLineColor = dImagFluxLineColor; + MaskLineColor = dMaskLineColor; + NameColor = dNameColor; + RealVectorColor = dRealVectorColor; + ImagVectorColor = dImagVectorColor; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // Apply default behaviors + EditAction=d_EditAction; + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowAi=d_ShowAi; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; +} + +CcviewView::~CcviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL CcviewView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CcviewView drawing +void CcviewView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +BOOL CcviewView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void CcviewView::DoContours(CDC *pDC,int *p,int side,int Aflag) +{ + int i,j,k; + static double q[4][4]; + static double *m[4]; + static int u[4]; + double *swap; + double hi,lo,a,b,z,offset; + + CcviewDoc *pDoc=GetDocument(); + + switch(side) + { + case 0 : u[0]=p[0]; u[1]=p[1]; u[2]=p[1]; u[3]=p[2]; break; + case 1 : u[0]=p[1]; u[1]=p[2]; u[2]=p[2]; u[3]=p[0]; break; + default: u[0]=p[2]; u[1]=p[0]; u[2]=p[0]; u[3]=p[1]; break; + } + + for(i=0;i<4;i++){ + m[i]=q[i]; + m[i][0]=(double) pDoc->meshnode[u[i]].xs; + m[i][1]=(double) pDoc->meshnode[u[i]].ys; + m[i][3]=pDoc->meshnode[u[i]].x; + if (Aflag==0) m[i][2]=Re(pDoc->meshnode[u[i]].v); + if (Aflag==1) m[i][2]=Im(pDoc->meshnode[u[i]].v); + if (Aflag==2) m[i][2]=pDoc->meshnode[u[i]].msk; + } + + // scale A for easier analysis. Not necessary if mask is being displayed, + // since mask always varies between zero and one. + + if (Aflag<2) + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-pDoc->A_Low)/ + (pDoc->A_High-pDoc->A_Low); + offset=-NumContours*pDoc->A_Low/(pDoc->A_High-pDoc->A_Low); + } + else + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-MSKLO)/(MSKHI-MSKLO); + offset=-NumContours*MSKLO/(MSKHI-MSKLO); + } + + // swap around so that lowest magnitude is first point in + // each line... + if (m[0][2]>m[1][2]){ + swap=m[1]; + m[1]=m[0]; + m[0]=swap; + } + if (m[2][2]>m[3][2]){ + swap=m[3]; + m[3]=m[2]; + m[2]=swap; + } + + // figure out which contours lie in this section + lo=m[0][2]; if(m[2][2]>lo) lo=m[2][2]; + hi=m[1][2]; if(m[3][2]=0) && (iSetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), RealFluxLineColor ); + + if(Aflag==1) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), ImagFluxLineColor ); + + if(Aflag==2) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), MaskLineColor ); + } +} + +//////////////// +void CcviewView::PlotFluxDensity(CDC *pDC,int elmnum,int flag) +{ + + int i,j,k,n,lav; + double b,bn[3],bh,bl,y,z; + CComplex b1[3],b2[3],Ex,Ey; + POINT ps[3]; + static double c[64][3],p[3][2]; + CElement elm; + CcviewDoc *pDoc=GetDocument(); + + elm=pDoc->meshelem[elmnum]; + + if (((pDoc->meshnode[elm.p[0]].xs == pDoc->meshnode[elm.p[1]].xs) && + (pDoc->meshnode[elm.p[1]].xs == pDoc->meshnode[elm.p[2]].xs)) || + ((pDoc->meshnode[elm.p[0]].ys == pDoc->meshnode[elm.p[1]].ys) && + (pDoc->meshnode[elm.p[1]].ys == pDoc->meshnode[elm.p[2]].ys) )) return; + + if(pDoc->blocklist[elm.lbl].IsSelected==TRUE) return; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + for(i=0;i<3;i++) + { + switch(DensityPlot) + { + // |Voltage| + case 1: + bn[i]=abs(pDoc->meshnode[elm.p[i]].v); + break; + + // |Re(Voltage)| + case 2: + bn[i]=Re(pDoc->meshnode[elm.p[i]].v); + break; + + // |Im(Voltage)| + case 3: + bn[i]=Im(pDoc->meshnode[elm.p[i]].v); + break; + + // |J| + case 4: + if (pDoc->Smooth==TRUE) + bn[i]=abs(abs(elm.jx[i])+I*abs(elm.jy[i])); + else + bn[i]=abs(abs(elm.Jx)+I*abs(elm.Jy)); + break; + + // |Re(J)| + case 5: + if (pDoc->Smooth==TRUE) + bn[i]=abs(Re(elm.jx[i].re)+I*Re(elm.jy[i])); + else + bn[i]=abs(Re(elm.Jx)+I*Re(elm.Jy)); + break; + + // |Im(J)| + case 6: + if (pDoc->Smooth==TRUE) + bn[i]=abs(Im(elm.jx[i])+I*Im(elm.jy[i])); + else + bn[i]=abs(Im(elm.Jx)+I*Im(elm.Jy)); + break; + + // |E| + case 7: + if (pDoc->Smooth==TRUE){ + Ex=elm.jx[i]/pDoc->blockproplist[elm.blk].Kx; + Ey=elm.jy[i]/pDoc->blockproplist[elm.blk].Ky; + } + else{ + Ex=elm.Jx/pDoc->blockproplist[elm.blk].Kx; + Ey=elm.Jy/pDoc->blockproplist[elm.blk].Ky; + } + bn[i]=abs(abs(Ex)+I*abs(Ey)); + break; + + // |Re(E)| + case 8: + if (pDoc->Smooth==TRUE){ + Ex=Re(elm.jx[i]/pDoc->blockproplist[elm.blk].Kx); + Ey=Re(elm.jy[i]/pDoc->blockproplist[elm.blk].Ky); + } + else{ + Ex=Re(elm.Jx/pDoc->blockproplist[elm.blk].Kx); + Ey=Re(elm.Jy/pDoc->blockproplist[elm.blk].Ky); + } + bn[i]=abs(abs(Ex)+I*abs(Ey)); + break; + + // |Im(E)| + case 9: + if (pDoc->Smooth==TRUE){ + Ex=Im(elm.jx[i]/pDoc->blockproplist[elm.blk].Kx); + Ey=Im(elm.jy[i]/pDoc->blockproplist[elm.blk].Ky); + } + else{ + Ex=Im(elm.Jx/pDoc->blockproplist[elm.blk].Kx); + Ey=Im(elm.Jy/pDoc->blockproplist[elm.blk].Ky); + } + bn[i]=abs(abs(Ex)+I*abs(Ey)); + break; + + default: + bn[i]=0; + break; + } + } + + flag=1; + + bl=pDoc->PlotBounds[DensityPlot-1][0]; + bh=pDoc->PlotBounds[DensityPlot-1][1]; + + if(bh==bl) return; + else for(i=0;i<3;i++) bn[i]=20.*(bn[i]-bl)/(bh-bl); + + // find subtriangle edges; + for(i=0,n=0;i<3;i++) + { + c[n][0]=(double) pDoc->meshnode[elm.p[i]].xs; + c[n][1]=(double) pDoc->meshnode[elm.p[i]].ys; + c[n][2]=bn[i]; + n++; if(n>=64) return; + j=i+1; if(j==3) j=0; + p[0][0]=(double) pDoc->meshnode[elm.p[i]].xs; + p[0][1]=(double) pDoc->meshnode[elm.p[i]].ys; + p[1][0]=(double) pDoc->meshnode[elm.p[j]].xs; + p[1][1]=(double) pDoc->meshnode[elm.p[j]].ys; + p[2][0]=bn[i]; + p[2][1]=bn[j]; + if(p[2][0]=0) && (z<20)) n++; + if(n>=64) return; + } + else + for(z=floor(p[2][0]);z>p[2][1];z--) + { + y=(z-p[2][0])/(p[2][1]-p[2][0]); + c[n][0]=(1.-y)*p[0][0] + y*p[1][0]; + c[n][1]=(1.-y)*p[0][1] + y*p[1][1]; + c[n][2]=(1.-y)*p[2][0] + y*p[2][1]; + if ((z>=0) && (z<20)) n++; + if(n>=64) return; + } + + } + + // subtriangle vertices are now listed in the c[][] array. + // there are n vertices. Now, plot out these subtriangles; + + do{ + // find lowest vertex & neighbors; + for(i=1,j=0;i=n) k=0; + + // plot triangle; + b=(c[i][2]+c[j][2]+c[k][2])/3.; + lav=19-((int) b); + if(lav>19) lav=19; + if(lav<0) lav=0; + + { + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + BOOL DrawIt=TRUE; + + if (GreyContours==FALSE){ + if(mymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(mymap[lav]); + FillPen.CreatePen(PS_SOLID,1,mymap[lav]); + } + } + else{ + if(greymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(greymap[lav]); + FillPen.CreatePen(PS_SOLID,1,greymap[lav]); + } + } + if(DrawIt==TRUE) + { + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + ps[0].x=(long) c[i][0]; ps[0].y=(long) c[i][1]; + ps[1].x=(long) c[j][0]; ps[1].y=(long) c[j][1]; + ps[2].x=(long) c[k][0]; ps[2].y=(long) c[k][1]; + pDC->Polygon(ps,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); + } + } + + // remove middle point from the list; + for(i=j;i2); +} + +/////////////// + +void CcviewView::PlotSelectedElm(CDC *pDC,CElement &elm) +{ + int i; + POINT p[3]; + CcviewDoc *pDoc=GetDocument(); + + if (elm.lbl!=DrawSelected) + if (pDoc->blocklist[elm.lbl].IsSelected==FALSE) return; + + for(i=0;i<3;i++){ + p[i].x=pDoc->meshnode[elm.p[i]].xs; + p[i].y=pDoc->meshnode[elm.p[i]].ys; + } + + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + if (pDoc->blocklist[elm.lbl].IsSelected==TRUE) + { + FillBrush.CreateSolidBrush(RegionColor); + FillPen.CreatePen(PS_SOLID,1,RegionColor); + } + else{ + FillBrush.CreateSolidBrush(0x00ffffff); + FillPen.CreatePen(PS_SOLID,1,0x00ffffff); + } + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + pDC->Polygon(p,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); +} + +void CcviewView::DrawUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CcviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,FALSE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,FALSE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,FALSE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CcviewView::EraseUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + CcviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,TRUE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,TRUE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,TRUE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void CcviewView::OnDraw(CDC* pDC) +{ + CcviewDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + RECT r; + static RECT oldr; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,dt,R; + double xss,yss,rss,rt; + CComplex p,c,s; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if(pDoc->FirstDraw<0) + { + pDoc->Smooth=d_Smooth; + pDoc->FirstDraw=FALSE; + } + + if(pDoc->FirstDraw==TRUE){ + // Apply default behaviors + ox=0.; oy=0.; mag=100.; + GridSize=0.25; + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + if(pDoc->bMultiplyDefinedLabels){ + EditAction=2; + ShowNames=TRUE; + } + else{ + EditAction=d_EditAction; + ShowNames=d_ShowNames; + } + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowAi=d_ShowAi; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; + pDoc->Smooth=d_Smooth; + + OnZoomNatural(); + LinePix.RemoveAll(); + oldr=r; + OnViewInfo(); + } + + if((oldr.right!=r.right) || (oldr.bottom!=r.bottom)) + { + LinePix.RemoveAll(); + oldr=r; + } + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + // just give up and make sure that the right + // buttons are checked every time through OnDraw; + // otherwise, it's just too easy to get the buttons + // so that they don't match the actual mode. + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen, + penMesh,penReal,penImag,penMask, + penNode,penText,penRealVector,penImagVector; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penReal.CreatePen(PS_SOLID,1,RealFluxLineColor); + penImag.CreatePen(PS_SOLID,1,ImagFluxLineColor); + penMask.CreatePen(PS_SOLID,1,MaskLineColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penText.CreatePen(PS_SOLID,1,TextColor); + penRealVector.CreatePen(PS_SOLID,1,RealVectorColor); + penImagVector.CreatePen(PS_SOLID,1,ImagVectorColor); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=2.; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // get center and radius of the screen in drawing coords. + // can then use to find out whether elements are off the screen. + xs=(r.right+r.left)/2; + ys=(r.top+r.bottom)/2; + ScreenToDwg(xs,ys, &xss, &yss, &r); + rss=sqrt(pow((double)r.bottom,2.) + pow((double)r.right,2.))/(2.*mag); + + // Draw selected area... + if (EditAction==2) + { + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + PlotSelectedElm(pDC,pDoc->meshelem[i]); + } + } + } + + // Draw flux densities if they are enabled... + if(DensityPlot!=0){ + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=abs(CComplex(xss,yss)-pDoc->meshelem[i].ctr); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + { + PlotFluxDensity(pDC,i,DensityPlot); + } + } + } + } + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + int pi,po,OnBoundary; + + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshelem.GetSize();i++) + { + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + + OnBoundary=FALSE; + for(j=0;j<3;j++) + if (pDoc->meshelem[i].n[j] == 1) + OnBoundary=TRUE; + + for(j=0;j<3;j++) + { + k=j+1; if (k==3) k=0; + pi=pDoc->meshelem[i].p[j]; + po=pDoc->meshelem[i].p[k]; + + if((po>pi) || (OnBoundary==TRUE)) + { + MyMoveTo(pDC,pDoc->meshnode[pi].xs, + pDoc->meshnode[pi].ys); + MyLineTo(pDC,pDoc->meshnode[po].xs, + pDoc->meshnode[po].ys); + } + } + } + } + pDC->SelectObject( pOldPen ); + } + + // Draw contour lines, if they are enabled. + pOldPen = pDC->SelectObject( &penReal ); + if (ShowAr==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,0); + } + } + + pDC->SelectObject( &penImag ); + if (ShowAi==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,1); + } + } + + pDC->SelectObject(&penMask); + if (ShowMask==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,2); + } + } + + pDC->SelectObject( pOldPen ); + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].Hidden==FALSE){ + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].Hidden==FALSE){ + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].MaxSideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + if(PtsFlag==TRUE) for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + + // Draw vectors + if ((VectorPlot>0) && (pDoc->nodelist.GetSize()>0)) + { + CPointVals u; + BOOL drawgrid=TRUE; + BOOL PlotJ; + double MaxVal; + int xp,yp; + CComplex vr,va,c0,c1; + CComplex px,py; + int ilo,ihi,jlo,jhi; + + if ((VectorPlot==1) || (VectorPlot==3) || (VectorPlot==5)) + { + MaxVal=pDoc->d_PlotBounds[3][1]; + PlotJ=TRUE; + } + else{ + MaxVal=pDoc->d_PlotBounds[6][1]; + PlotJ=FALSE; + } + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Vectors too dense to display.",TRUE); + } + else{ + int MakePlots=(VectorPlot+1)/2; + + for(k=0;kmeshelem.GetSize();k++) + { + rt=abs(CComplex(xss,yss)-pDoc->meshelem[k].ctr); + if( rt < ( sqrt(pDoc->meshelem[k].rsqr) + rss) ) + { + c0=pDoc->meshelem[k].ctr-sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c1=pDoc->meshelem[k].ctr+sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c0/=GridSize; + c1/=GridSize; + ilo=(int) floor(Re(c0)); + ihi=(int) ceil (Re(c1)); + jlo=(int) floor(Im(c0)); + jhi=(int) ceil (Im(c1)); + for(i=ilo;i<=ihi;i++) + { + for(j=jlo;j<=jhi;j++) + { + xd=GridSize*((double) i); + yd=GridSize*((double) j); + if(pDoc->InTriangleTest(xd,yd,k)) + { + pDoc->GetPointValues(xd,yd,k,u); + px=u.Jx; py=u.Jy; + if(!PlotJ){ + px/=u.Kx; + py/=u.Ky; + } + + // plot real arrows + if (MakePlots & 1){ + pOldPen = pDC->SelectObject( &penRealVector); + vr=(Re(px)+I*Re(py))*GridSize*VectorScaleFactor/MaxVal; + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, RealVectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + pDC->SelectObject( pOldPen ); + } + + // plot imaginary arrows + if (MakePlots & 2){ + pOldPen = pDC->SelectObject( &penImagVector); + vr=(Im(px)+I*Im(py))*GridSize*VectorScaleFactor/MaxVal; + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, ImagVectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + pDC->SelectObject( pOldPen ); + } + } + } + } + } // end of if(rt<... + } + + } + } + + if(EditAction==1) DrawUserContour(TRUE); + + // draw block names/labels + if(ShowNames){ + pDC->SetTextColor(NameColor); + pOldPen = pDC->SelectObject( &penGreen ); + CString lbl; + for(i=0;iblocklist.GetSize();i++) + { + + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + lbl=pDoc->blockproplist[pDoc->blocklist[i].BlockType].BlockName; + pDC->TextOut(xs+5,ys,lbl); + } + pDC->SelectObject( pOldPen ); + } + + // Draw Legend if it is enabled; + if((LegendFlag==TRUE) && (DensityPlot!=0)) + { + CBrush *pOldBrush; + char cc[80]; + double dta; + CBrush BackBrush; + + pOldPen = pDC->SelectObject( &penText ); + pDC->SetTextColor(TextColor); + pDC->SetBkMode(TRANSPARENT); + pDC->SetTextAlign(TA_TOP); + pDC->SetTextAlign(TA_LEFT); + BackBrush.CreateSolidBrush(BackColor); + pOldBrush = pDC->SelectObject( &BackBrush ); + pDC->Rectangle(r.right-212-6,r.top+6,r.right-6,r.top+24+21*16 ); + pDC->SelectObject(pOldBrush); + + if (DensityPlot==1) sprintf(cc,"Density Plot: |V|, Volts"); + if (DensityPlot==2) sprintf(cc,"Density Plot: |Re(V)|, Volts"); + if (DensityPlot==3) sprintf(cc,"Density Plot: |Im(V)|, Volts"); + if (DensityPlot==4) sprintf(cc,"Density Plot: |J|, A/m^2"); + if (DensityPlot==5) sprintf(cc,"Density Plot: |Re(J)|, A/m^2"); + if (DensityPlot==6) sprintf(cc,"Density Plot: |Im(J)|, A/m^2"); + if (DensityPlot==7) sprintf(cc,"Density Plot: |E|, V/m"); + if (DensityPlot==8) sprintf(cc,"Density Plot: |Re(E)|, V/m"); + if (DensityPlot==9) sprintf(cc,"Density Plot: |Im(E)|, V/m"); + pDC->TextOut(r.right-212,r.top+16*20+16,cc,(int) strlen(cc)); + + dta=(pDoc->PlotBounds[DensityPlot-1][1]- + pDoc->PlotBounds[DensityPlot-1][0])/20.; + + for(i=0;i<20;i++){ + + { + CBrush FillBrush; + + if (GreyContours==FALSE) FillBrush.CreateSolidBrush(mymap[i]); + else FillBrush.CreateSolidBrush(greymap[i]); + pOldBrush = pDC->SelectObject( &FillBrush ); + pDC->Rectangle(r.right-212,r.top+16*i+12,r.right-187,r.top+12+16*(i+1) ); + pDC->SelectObject(pOldBrush); + } + + double Blb=pDoc->PlotBounds[DensityPlot-1][0]; + double Bub=pDoc->PlotBounds[DensityPlot-1][1]; + if(i==0) + sprintf(cc,"%.3e : >%.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else if(i==19) + sprintf(cc,"<%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else + sprintf(cc,"%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + pDC->TextOut(r.right-182,r.top+16*i+12,cc,(int) strlen(cc)); + } + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +///////////////////////////////////////////////////////////////////////////// +// CcviewView printing + +BOOL CcviewView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CcviewView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CcviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CcviewView diagnostics + +#ifdef _DEBUG +void CcviewView::AssertValid() const +{ + CView::AssertValid(); +} + +void CcviewView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CcviewDoc* CcviewView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CcviewDoc))); + return (CcviewDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CcviewView message handlers + +void CcviewView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + CcviewDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ((SnapFlag==TRUE) && (EditAction!=2) && (ZoomWndFlag==0)){ + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + // draw box for window zoom; + if(ZoomWndFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int)ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + } + + + // update mouse position; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CcviewView::OnZoomIn() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + RedrawView(); +} + +void CcviewView::OnZoomOut() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + RedrawView(); +} + +void CcviewView::OnZoomNatural() +{ + CcviewDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else RedrawView(); +} + + +void CcviewView::OnKbdZoom() +{ + CcviewDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + RedrawView(); +} + +void CcviewView::OnSetGrid() +{ + CGridMod pDlg; + CcviewDoc *pDoc=GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + RedrawView(); + } +} + +void CcviewView::OnSnapGrid() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void CcviewView::OnShowMesh() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + } + + RedrawView(); +} + + +void CcviewView::OnCplot() +{ + CcviewDoc *pDoc=GetDocument(); + + cvCCPlotDlg2 dlg; + dlg.m_showa=ShowAr; + dlg.m_showa2=ShowAi; + dlg.m_showmask=ShowMask; + dlg.m_numcontours=NumContours; + dlg.m_alow=pDoc->A_Low; + dlg.m_ahigh=pDoc->A_High; + dlg.Alb=__min(pDoc->A_lb.re,pDoc->A_lb.im); + dlg.Aub=__max(pDoc->A_ub.re,pDoc->A_ub.im); + if(dlg.DoModal()==IDOK){ + ShowAr=dlg.m_showa; + ShowAi=dlg.m_showa2; + ShowMask=dlg.m_showmask; + pDoc->A_Low=dlg.m_alow; + pDoc->A_High=dlg.m_ahigh; + NumContours=dlg.m_numcontours; + RedrawView(); + } + +} + +void CcviewView::OnDplot() +{ + CcviewDoc *pDoc=GetDocument(); + int i,k; + + cvCDPlotDlg2 dlg; + + if(!DensityPlot) dlg.m_showit=FALSE; + else dlg.m_showit=TRUE; + dlg.m_showlegend=LegendFlag; + dlg.m_gscale=GreyContours; + dlg.DensityPlot=DensityPlot; + dlg.listtype=0; + + for(i=0;i<9;i++) + for(k=0;k<2;k++) + { + dlg.PlotBounds[i][k]=pDoc->PlotBounds[i][k]; + dlg.d_PlotBounds[i][k]=pDoc->d_PlotBounds[i][k]; + } + + if(dlg.DoModal()==IDOK){ + if(dlg.m_showit) DensityPlot=dlg.DensityPlot; + else DensityPlot=0; + LegendFlag=dlg.m_showlegend; + GreyContours=dlg.m_gscale; + for(i=0;i<9;i++) + for(k=0;k<2;k++) + pDoc->PlotBounds[i][k]=dlg.PlotBounds[i][k]; + RedrawView(); + } +} + +void CcviewView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame"); + else{ + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + Dspl=&MFrm->m_dlgBar; + } + + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); +} + +void CcviewView::DisplayPointProperties(double px, double py) +{ + CcviewDoc* pDoc = GetDocument(); + char c[80]; + CPointVals u; + CComplex Jtot; + if (pDoc->nodelist.GetSize()==0) return; + if(pDoc->GetPointValues(px, py, u)==TRUE) + { + CString outbox,s; + if (pDoc->ProblemType>=0) + { + if (pDoc->ProblemType==0) + { + s.Format("Point: x=%g, y=%g",px,py); + outbox=s; + s.Format("V = %s V",u.v.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|J| = %g A/m^2",abs(abs(u.Jx) + I*abs(u.Jy))); + outbox+="\r\n"+s; + s.Format("Jx = %s A/m^2",u.Jx.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Jy = %s A/m^2",u.Jy.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|E| = %g V/m",abs(abs(u.Ex) + I*abs(u.Ey))); + outbox+="\r\n"+s; + s.Format("Ex = %s V/m",u.Ex.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Ey = %s V/m",u.Ey.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("ex = %s (rel)",u.ex.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("ey = %s (rel)",u.ey.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("ox = %g S/m",u.ox); + outbox+="\r\n"+s; + s.Format("oy = %g S/m",u.ox); + outbox+="\r\n"+s; + s.Format("|Jc| = %g A/m^2",abs(abs(u.Jcx) + I*abs(u.Jcy))); + outbox+="\r\n"+s; + s.Format("|Jd| = %g A/m^2",abs(abs(u.Jdx) + I*abs(u.Jdy))); + outbox+="\r\n"+s; + + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + else{ + s.Format("Point: r=%g, z=%g",px,py); + outbox=s; + s.Format("V = %s V",u.v.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|J| = %g A/m^2",abs(abs(u.Jx) + I*abs(u.Jy))); + outbox+="\r\n"+s; + s.Format("Jr = %s A/m^2",u.Jx.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Jz = %s A/m^2",u.Jy.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("|E| = %g V/m",abs(abs(u.Ex) + I*abs(u.Ey))); + outbox+="\r\n"+s; + s.Format("Er = %s V/m",u.Ex.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("Ez = %s V/m",u.Ey.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("er = %s (rel)",u.ex.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("ez = %s (rel)",u.ey.ToStringAlt(c)); + outbox+="\r\n"+s; + s.Format("or = %g S/m",u.ox); + outbox+="\r\n"+s; + s.Format("oz = %g S/m",u.ox); + outbox+="\r\n"+s; + s.Format("|Jc| = %g A/m^2",abs(abs(u.Jcx) + I*abs(u.Jcy))); + outbox+="\r\n"+s; + s.Format("|Jd| = %g A/m^2",abs(abs(u.Jdx) + I*abs(u.Jdy))); + outbox+="\r\n"+s; + + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + } +} +} + +void CcviewView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonDown(nFlags, point); + return; + } + + int i,j,k,m; + + if (ZoomWndFlag==1) + { + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0) DisplayPointProperties(mx,my); + + if (EditAction==1){ + CcviewDoc *pDoc=GetDocument(); + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + DrawUserContour(FALSE); + return; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(y); + DrawUserContour(FALSE); + } + } + } + } + + if (EditAction==2){ + CcviewDoc *pDoc=GetDocument(); + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + pDoc->blocklist[pDoc->meshelem[k].lbl].ToggleSelect(); + DrawSelected=pDoc->meshelem[k].lbl; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + + } + + CView::OnLButtonDown(nFlags, point); +} + +void CcviewView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag>0){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + RedrawView(); + return; + } + RECT r; + double z,cmag,m[2]; + if (mxcontour.GetSize(); + if(i>0){ + if (z!=pDoc->contour[i-1]) + pDoc->contour.Add(z); + } + else pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(EditAction==2){ + CcviewDoc *pDoc=GetDocument(); + int clnode,clseg,claseg,i,j; + double dnode,dseg,daseg,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InConductor; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InConductor; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InConductor; + } + + if (j<0) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + pDoc->bHasMask=FALSE; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InConductor==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InConductor==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InConductor==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (pDoc->meshnode[i].Q==j) + { + pDoc->meshnode[i].IsSelected=1-pDoc->meshnode[i].IsSelected; + } + } + // DrawPSLG(); + RedrawView(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void CcviewView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CcviewView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void CcviewView::OnReload() +{ + CcviewDoc *pDoc=GetDocument(); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->OnReload(); + if (bLinehook==FALSE) EndWaitCursor(); + if (d_ResetOnReload==FALSE) pDoc->FirstDraw=FALSE; + RedrawView(); + OnViewInfo(); +} + +void CcviewView::OnMenuArea() +{ + CcviewDoc *pDoc=GetDocument(); + if(EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, TRUE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CcviewView::OnMenushowpts() +{ + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(PtsFlag==FALSE){ + PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + } + else{ + PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + } + RedrawView(); +} + +void CcviewView::OnMenuContour() +{ + CcviewDoc *pDoc=GetDocument(); + + if(EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + + RedrawView(); + } + + EditAction=1; + + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, TRUE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void CcviewView::OnMenuPoint() +{ + CcviewDoc *pDoc=GetDocument(); + + if (EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + if (EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + RedrawView(); + } + + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_CV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, TRUE); + +} + +void CcviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CcviewDoc *pDoc=GetDocument(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if ((nChar==VK_TAB) && (EditAction!=2)) EnterPoint(); + + if ((nChar==VK_DELETE) && (EditAction==1)){ + int k; + k=(int) pDoc->contour.GetSize(); + + if(k>1){ + EraseUserContour(FALSE); + pDoc->contour.RemoveAt(k-1); + DrawUserContour(TRUE); + } + else if(k!=0){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAt(0); + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==1)){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + + if ((nChar==VK_SHIFT) && (EditAction==1)){ + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==2)){ + UnselectAll(); + RedrawView(); + } + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CcviewView::UnselectAll() +{ + CcviewDoc *pDoc=GetDocument(); + int i; + + pDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) pDoc->blocklist[i].IsSelected=FALSE; + for(i=0;imeshnode.GetSize();i++) pDoc->meshnode[i].IsSelected=FALSE; + for(i=0;inodelist.GetSize();i++) pDoc->nodelist[i].IsSelected=FALSE; + for(i=0;ilinelist.GetSize();i++) pDoc->linelist[i].IsSelected=FALSE; + for(i=0;iarclist.GetSize();i++) pDoc->arclist[i].IsSelected=FALSE; +} + +void CcviewView::EnterPoint() +{ + CEnterPt pDlg; + double x,y,t; + CcviewDoc* pDoc = GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + if (EditAction==0) DisplayPointProperties(x,y); + if (EditAction==1){ + CComplex z; + z.Set(x,y); + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + } +} + +void CcviewView::SpecialLine(CDC *pDC, int X0, int Y0, int X1, int Y1, int flag) +{ + double l; + int i,j,k,p,x,y,z; + int hi,lo,zj; + BOOL InLine,DrawIt; + COLORREF c; + COLORREF Red; + RECT r; + + GetClientRect(&r); + Red=SelColor; + + int x0,y0,x1,y1,xb,yb; + + x0=X0; y0=Y0; + x1=X1; y1=Y1; + xb=r.right; + yb=r.bottom; + DrawIt=TRUE; + + // test to see if any of the endpoints are offscreen. + // if they are, crop them to the screen size + if ((x0<0) || (x0>xb) || (x1<0) || (x1>xb) || + (y0<0) || (y0>yb) || (y1<0) || (y1>yb)) + { + DrawIt=FALSE; + double z,dx0,dx1,dy0,dy1,dxb,dyb; + dx0=(double) x0; + dy0=(double) y0; + dx1=(double) x1; + dy1=(double) y1; + dxb=(double) xb; + dyb=(double) yb; + + + if ((x1-x0)!=0) + { + // test left side; + z=(-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0<0) + { + dx0=0; + x0=0; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=0; + x1=0; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + // test right side; + z=(dxb-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0>xb) + { + dx0=dxb; + x0=xb; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=dxb; + x1=xb; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + } + + if ((y1-y0)!=0) + { + // test top side; + z=(-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0<0) + { + dy0=0; + y0=0; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=0; + y1=0; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + + // test bottom side; + z=(dyb-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0>dyb) + { + dy0=dyb; + y0=yb; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=dyb; + y1=yb; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + } + } + + if(!DrawIt) return; + + l=(double)((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + l=sqrt(l); + k=(int) l; + for(i=0;i<=k;i++) + { + if(k!=0){ + x=x0+((x1-x0)*i)/k; + y=y0+((y1-y0)*i)/k; + } + else{ + x=x0; + y=y0; + } + + z=x+y*r.right; + + // check if this point is already in the line + // in the case that a red line is supposed to be drawn; + + if(flag==FALSE) + { + // bisection search to see if the pixel under + // consideration is already in LinePix + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj) InLine=TRUE; + } + zj=LinePix[hi].z; + if(z>=zj){ + hi+=1; + lo=hi; + if(z==zj) InLine=TRUE; + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + break; + } + else if(zjGetPixel(x,y); + if (hi==(int) LinePix.GetSize()) LinePix.Add(NewPixel); + else LinePix.InsertAt(hi,NewPixel); + } + } + + // if line is to be erased, get entry out of the pixel list + if(flag!=FALSE){ + // bisection search to find the pixel + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj){ + InLine=TRUE; + p=0; + } + } + zj=LinePix[hi].z; + if(z>=zj){ + lo=hi; + if(z==zj){ + InLine=TRUE; + p=hi; + } + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + p=j; + break; + } + else if(zjPtVisible(x,y)!=FALSE) + { + if(flag==FALSE) pDC->SetPixel(x,y,Red); + else if(InLine==TRUE) pDC->SetPixel(x,y,c); + } + } + +} + + +void CcviewView::OnMenuPlot() +{ + cvCXYPlotDlg dlg; + CcviewDoc *pDoc=GetDocument(); + int PlotType,npoints,FileFormat; + BOOL ToFile; + + if ((EditAction!=1) || (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot create a plot;\nNo contour has been defined"); + return; + } + + dlg.m_npoints=d_PlotPoints; + if (dlg.DoModal()==IDOK){ + PlotType=dlg.XYPlotType; + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + CXYPlot xyplot; + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->GetLineValues(xyplot,PlotType,npoints); + if (bLinehook==FALSE) EndWaitCursor(); + if(ToFile==FALSE){ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else xyplot.ToDisk(FileFormat); + } +} + +void CcviewView::OnMenuIntegrate() +{ + CcviewDoc *pDoc=GetDocument(); + int inttype; + + if (EditAction==0){ + MsgBox("Cannot integrate;\nNo contour or area\nhas been defined."); + return; + } + + if ((EditAction==1) && (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot integrate;\nNo contour has been defined"); + return; + } + + if (EditAction==2){ + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + for(i=0;imeshnode.GetSize();i++) + if (pDoc->meshnode[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE){ + MsgBox("Cannot integrate;\nNo area has been selected"); + return; + } + } + + if(EditAction==1){ + cvCLIntDlg dlg; + int inttype; + CComplex z[4]; + char c[80],d[80],s[512]; + CString ss; + + dlg.Frequency=pDoc->Frequency; + if(dlg.DoModal()==IDOK){ + inttype=dlg.linttype; + switch(inttype) + { + case 0: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Voltage Difference = %s Volts",z[0].ToStringAlt(c)); + MyMessageBox(s); + break; + + case 1: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + sprintf(s,"Current = %s A\nAverage Current = %s A/m^2", + z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + MyMessageBox(s); + break; + + case 2: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Contour length = %g meters\nSurface Area = %g meter^2",Re(z[0]),Re(z[1])); + MyMessageBox(s); + break; + + case 4: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if (pDoc->ProblemType==0){ + sprintf(s,"DC Force:\n x-direction = %g N\n y-direction = %g N\n",z[2].re,z[3].re); + ss=s; + sprintf(s,"\n%g Hz Force:\n x-direction = %s N\n y-direction = %s N", + pDoc->Frequency*2.,z[0].ToStringAlt(c),z[1].ToStringAlt(d)); + ss+=s; + } + else{ + sprintf(s,"DC Force:\n z-direction = %g N",z[3].re); + ss=s; + sprintf(s,"\n%g Hz Force:\n z-direction = %s N", + pDoc->Frequency*2.,z[1].ToStringAlt(c)); + ss+=s; + } + MyMessageBox(ss); + break; + + case 5: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + if (pDoc->ProblemType==0){ + sprintf(s,"Torque about (0,0):\nDC Torque = %g N*m\n",z[1].re); + ss=s; + sprintf(s,"%g Hz Torque = %s N*m", + pDoc->Frequency*2.,z[0].ToStringAlt(c)); + ss+=s; + } + else{ + sprintf(s,"No net torque in axisymmetric case"); + ss=s; + } + MyMessageBox(ss); + break; + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + } + } + + if(EditAction==2){ + cvCBlockInt dlg; + char c[80],d[80]; + + dlg.Frequency=pDoc->Frequency; + if(dlg.DoModal()==IDOK){ + inttype=dlg.binttype; + CComplex z1,z2,z3,z4; + char s[512]; + // Average Temp over volume + // Block cross-section area + // Block volume + // Average F over volume + // Average G over volume + switch(inttype) + { + case 0: + z1=pDoc->BlockIntegral(0); + sprintf(s,"%g W",Re(z1)); + break; + + case 1: + z1=pDoc->BlockIntegral(1); + sprintf(s,"%g VAR",abs(z1)); + break; + case 2: + z1=pDoc->BlockIntegral(2); + sprintf(s,"%g VA",abs(z1)); + break; + + case 3: + z1=pDoc->BlockIntegral(3); + sprintf(s,"%g J",Re(z1)); + break; + + case 4: + z1=pDoc->BlockIntegral(4); + sprintf(s,"%g m^2",Re(z1)); + break; + + case 5: + z1=pDoc->BlockIntegral(5); + sprintf(s,"%g m^3",Re(z1)); + break; + + // Weighted Stress Tensor Force + case 6: + if (!pDoc->MakeMask()) return; + z1=pDoc->BlockIntegral(6); + z2=pDoc->BlockIntegral(7); + z3=pDoc->BlockIntegral(8); + z4=pDoc->BlockIntegral(9); + if(pDoc->ProblemType==0){ + sprintf(s,"Steady-state force:\nx-component: %g N\ny-component: %g N\n2x Frequency force:\nx-component: %s N\ny-component: %s N", + z1.re,z2.re,z3.ToStringAlt(c),z4.ToStringAlt(d)); + } + else{ + sprintf(s,"Steady-state force:\nr-component: 0. N\nz-component: %g N\n2x Frequency force:\nr-component: 0. N\nz-component: %s N", + z2.re,z4.ToStringAlt(d)); + } + if (ShowMask) InvalidateRect(NULL); + break; + + // Weighted Stress Tensor Torque + case 7: + if (!pDoc->MakeMask()) return; + z1=pDoc->BlockIntegral(10); + z2=pDoc->BlockIntegral(11); + if(pDoc->ProblemType==0) + { + sprintf(s,"Torque about (0,0):\nSteady State: %g N*m\n2x Frequency: %s N*m", + z1.re,z2.ToStringAlt(d)); + } + else{ + sprintf(s,"No torque possible in axisymmetric case"); + } + if (ShowMask) InvalidateRect(NULL); + break; + + default: + sprintf(s,"Invalid integral selection"); + break; + } + MyMessageBox(s); + } + + } +} + + + +void CcviewView::OnSmooth() +{ + CcviewDoc *pDoc=GetDocument(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if (pDoc->Smooth==TRUE){ + pDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + } + else{ + pDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + + RedrawView(); +} + +BOOL CcviewView::OnEraseBkgnd(CDC* pDC) +{ + + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + return TRUE; + +} + +void CcviewView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + CcviewDoc *pDoc=GetDocument(); + + if(EditAction==0){ + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + sprintf(s,"Closest input node:\n(%g,%g)",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + AfxMessageBox(s,MB_ICONINFORMATION); + } + } + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + CView::OnRButtonDblClk(nFlags, point); +} + + + + +void CcviewView::OnPanDown() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy-=0.25*y/mag; + + RedrawView(); +} + +void CcviewView::OnPanLeft() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; + + RedrawView(); +} + +void CcviewView::OnPanRight() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; + + RedrawView(); +} + +void CcviewView::OnPanUp() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy+=0.25*y/mag; + + RedrawView(); +} + +void CcviewView::OnViewCircprops() +{ + cvCCircDlg dlg; + + dlg.TheDoc=GetDocument(); + dlg.DoModal(); + +} + +void CcviewView::RedrawView() +{ + LinePix.RemoveAll(); + InvalidateRect(NULL); +} + +BOOL CcviewView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"cview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAi); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowNames); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +BOOL CcviewView::WritePreferences() +{ + FILE *fp; + CString fname; + CcviewDoc *pDoc=GetDocument(); + + fname=BinDir+"cview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("FluxIColor",ImagFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorRColor", RealVectorColor,fp); + WriteColor("VectorIColor", ImagVectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",d_EditAction); + fprintf(fp," = %i\n",d_DensityPlot); + fprintf(fp," = %i\n",d_VectorPlot); + fprintf(fp," = %i\n",d_GridFlag); + fprintf(fp," = %i\n",d_SnapFlag); + fprintf(fp," = %i\n",d_MeshFlag); + fprintf(fp," = %i\n",d_LegendFlag); + fprintf(fp," = %i\n",d_NumContours); + fprintf(fp," = %i\n",d_ShowAr); + fprintf(fp," = %i\n",d_ShowAi); + fprintf(fp," = %i\n",d_ShowMask); + fprintf(fp," = %i\n",d_GreyContours); + fprintf(fp," = %i\n",d_PtsFlag); + fprintf(fp," = %i\n",d_ResetOnReload); + fprintf(fp," = %i\n",d_Smooth); + fprintf(fp," = %i\n",d_PlotPoints); + fprintf(fp," = %i\n",d_ShowNames); + fprintf(fp," = %i\n", + pDoc->d_LineIntegralPoints); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void CcviewView::CheckIt() +{ + // make sure all of the right things are checked + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar1,*pToolBar2; + pToolBar1=&MFrm->m_CV_toolBar1; + pToolBar2=&MFrm->m_leftbar; + CToolBarCtrl *tc1=&pToolBar1->GetToolBarCtrl(); + CToolBarCtrl *tc2=&pToolBar2->GetToolBarCtrl(); + + if(SnapFlag==FALSE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc2->PressButton(ID_SNAP_GRID,TRUE); + } + + + if(GridFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc2->PressButton(ID_SHOW_GRID,TRUE); + } + + if(MeshFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc1->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc1->PressButton(ID_SHOW_MESH,TRUE); + } + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc1->PressButton(ID_MENU_AREA, FALSE); + tc1->PressButton(ID_MENU_CONTOUR, FALSE); + tc1->PressButton(ID_MENU_POINT,FALSE); + + if (EditAction==2){ + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + tc1->PressButton(ID_MENU_AREA, TRUE); + } + if (EditAction==1){ + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + tc1->PressButton(ID_MENU_CONTOUR, TRUE); + } + if (EditAction==0){ + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc1->PressButton(ID_MENU_POINT,TRUE); + } + + if(PtsFlag==TRUE) + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + CcviewDoc *pDoc=GetDocument(); + if (pDoc->Smooth==FALSE) + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + + if (ShowNames==FALSE) + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_CHECKED); + + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + +} + +void CcviewView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + CcviewDoc *pDoc=GetDocument(); + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if(EditAction==2) + { + int i,k,grp,sel; + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + grp=pDoc->blocklist[pDoc->meshelem[k].lbl].InGroup; + sel=pDoc->blocklist[pDoc->meshelem[k].lbl].IsSelected; + for(i=0;iblocklist.GetSize();i++) + if ((pDoc->blocklist[i].InGroup==grp) && + (pDoc->blocklist[i].IsSelected!=sel)) + { + pDoc->blocklist[i].IsSelected=sel; + DrawSelected=i; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + } + } + + CView::OnLButtonDblClk(nFlags, point); +} + + + +void CcviewView::OnViewInfo() +{ + CcviewDoc *pDoc=GetDocument(); + CString s,z,outbox; + + // first line; + outbox.Format("Title: %s\r\n",pDoc->GetTitle()); + + // second line; + switch(pDoc->LengthUnits){ + case 0: + s="Length Units: Inches"; + z=" in"; + break; + case 1: + s="Length Units: Millimeters"; + z=" mm"; + break; + case 2: + s="Length Units: Centimeters"; + z=" cm"; + break; + case 4: + s="Length Units: Mils"; + z=" mil"; + break; + case 5: + s="Length Units: Micrometers"; + z=" um"; + break; + default: + s="Length Units: Meters"; + z=" m"; + break; + } + outbox+="\r\n" + s; + + // third line + if(pDoc->ProblemType==TRUE) s="Axisymmetric Solution"; + else{ + s.Format("2-D Planar (Depth: %g", + pDoc->Depth/pDoc->LengthConv[pDoc->LengthUnits]); + s=s+z+")"; + } + outbox+="\r\n" + s; + + // fourth line + s.Format("Frequency: %g Hz",pDoc->Frequency); + outbox+="\r\n" + s; + + // fifth line + s.Format(""); + outbox+="\r\n" + s; + + // sixth line + s.Format("%i Nodes",pDoc->meshnode.GetSize()); + outbox+="\r\n" + s; + + // seventh line + s.Format("%i Elements",pDoc->meshelem.GetSize()); + outbox+="\r\n" + s; + + // display it + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; +} + +void CcviewView::OnViewShowblocknames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + RedrawView(); +} + +void CcviewView::OnVplot() +{ + // TODO: Add your command handler code here + cvCVPlotDlg dlg; + + dlg.m_vectorscalefactor=VectorScaleFactor; + dlg.m_plottype=VectorPlot; + if(dlg.DoModal()==IDOK) + { + VectorScaleFactor=dlg.m_vectorscalefactor; + VectorPlot=dlg.m_plottype; + InvalidateRect(NULL); + } +} + +void CcviewView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void CcviewView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +BOOL CcviewView::IsMinimized() +{ + CChildFrame *pChildFrm = (CChildFrame *)GetParentFrame(); + if (pChildFrm->GetStyle() & WS_MINIMIZE) return TRUE; return FALSE; +} + +void CcviewView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if((bActivate) && (pActivateView==this)) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(8); + CheckIt(); + } + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CcviewView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void CcviewView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + // The child frame makes a special effort to pass down the + // WM_SIZE message when a window is minimized. The view + // uses this message to minimize the output window, if it is visible. + if(nType==SIZE_MINIMIZED) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if(MFrm->m_dlgBar.GetStyle() & WS_VISIBLE) MFrm->m_dlgBar.ShowWindow(SW_HIDE); + } + + if((nType==SIZE_MAXIMIZED) || (nType==SIZE_RESTORED)) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + +} diff --git a/femm/cviewView.h b/femm/cviewView.h new file mode 100644 index 0000000..8d49894 --- /dev/null +++ b/femm/cviewView.h @@ -0,0 +1,233 @@ +// cviewView.h : interface of the CcviewView class +// +///////////////////////////////////////////////////////////////////////////// + +class CcviewView : public CView +{ +protected: // create from serialization only + CcviewView(); + DECLARE_DYNCREATE(CcviewView) + +// Attributes +public: + + CcviewDoc* GetDocument(); + + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void EnterPoint(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL LegendFlag; + BOOL GreyContours; + BOOL PtsFlag; + BOOL Coords; // False=Cartesian; True=Polar + BOOL ShowNames; + double VectorScaleFactor; + int ZoomWndFlag; + int DrawSelected; + double wzx,wzy; + +// default behaviors + int d_EditAction; + BOOL d_GridFlag; + BOOL d_SnapFlag; + BOOL d_MeshFlag; + BOOL d_LegendFlag; + BOOL d_GreyContours; + int d_NumContours; + BOOL d_ShowAr; + BOOL d_ShowAi; + BOOL d_ShowMask; + int d_DensityPlot; + int d_VectorPlot; + BOOL d_PtsFlag; + BOOL d_ResetOnReload; + BOOL d_Smooth; + BOOL d_PlotPoints; + BOOL d_ShowNames; + + COutBox *Dspl; + CString BinDir; // pathname for triangle.exe + + int NumContours; + BOOL ShowAr,ShowAi,ShowMask; + int DensityPlot; + int VectorPlot; + CString OutputWindowText; + + CArray< CPixel, CPixel& > LinePix; + CArray< CZPix, CZPix& > ZoomPix; + + // Greyscale Density Plot Colormap + COLORREF Grey00; + COLORREF Grey01; + COLORREF Grey02; + COLORREF Grey03; + COLORREF Grey04; + COLORREF Grey05; + COLORREF Grey06; + COLORREF Grey07; + COLORREF Grey08; + COLORREF Grey09; + COLORREF Grey10; + COLORREF Grey11; + COLORREF Grey12; + COLORREF Grey13; + COLORREF Grey14; + COLORREF Grey15; + COLORREF Grey16; + COLORREF Grey17; + COLORREF Grey18; + COLORREF Grey19; + + // Density Plot Colormap + COLORREF Color00; + COLORREF Color01; + COLORREF Color02; + COLORREF Color03; + COLORREF Color04; + COLORREF Color05; + COLORREF Color06; + COLORREF Color07; + COLORREF Color08; + COLORREF Color09; + COLORREF Color10; + COLORREF Color11; + COLORREF Color12; + COLORREF Color13; + COLORREF Color14; + COLORREF Color15; + COLORREF Color16; + COLORREF Color17; + COLORREF Color18; + COLORREF Color19; + + // Other colors + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF RegionColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF TextColor; + COLORREF NodeColor; + COLORREF RealFluxLineColor; + COLORREF ImagFluxLineColor; + COLORREF NameColor; + COLORREF MaskLineColor; + COLORREF RealVectorColor; + COLORREF ImagVectorColor; + +// Operations +public: + + void DoContours(CDC *pDC, int *p, int side, int Aflag); + void PlotFluxDensity(CDC *pDC,int elmnum,int flag); + void DisplayPointProperties(double px, double py); + void DrawUserContour(BOOL flag); + void EraseUserContour(BOOL flag); + void SpecialLine(CDC *pDC, int x0, int y0, int x1, int y1, BOOL flag); + void PlotSelectedElm(CDC *pDC,cviewtype::CElement &elm); + void RedrawView(); + void UnselectAll(); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL IsMinimized(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void CheckIt(); + void LuaViewInfo(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CcviewView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CcviewView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CcviewView) + afx_msg void OnSmooth(); + afx_msg void OnZoomIn(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnCplot(); + afx_msg void OnDplot(); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomOut(); + afx_msg void OnZoomWindow(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnEditCopy(); + afx_msg void OnReload(); + afx_msg void OnMenuArea(); + afx_msg void OnMenuContour(); + afx_msg void OnMenuPoint(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMenuPlot(); + afx_msg void OnMenuIntegrate(); + afx_msg void OnMenushowpts(); + afx_msg void OnKbdZoom(); + afx_msg void Onintegral(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnHelpFinder(); + afx_msg void OnViewCircprops(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnHelpLicense(); + afx_msg void OnViewInfo(); + afx_msg void OnViewShowblocknames(); + afx_msg void OnVplot(); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); +}; + +#ifndef _DEBUG // debug version in cviewView.cpp +inline CcviewDoc* CcviewView::GetDocument() + { return (CcviewDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + + diff --git a/femm/fe_libdlg.cpp b/femm/fe_libdlg.cpp new file mode 100644 index 0000000..250bee4 --- /dev/null +++ b/femm/fe_libdlg.cpp @@ -0,0 +1,1349 @@ +// treetestDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "FemmeDoc.h" +#include "MatDlg.h" +#include "fe_libdlg.h" +#include "libfolderinfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// fe_CLibDlg dialog + + +// CLuaConsoleDlg dialog + +fe_CLibDlg::fe_CLibDlg(CWnd* pParent /*=NULL*/) + : CResizableDialog(fe_CLibDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(fe_CLibDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + // m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void fe_CLibDlg::DoDataExchange(CDataExchange* pDX) +{ + CResizableDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(fe_CLibDlg) + DDX_Control(pDX, IDC_MYLIST, m_mylist); + DDX_Control(pDX, IDC_MYTREE, m_mytree); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(fe_CLibDlg, CResizableDialog) + //{{AFX_MSG_MAP(fe_CLibDlg) + ON_WM_QUERYDRAGICON() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYTREE, OnBegindragMytree) + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYLIST, OnBegindragMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYLIST, OnRclickMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYTREE, OnRclickMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYTREE, OnDblclkMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYLIST, OnDblclkMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYLIST, OnKeydownMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYTREE, OnKeydownMytree) + ON_WM_TIMER() + //}}AFX_MSG_MAP + ON_COMMAND(ID_EDIT_CUT, Zappit) + ON_COMMAND(ID_EDIT_COPY, AddNewProperty) + ON_COMMAND(ID_EDIT_PASTE, AddNewFolder) + ON_COMMAND(ID_EDIT_REPLACE, MouseModify) + ON_COMMAND(ID_EDIT_PASTE_LINK, VendorLink) + ON_COMMAND(ID_EDIT_FIND, ImportMaterials) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// fe_CLibDlg message handlers + +BOOL fe_CLibDlg::OnInitDialog() +{ + CResizableDialog::OnInitDialog(); + + // TODO: Add extra initialization here + ////////////////////////////////////////////////////////////////// + + // preset layout + AddAnchor(IDOK,BOTTOM_RIGHT); + AddAnchor(IDCANCEL,BOTTOM_RIGHT); + AddAnchor(IDC_MYTREE,TOP_LEFT,BOTTOM_CENTER); + AddAnchor(IDC_MYLIST,TOP_CENTER,BOTTOM_RIGHT); + + CString LibName=BinDir+"matlib.dat"; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int i,k; + + Ancestors.RemoveAll(); + Parent=NULL; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + + // set up materials library tree control + m_bIsDragging = FALSE; + m_dragTargetTree = NULL; + m_dragTargetList = NULL; + m_dragItem = NULL; + m_imageList.Create( IDB_TREE, 16, 1, RGB(255,0,0) ); + m_mytree.SetImageList( &m_imageList, TVSIL_NORMAL ); + m_mylist.SetImageList( &m_imageList, TVSIL_NORMAL ); + + LibParent = m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Library Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + Parent=LibParent; + ModelParent = m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Model Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + + // Put Model's properties into the InModel edit box; + LibProps.RemoveAll(); + HTREEITEM hResult; + CArray &blockproplist=pDoc->blockproplist; + for(i=0;i=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + break; + + default: + + break; + } + } + + MProp.BHpoints=0; + + fclose(fp); + +/* + // tutorial example + HTREEITEM hChapter; + hChapter = m_mytree.InsertItem( "Chapter 1", 0, 1 ); + m_mytree.InsertItem( "What", 2, 2, hChapter ); +*/ + + Focus=NULL; + + return TRUE; // return TRUE unless you set the focus to a control +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR fe_CLibDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + + + + + +/////////////////////////////////////////////////// +// Implementation of library-specific file I/O +/////////////////////////////////////////////////// + +char* fe_CLibDlg::StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderName=v; + m_mytree.SetItemText(Parent,v); + 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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderURL=v; + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderVendor=v; + 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.NStrands=0; + MProp.WireD=0; + MProp.LamFill=1.; // lamination fill factor; + MProp.LamType=0; // type of lamination; + MProp.BHpoints=0; + MProp.BHdata=NULL; + + q[0]=NULL; + } + + // Library Hierarchy + if( _strnicmp(q,"",11)==0){ + + q[0]=NULL; + return 3; + } + + 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); + 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){ + q[0]=NULL; + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////// +// Drag-n-Drop Implementation + +void fe_CLibDlg::OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=LibParent) // can't drag top-level folder + { + CImageList* pDragImage; + pDragImage = m_mytree.CreateDragImage( m_dragItem ); + m_mytree.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + SetTimer ( 1, 75, NULL ) ; + bDragFromLibrary=TRUE; + } + + *pResult = 0; + +} + +void fe_CLibDlg::OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=ModelParent) + { + CImageList* pDragImage; + pDragImage = m_mylist.CreateDragImage( m_dragItem ); + m_mylist.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + bDragFromLibrary=FALSE; + SetTimer ( 1, 75, NULL ) ; + } + + *pResult = 0; +} + +void fe_CLibDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + CPoint ptDrag( point ); + CPoint ptTree( point ); + CPoint ptList( point ); + UINT uHitTest = TVHT_ONITEM; + + MapWindowPoints( this, &ptDrag, 1 ); + MapWindowPoints( &m_mytree, &ptTree, 1 ); + MapWindowPoints( &m_mylist, &ptList, 1 ); + + CImageList::DragMove( ptDrag ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + } + + CResizableDialog::OnMouseMove(nFlags, point); +} + +void fe_CLibDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + KillTimer ( 1 ) ; + CImageList::DragLeave( &m_mytree ); + CImageList::EndDrag(); + ReleaseCapture(); + m_bIsDragging = FALSE; + + // Do some logic to drop onto the main tree if the property is + // dropped onto the tree's window, but not exactly on the list + if((m_dragTargetTree==NULL) && (m_dragTargetList==NULL)) + { + POINT point; + GetCursorPos(&point); + void* pVoid = (void*)GetDesktopWindow()->WindowFromPoint(point); + if((void *) &m_mytree==pVoid) m_dragTargetTree=LibParent; + if((void *) &m_mylist==pVoid) m_dragTargetList=ModelParent; + } + + // Drop onto the Library tree + if( m_dragTargetTree != NULL ) + { + if(!IsTailChasing(m_dragItem,m_dragTargetTree)) + { + CopyItemToLibrary(m_dragItem,m_dragTargetTree); + if(bDragFromLibrary){ + m_mytree.DeleteItem( m_dragItem ); + } + } + } + + // Drop onto the model materials + if( m_dragTargetList != NULL ) + { + CopyItemToModel(m_dragItem,m_dragTargetList); + if(!bDragFromLibrary) m_mylist.DeleteItem( m_dragItem ); + } + } + else CResizableDialog::OnLButtonUp(nFlags, point); +} + +BOOL fe_CLibDlg::IsFolder(HTREEITEM hItem) +{ + int nImage1, nImage2, nSelImage; + m_mytree.GetItemImage(hItem,nImage1,nSelImage); + m_mylist.GetItemImage(hItem,nImage2,nSelImage); + if ((nImage1!=2) && (nImage2!=2)) return TRUE; + return FALSE; +} + +HTREEITEM fe_CLibDlg::CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(IsFolder(hTarget)) + { + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hTarget, TVI_LAST ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + MProp.BHdata=NULL;MProp.BHpoints=NULL; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + CopyBHdata(LibProps[ItemData],LibProps[NewItemData]); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hTarget, TVI_LAST); + m_mytree.SetItemData(hResult,ItemData); + } + } + else + { + hParent = m_mytree.GetParentItem(hTarget); + + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + MProp.BHdata=NULL;MProp.BHpoints=NULL; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + CopyBHdata(LibProps[ItemData],LibProps[NewItemData]); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + } + } + + + return hResult; +} + +HTREEITEM fe_CLibDlg::CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + if (IsFolder(hItem)) + { + hChild=m_mytree.GetChildItem(hItem) ; + hParent=hTarget; + while (hChild!=NULL) + { + hParent=CopyItemToModel(hChild,hParent) ; + hChild = m_mytree.GetNextSiblingItem(hChild); + } + hResult=hParent; + } + else{ + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + MProp.BHdata=NULL;MProp.BHpoints=NULL; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + CopyBHdata(LibProps[ItemData],LibProps[NewItemData]); + ItemData=NewItemData; + } + + hParent = m_mylist.GetParentItem( hTarget ); + if( hParent != NULL ) + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, hTarget); + else + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, TVI_LAST ); + m_mylist.SetItemData(hResult,ItemData); + } + + return hResult; +} + +void fe_CLibDlg::AddNewProperty() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetList!=NULL) + { + hParent = m_mylist.GetParentItem(m_dragTargetList); + if( hParent != NULL ) + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, m_dragTargetList); + else + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mylist.SetItemData(hResult,LibProps.GetUpperBound()); + } + + if(m_dragTargetTree!=NULL) + { + if(IsFolder(m_dragTargetTree)) hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Material", 2, 2, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Material", 2, 2, LibParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mytree.SetItemData(hResult,LibProps.GetUpperBound()); + } +} + +void fe_CLibDlg::AddNewFolder() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetTree!=NULL) + { + if (IsFolder(m_dragTargetTree)) + hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Folder", 0, 1, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Folder", 0, 1, LibParent, TVI_LAST ); + + CFolderProp FProp; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(hResult,FoldProps.GetUpperBound()); + } +} + +void fe_CLibDlg::Zappit() +{ + if ((m_dragTargetTree!=NULL) && (m_dragTargetTree!=LibParent)) + m_mytree.DeleteItem(m_dragTargetTree); + if ((m_dragTargetList!=NULL) && (m_dragTargetList!=ModelParent)) + m_mylist.DeleteItem(m_dragTargetList); +} + +void fe_CLibDlg::OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptTree(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptTree, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree==NULL) m_dragTargetTree=LibParent; + + VERIFY(pMenu->CreatePopupMenu()); + if(m_dragTargetTree!=LibParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Add New Folder")); + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)) + { + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + HTREEITEM hParent=m_mytree.GetParentItem(m_dragTargetTree); + if(hParent!=LibParent) + { + int k=(int) m_mytree.GetItemData(hParent); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + else if(m_dragTargetTree!=LibParent){ + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Edit Folder Info")); + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("fe_CLibDlg::OnRclickMytree failed to destroy menu resource\n"); + pMenu = FALSE; + } + + + *pResult = 0; +} + +void fe_CLibDlg::OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList==NULL) m_dragTargetList=ModelParent; + + VERIFY(pMenu->CreatePopupMenu()); + if (m_dragTargetList!=ModelParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("fe_CLibDlg::OnRclickMylist failed to destroy menu resource\n"); + pMenu = FALSE; + } + + *pResult = 0; +} + +void fe_CLibDlg::CopyBHdata(CMaterialProp &source, CMaterialProp &dest) +{ + // copy BH data from source to destination + dest.BHpoints=source.BHpoints; + if(source.BHpoints==0) return; + dest.BHdata=(CComplex *)calloc(source.BHpoints,sizeof(CComplex)); + for(int k=0;kMapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + + *pResult = 0; +} + +void fe_CLibDlg::OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptList, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptList, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + } + + *pResult = 0; +} + +void fe_CLibDlg::ModifyMaterial(int k) +{ + CMatDlg zDlg; + + zDlg.m_mu_x=LibProps[k].mu_x; + zDlg.m_mu_y=LibProps[k].mu_y; + zDlg.m_H_c=LibProps[k].H_c; + zDlg.m_Jsrc=LibProps[k].Jsrc; + zDlg.m_Cduct=LibProps[k].Cduct; + zDlg.m_Lam_d=LibProps[k].Lam_d; + zDlg.m_Theta_hn=LibProps[k].Theta_hn; + zDlg.m_Theta_hx=LibProps[k].Theta_hx; + zDlg.m_Theta_hy=LibProps[k].Theta_hy; + zDlg.m_WireD=LibProps[k].WireD; + zDlg.m_NStrands=LibProps[k].NStrands; + zDlg.m_BlockName=LibProps[k].BlockName; + zDlg.LamType=LibProps[k].LamType; + zDlg.m_lam_fill=LibProps[k].LamFill; +// for(int nn=0;nnProblemType==0){ + zDlg.m_mu1label="x"; + zDlg.m_mu2label="y"; + zDlg.m_h1label="hx"; + zDlg.m_h2label="hy"; + } + else{ + zDlg.m_mu1label="r"; + zDlg.m_mu2label="z"; + zDlg.m_h1label="hr"; + zDlg.m_h2label="hz"; + } + if(zDlg.DoModal()==IDOK){ + LibProps[k].BlockName=zDlg.m_BlockName; + LibProps[k].mu_x=zDlg.m_mu_x; + LibProps[k].mu_y=zDlg.m_mu_y; + LibProps[k].H_c=zDlg.m_H_c; + LibProps[k].Jsrc=zDlg.m_Jsrc; + LibProps[k].Cduct=zDlg.m_Cduct; + LibProps[k].Lam_d=zDlg.m_Lam_d; + LibProps[k].Theta_hn=zDlg.m_Theta_hn; + LibProps[k].Theta_hx=zDlg.m_Theta_hx; + LibProps[k].Theta_hy=zDlg.m_Theta_hy; + LibProps[k].NStrands=zDlg.m_NStrands; + LibProps[k].WireD=zDlg.m_WireD; + LibProps[k].LamType=zDlg.LamType; + LibProps[k].LamFill=zDlg.m_lam_fill; + if (zDlg.m_nlflag==FALSE) + { + zDlg.BData.Empty(); + zDlg.HData.Empty(); + } + LibProps[k].StripBHData(zDlg.BData,zDlg.HData); + } +} + +void fe_CLibDlg::MouseModify() +{ + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + else{ + CLibFolderInfo dlg; + + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + dlg.m_foldername =FoldProps[k].FolderName; + dlg.m_folderurl =FoldProps[k].FolderURL; + dlg.m_foldervendor=FoldProps[k].FolderVendor; + if (dlg.DoModal()==IDOK) + { + m_mytree.SetItemText(m_dragTargetTree,dlg.m_foldername); + FoldProps[k].FolderName =dlg.m_foldername; + FoldProps[k].FolderURL =dlg.m_folderurl; + FoldProps[k].FolderVendor=dlg.m_foldervendor; + } + } + } +} + +void fe_CLibDlg::OnOK() +{ + HTREEITEM hChild; + CArray &blockproplist=pDoc->blockproplist; + int k; + + // copy Model Materials into the model + blockproplist.RemoveAll(); + hChild=m_mylist.GetChildItem(ModelParent); + while (hChild!=NULL) + { + k=(int) m_mylist.GetItemData(hChild); + blockproplist.Add(LibProps[k]); + CopyBHdata(LibProps[k],blockproplist[blockproplist.GetUpperBound()]); + hChild = m_mylist.GetNextSiblingItem(hChild) ; + } + + // write Library Materials to disk + + CString LibName=BinDir+"matlib.dat"; + FILE *fp; + + if ((fp=fopen(LibName,"wt"))==NULL) return; + + hChild=m_mytree.GetChildItem(LibParent); + while(hChild!=NULL) + { + CopyItemToDisk(hChild,fp); + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fclose(fp); + + + CResizableDialog::OnOK(); +} + +void fe_CLibDlg::CopyItemToDisk(HTREEITEM hItem, FILE *fp) +{ + HTREEITEM hChild; + int i =(int) m_mytree.GetItemData(hItem); + + if (IsFolder(hItem)) + { + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderName); + if(FoldProps[i].FolderURL!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderURL); + if(FoldProps[i].FolderVendor!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderVendor); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToDisk(hChild,fp) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fprintf(fp,"\n"); + } + else{ + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) LibProps[i].BlockName); + fprintf(fp," = %.17g\n",LibProps[i].mu_x); + fprintf(fp," = %.17g\n",LibProps[i].mu_y); + fprintf(fp," = %.17g\n",LibProps[i].H_c); + fprintf(fp," = %.17g\n",LibProps[i].Theta_m); + fprintf(fp," = %.17g\n",LibProps[i].Jsrc.re); + fprintf(fp," = %.17g\n",LibProps[i].Jsrc.im); + fprintf(fp," = %.17g\n",LibProps[i].Cduct); + fprintf(fp," = %.17g\n",LibProps[i].Lam_d); + fprintf(fp," = %.17g\n",LibProps[i].Theta_hn); + fprintf(fp," = %.17g\n",LibProps[i].Theta_hx); + fprintf(fp," = %.17g\n",LibProps[i].Theta_hy); + fprintf(fp," = %i\n",LibProps[i].LamType); + fprintf(fp," = %.17g\n",LibProps[i].LamFill); + fprintf(fp," = %i\n",LibProps[i].NStrands); + fprintf(fp," = %.17g\n",LibProps[i].WireD); + fprintf(fp," = %i\n",LibProps[i].BHpoints); + for(int j=0;j\n\n"); + } +} + +void fe_CLibDlg::VendorLink() +{ + if (VendorURL!="") + ShellExecute(m_hWnd,"open",VendorURL,"","",SW_SHOWMAXIMIZED); + else + MsgBox("No URL available for %s",VendorName); +} + +void fe_CLibDlg::ImportMaterials() +{ + CFileDialog *fname_dia; + CString SourceFile; + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Magnetostatic Input File (*.fem) | *.fem; *.FEM | All Files (*.*) | *.*||", + NULL); + + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + + SourceFile=fname_dia->GetPathName(); + delete[] fname_dia; + + // Add selected properties to the library; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int k; + BOOL bToLibrary=TRUE; + + if ((fp=fopen(SourceFile,"rt"))==NULL) return; + + Ancestors.RemoveAll(); + if(m_dragTargetTree!=NULL){ + // importing into the library + // put the imported materials in a new folder + Parent=m_mytree.InsertItem("Imported Materials", 0, 1, LibParent, TVI_FIRST ); + FProp.FolderName="Imported Materials"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(Parent,FoldProps.GetUpperBound()); + } + else if(m_dragTargetList!=NULL){ + Parent=ModelParent; + bToLibrary=FALSE; + } + else return; + + while (fgets(s,1024,fp)!=NULL) + { + switch(ParseLine(s,fp,MProp)) + { + case 1: + + // add a material to library + k=(int) LibProps.GetSize(); + LibProps.Add(MProp); + if(bToLibrary) + m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + else + m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + MProp.BHpoints=0; + + break; + + case 2: + if (bToLibrary) + { + // open a new folder + if (Parent!=NULL) Ancestors.Add(Parent); + k=(int) FoldProps.GetSize(); + FoldProps.Add(FProp); + Parent=m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + FProp.FolderName,0,1,NULL,NULL,k,Parent,NULL); + } + + break; + + case 3: + if (bToLibrary) + { + // close a folder + k=(int) Ancestors.GetUpperBound(); + if (k>=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + } + break; + + default: + + break; + } + } + + MProp.BHpoints=0; + + fclose(fp); +} + +BOOL fe_CLibDlg::IsTailChasing(HTREEITEM hSource, HTREEITEM hDest) +{ + HTREEITEM hItem; + + hItem=hDest; + while(hItem!=NULL) + { + if(hSource==hItem) return TRUE; + hItem=m_mytree.GetParentItem(hItem); + } + + return FALSE; +} + +void fe_CLibDlg::OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mylist.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=ModelParent)) + m_mylist.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetList=m_mylist.GetSelectedItem(); + m_dragTargetTree=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + +void fe_CLibDlg::OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mytree.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=LibParent)) + m_mytree.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetTree=m_mytree.GetSelectedItem(); + m_dragTargetList=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + + +void fe_CLibDlg::OnTimer(UINT_PTR nIDEvent) +{ + POINT pt ; + GetCursorPos ( &pt ) ; + RECT rect ; + + + // check if Library needs to be scrolled and do it; + m_mytree.GetClientRect ( &rect ) ; + m_mytree.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mytree.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + // check if Model Materials needs to be scrolled and do it; + m_mylist.GetClientRect ( &rect ) ; + m_mylist.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mylist.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + CResizableDialog::OnTimer(nIDEvent); +} + + + + + diff --git a/femm/fe_libdlg.h b/femm/fe_libdlg.h new file mode 100644 index 0000000..9225afc --- /dev/null +++ b/femm/fe_libdlg.h @@ -0,0 +1,106 @@ +#pragma once + +#include "ResizableDialog.h" + +// treetestDlg.h : header file +// + +#if !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) +#define AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// fe_CLibDlg dialog + +class fe_CLibDlg : public CResizableDialog +{ +// Construction +public: + fe_CLibDlg(CWnd* pParent = NULL); // standard constructor + + CFemmeDoc *pDoc; + CArray LibProps; + CArray FoldProps; + CArray Ancestors; + HTREEITEM Parent; + HTREEITEM ModelParent; + HTREEITEM LibParent; + BOOL bDragFromLibrary; + CString BinDir; + CString VendorURL; + CString VendorName; + int Focus; + + int ParseLine(char *s, FILE *fp, CMaterialProp &MProp); + char* StripKey(char *c); + BOOL IsFolder(HTREEITEM hItem); + HTREEITEM CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget); + HTREEITEM CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget); + void CopyItemToDisk(HTREEITEM hItem, FILE *fp); + void VendorLink(); + void Zappit(); + void MouseModify(); + void AddNewProperty(); + void AddNewFolder(); + void ImportMaterials(); + void CopyBHdata(CMaterialProp &source, CMaterialProp &dest); + void ModifyMaterial(int k); + BOOL IsTailChasing(HTREEITEM hSource, HTREEITEM hDest); + +// Dialog Data + //{{AFX_DATA(fe_CLibDlg) + enum { IDD = IDD_TREETEST_DIALOG }; + CTreeCtrl m_mylist; + CTreeCtrl m_mytree; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(fe_CLibDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + HICON m_hIcon; + + // stuff needed to do CTreeCtrl properly + CImageList m_imageList; + BOOL m_bIsDragging; + HTREEITEM m_dragItem; + HTREEITEM m_dragTargetTree; + HTREEITEM m_dragTargetList; + + // Generated message map functions + //{{AFX_MSG(fe_CLibDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTimer(UINT_PTR nIDEvent); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) + + + + + diff --git a/femm/femm.cpp b/femm/femm.cpp new file mode 100644 index 0000000..d0c7ec3 --- /dev/null +++ b/femm/femm.cpp @@ -0,0 +1,1419 @@ + // femm.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "femm.h" +#include "FemmeDoc.h" +#include "FemmeView.h" +#include "xyplot.h" +#include "problem.h" +#include "FemmviewDoc.h" +#include "FemmviewView.h" +#include "hdrawDoc.h" +#include "hdrawView.h" +#include "hv_problem.h" +#include "hviewDoc.h" +#include "hviewView.h" + +#include "cdrawDoc.h" +#include "cdrawView.h" +#include "cv_problem.h" +#include "cviewDoc.h" +#include "cviewView.h" + +#include "beladrawDoc.h" +#include "beladrawView.h" +#include "bv_problem.h" +#include "belaviewDoc.h" +#include "belaviewView.h" +#include "femmplotDoc.h" +#include "femmplotView.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "promptbox.h" +#include "lua.h" +#include "MyCommandLineInfo.h" +#include "NewDocDlg.h" +#include +#include +#include +#include "MyRecentFileList.h" + +#ifdef MATHLINK +#include "mathlink.h" +#endif + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + + +extern void *pFemmeDoc; +extern void *pFemmviewdoc; +extern void *pBeladrawDoc; +extern void *pBelaviewDoc; +extern void *phdrawDoc; +extern void *phviewDoc; +extern void *pcdrawDoc; +extern void *pcviewDoc; + +extern CLuaConsoleDlg *LuaConsole; + +extern lua_State *lua; +extern BOOL bLinehook; +extern BOOL lua_byebye; +extern HANDLE hProc; +extern int m_luaWindowStatus; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmApp + +BEGIN_MESSAGE_MAP(CFemmApp, CWinApp) + //{{AFX_MSG_MAP(CFemmApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + ON_COMMAND(ID_FILE_OPEN_LUA_SCRIPT, OnFileOpenLuaScript) + ON_COMMAND(ID_FILE_NEW, OnFileNew) + ON_COMMAND(ID_FILE_OPEN, OnFileOpen) + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmApp construction + +CFemmApp::CFemmApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance + + // defaults + d_luaconsole=FALSE; + d_sepplot=FALSE; + d_defdoc=0; + d_SmartMesh=TRUE; + session_SmartMesh=-1; + d_bShowOutputWindow=TRUE; + bFileLink=FALSE; + bActiveX=FALSE; + IFile=GetExecutablePath()+"ifile.txt"; + OFile=GetExecutablePath()+"ofile.txt"; + luaShowWindow=NULL; + CompatibilityMode=0; +#ifdef MATHLINK + bMathLink=FALSE; +#endif + + + ScanPrefs(); +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CFemmApp object + +CFemmApp theApp; + +// lua globals +lua_State *lua; // the main lua object +BOOL bLinehook; +BOOL lua_byebye; +CString luafiles[20]; +CLuaConsoleDlg *LuaConsole=NULL; +int luafilepointer; // both used during the CMyCommandLineInfo parsing +CFemmApp *pApp; +HANDLE hProc; +int m_luaWindowStatus=SW_SHOW; +CString luascriptname; + +void *pFemmeDoc=NULL; // pointer to the Femme document currently in use +void *pFemmviewdoc=NULL; // pointer to the Femmview document currently in use +void *pBeladrawDoc=NULL; // pointer to the Beladraw document currently in use +void *pBelaviewDoc=NULL; // pointer to the Belaview document currently in use +void *phdrawDoc=NULL; // pointer to the hdraw document currently in use +void *phviewDoc=NULL; // pointer to the hview document currently in use +void *pcdrawDoc=NULL; +void *pcviewDoc=NULL; + +#ifdef MATHLINK +// Mathlink; +MLINK alink; +MLENV mathenv; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmApp initialization + +BOOL CFemmApp::InitInstance() +{ + // Initialize OLE libraries + if (!AfxOleInit()) + { + MsgBox("OLE initialization failed. Make sure that the OLE libraries are the correct version."); + return FALSE; + } + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Gedanken Magnetics\\FEMM\\4")); + + LoadStdProfileSettings(8); // Load standard INI file options (including MRU) + + // Parse the command line to see if launched as OLE server + if (RunEmbedded() || RunAutomated()) + { + // Register all OLE server (factories) as running. This enables the + // OLE libraries to create objects from other applications. + COleTemplateServer::RegisterAll(); + m_luaWindowStatus=SW_SHOWMINNOACTIVE; + } + else + { + // When a server application is launched stand-alone, it is a good idea + // to update the system registry in case it has been damaged. + COleObjectFactory::UpdateRegistryAll(); + } + + //04EF434A-1A91-495A-85AA-C625602B4AF4 + const IID LIBID_ActiveFEMM = { 0x04EF434A, 0x1A91, 0x495A, { 0x85, 0xAA, 0xC6, 0x25, 0x60, 0x2B, 0x4A, 0xF4 } }; + +// if(AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_ActiveFEMM, _T("femm.TLB"))==FALSE) MsgBox("TypeLib not registered!"); + AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_ActiveFEMM, _T("femm.TLB"),NULL); + + // Initialize Lua + bLinehook=FALSE; + lua=lua_open(4096); + lua_baselibopen(lua); + lua_strlibopen(lua); + lua_mathlibopen(lua); + lua_iolibopen(lua); + // register some common Lua functionality + lua_register(lua,"_ALERT",lua_ERROR); + lua_register(lua,"messagebox",lua_messagebox); + lua_register(lua,"pause",lua_afxpause); + lua_register(lua,"prompt",lua_promptbox); + lua_register(lua,"open",luaOpenDocument); + lua_register(lua,"quit",lua_endapp); + lua_register(lua,"exit",lua_endapp); + + lua_register(lua,"create",lua_newdocument); + lua_register(lua,"Complex",lua_Complex); + lua_register(lua,"newdocument",lua_newdocument); + lua_register(lua,"new_document",lua_newdocument); + + lua_register(lua,"showpointprops" ,lua_showpointprops); + lua_register(lua,"hidepointprops" ,lua_hidepointprops); + lua_register(lua,"show_point_props",lua_showpointprops); + lua_register(lua,"hide_point_props",lua_hidepointprops); + +#ifdef MATHLINK + lua_register(lua,"mlput",lua_to_mathematica); + lua_register(lua,"mlopen",lua_open_mathlink); + lua_register(lua,"mlclose",lua_close_mathlink); +#endif + + lua_register(lua,"flput",lua_to_filelink); + lua_register(lua,"setcompatibilitymode",lua_compatibilitymode); + lua_register(lua,"setcurrentdirectory",lua_setcurrentdirectory); + lua_register(lua,"chdir",lua_setcurrentdirectory); + lua_register(lua,"smartmesh",lua_smartmesh); + lua_register(lua,"makeplot",lua_makeplot); + lua_setlinehook(lua,line_hook); + + pApp=this; + NumViews=0; + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CMultiDocTemplate* pFemmeDocTemplate; + pFemmeDocTemplate = new CMultiDocTemplate( + IDR_FEMMETYPE, + RUNTIME_CLASS(CFemmeDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CFemmeView)); + AddDocTemplate(pFemmeDocTemplate); + + CMultiDocTemplate* pbeladrawDocTemplate; + pbeladrawDocTemplate = new CMultiDocTemplate( + IDR_BELADRAWTYPE, + RUNTIME_CLASS(CbeladrawDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CbeladrawView)); + AddDocTemplate(pbeladrawDocTemplate); + + CMultiDocTemplate* phdrawDocTemplate; + phdrawDocTemplate = new CMultiDocTemplate( + IDR_HDRAWTYPE, + RUNTIME_CLASS(ChdrawDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(ChdrawView)); + AddDocTemplate(phdrawDocTemplate); + + CMultiDocTemplate* pcdrawDocTemplate; + pcdrawDocTemplate = new CMultiDocTemplate( + IDR_CDRAWTYPE, + RUNTIME_CLASS(CcdrawDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CcdrawView)); + AddDocTemplate(pcdrawDocTemplate); + + CMultiDocTemplate* pFemmviewDocTemplate; + pFemmviewDocTemplate = new CMultiDocTemplate( + IDR_FEMMVIEWTYPE, + RUNTIME_CLASS(CFemmviewDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CFemmviewView)); + AddDocTemplate(pFemmviewDocTemplate); + + CMultiDocTemplate* pBelaviewDocTemplate; + pBelaviewDocTemplate = new CMultiDocTemplate( + IDR_BELAVIEWTYPE, + RUNTIME_CLASS(CbelaviewDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CbelaviewView)); + AddDocTemplate(pBelaviewDocTemplate); + + CMultiDocTemplate* phviewDocTemplate; + phviewDocTemplate = new CMultiDocTemplate( + IDR_HVIEWTYPE, + RUNTIME_CLASS(ChviewDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(ChviewView)); + AddDocTemplate(phviewDocTemplate); + + CMultiDocTemplate* pcviewDocTemplate; + pcviewDocTemplate = new CMultiDocTemplate( + IDR_CVIEWTYPE, + RUNTIME_CLASS(CcviewDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CcviewView)); + AddDocTemplate(pcviewDocTemplate); + + CMultiDocTemplate* pFemmplotDocTemplate; + pFemmplotDocTemplate = new CMultiDocTemplate( + IDR_FEMMPLOTTYPE, + RUNTIME_CLASS(CFemmplotDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CFemmplotView)); + AddDocTemplate(pFemmplotDocTemplate); + + // create main MDI Frame window + CMainFrame* pMainFrame = new CMainFrame; + + if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) + return FALSE; + m_pMainWnd = pMainFrame; + + // Enable drag/drop open + m_pMainWnd->DragAcceptFiles(); + + // Enable DDE Execute open + EnableShellOpen(); + RegisterShellFileTypes(TRUE); + +#ifdef MATHLINK + if (__argc>1) + if(strcmp("-mathlink",__argv[1])==0) bMathLink=TRUE; + + if(!bMathLink) +#endif + { + // Parse command line for standard shell commands, DDE, file open + CMyCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // don't display annoying "new document" dialog automatically + if(cmdInfo.m_nShellCommand==CCommandLineInfo::FileNew) + { + cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing; + + switch(d_defdoc) + { + case 1: + OnFileNew(); + break; + case 2: + CreateNewDocument(0); + break; + case 3: + CreateNewDocument(1); + break; + case 4: + CreateNewDocument(2); + break; + case 5: + CreateNewDocument(3); + break; + default: + break; + } + + // load up most recently used file if nothing else on tap + // if ((luascriptname.IsEmpty()) && (m_pRecentFileList->GetSize()>0)) + // m_pMainWnd->PostMessage(WM_COMMAND, ID_FILE_MRU_FILE1); + } + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) return FALSE; + } + + // lua extension: if we are running in quiet mode, hide window + this->m_nCmdShow=m_luaWindowStatus; + + // The main window has been initialized, so show and update it. + pMainFrame->ShowWindow(m_nCmdShow); + pMainFrame->UpdateWindow(); + +#ifdef MATHLINK + // If -mathlink has been specified on the command line, open the link; + if (bMathLink) + { + mathenv = MLInitialize(0); + alink = MLOpen(__argc,__argv); + if(alink==NULL){ + MsgBox("problem opening a MathLink link\n"); + bMathLink=FALSE; + } + else MLActivate(alink); + } +#endif + + // !!! + // Load up an external lua script that does canned initialization. + // Users can modify this file to get their own custom initialization functionality. + CString initlua=GetExecutablePath()+"init.lua"; + FILE *fp; + if ( (fp=fopen(initlua,"rt")) != NULL) + { + fclose(fp); + if (int lua_error_code=lua_dofile(lua,initlua)!=0) + { + if (lua_error_code==LUA_ERRRUN) + AfxMessageBox("Run Error in init.lua"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error in init.lua"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error in init.lua"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error in init.lua"); + } + } + + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + CString m_compiledate; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + m_compiledate = __DATE__; +// m_compiledate = "11Apr2012"; + //}}AFX_DATA_INIT +#ifdef MATHLINK +#ifdef _DEBUG + m_compiledate += " (Mathematica Debug)"; +#else + m_compiledate += " (Mathematica Build)"; +#endif +#endif + +#ifdef _WIN64 + m_compiledate += " (x64)"; +#endif + +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + DDX_Text(pDX, IDC_COMPILEDATE, m_compiledate); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CFemmApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmApp message handlers + + +int CFemmApp::ExitInstance() +{ + lua_close(lua); + +#ifdef MATHLINK + if(bMathLink){ + MLClose(alink); + MLDeinitialize(mathenv); + bMathLink=FALSE; + } +#endif + + return CWinApp::ExitInstance(); +} + +void CFemmApp::OnFileOpenLuaScript() +{ + static char BASED_CODE szFilter[] = "Lua Script Files (*.lua)|*.lua|"; + char ext[]=".lua"; + CFileDialog MyDlg(TRUE,ext,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter); + if(MyDlg.DoModal()==IDOK){ + luascriptname=MyDlg.GetPathName(); + CString FolderPath=luascriptname.Left(MyDlg.m_ofn.nFileOffset); + SetCurrentDirectory(FolderPath); + } +} + +BOOL CFemmApp::OnIdle(LONG lCount) +{ + static time_t timestamp=0; + static char inbuff[4096]; + + // if a lua script was specified on the command line, run it. + // Invoking the lua script here, rather than in InitInstance, + // makes sure that everything is initialized correctly before + // the lua script starts to run. + if (luascriptname.GetLength()!=0){ + if(m_luaWindowStatus==SW_SHOW) bLinehook=NormalLua; + else bLinehook=HiddenLua; + CString doscript=luascriptname; + luascriptname.Empty(); + int lua_error_code; + lua_byebye=FALSE; + CStatusBar *StatBar=(CStatusBar *)((CMainFrame *)m_pMainWnd)->GetMessageBar(); + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + if (lua_error_code=lua_dofile(lua,doscript)!=0) + { +// if (lua_error_code==LUA_ERRRUN) +// AfxMessageBox("Run Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + } + StatBar->SetPaneText(0,"Ready",TRUE); + if(lua_byebye==TRUE){ + ASSERT(AfxGetMainWnd() != NULL); + AfxGetMainWnd()->PostMessage(WM_CLOSE); + } + bLinehook=FALSE; + } + +#ifdef MATHLINK + + // Sniff for any Mathlink message if Mathlink is connected + if (bMathLink) + { + MLFlush(alink); + if(MLReady(alink)) + { + char *mathstring; + CString luacmd; + if(MLGetString(alink,(const char **) &mathstring)) + { + luacmd=mathstring; + MLDisownString(alink,mathstring); + + if(m_luaWindowStatus==SW_SHOW) bLinehook=NormalLua; + else bLinehook=HiddenLua; + int lua_error_code; + lua_byebye=FALSE; + CStatusBar *StatBar=(CStatusBar *)((CMainFrame *)m_pMainWnd)->GetMessageBar(); +// StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + if (lua_error_code=lua_dostring(lua,luacmd)!=0) + { +// if (lua_error_code==LUA_ERRRUN) +// AfxMessageBox("Run Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + } +// StatBar->SetPaneText(0,"Ready",TRUE); + if(lua_byebye==TRUE){ + ASSERT(AfxGetMainWnd() != NULL); + AfxGetMainWnd()->PostMessage(WM_CLOSE); + } + bLinehook=FALSE; + + time(×tamp); + } + else{ + MsgBox("MathLink::Closing connection"); + MLClose(alink); + MLDeinitialize(mathenv); + bMathLink=FALSE; + } + } + + // have to return something other than zero + // so that the program will keep checking + // to see if there is a new mathlink message; + // A kludge is to call for a 1ms sleep. Otherwise, + // the program hogs all the CPU time checking for + // new messages, slowing down the entire system. + if (time(NULL)!=timestamp) Sleep(1); + CWinApp::OnIdle(0); + return TRUE; + } +#endif + + // Sniff for kludge IPC messages sent via temporary files + if (bFileLink) + { + FILE *fp; + char *s; + + if ( (fp=fopen(IFile,"rt")) != NULL) + { + s=fgets(inbuff,4096,fp); + fclose(fp); + + if((s!=NULL) && (strlen(inbuff)!=0)) + { + DeleteFile(IFile); + if(m_luaWindowStatus==SW_SHOW) bLinehook=NormalLua; + else bLinehook=HiddenLua; + int lua_error_code; + lua_byebye=FALSE; + CStatusBar *StatBar=(CStatusBar *)((CMainFrame *)m_pMainWnd)->GetMessageBar(); +// StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + if (lua_error_code=lua_dostring(lua,inbuff)!=0) + { +// if (lua_error_code==LUA_ERRRUN) +// AfxMessageBox("Run Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + } +// StatBar->SetPaneText(0,"Ready",TRUE); + if(lua_byebye==TRUE){ + ASSERT(AfxGetMainWnd() != NULL); + AfxGetMainWnd()->PostMessage(WM_CLOSE); + } + bLinehook=FALSE; + + time(×tamp); + } + } + + // have to return something other than zero + // so that the program will keep checking + // to see if there is a new mathlink message; + // A kludge is to call for a 1ms sleep. Otherwise, + // the program hogs all the CPU time checking for + // new messages, slowing down the entire system. + if(time(NULL)!=timestamp) Sleep(1); + CWinApp::OnIdle(0); + return TRUE; + } + + return CWinApp::OnIdle(lCount); +} + +void CFemmApp::line_hook(lua_State *L, lua_Debug *ar) +{ + MSG msg; + + while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) + { + bLinehook=FALSE; + + // If there is a running process (e.g. the solver), kill it + if (hProc!=NULL) TerminateProcess(hProc,NULL); + hProc=NULL; + + // bust out of script + lua_error(L,NULL); + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +int CFemmApp::lua_endapp(lua_State *L) +{ + lua_byebye=TRUE; + return 0; +} + + +int CFemmApp::luaOpenDocument(lua_State *L) +{ + CString temp; + + int n=lua_gettop(L); + if (n==0) return 0; + temp.Format("%s",lua_tostring(L,1)); + if (n>1){ + switch((int) lua_todouble(L,2)) + { + case 1: + theApp.luaShowWindow=SW_MINIMIZE; + break; + case 2: + theApp.luaShowWindow=SW_RESTORE; + break; + case 3: + theApp.luaShowWindow=SW_MAXIMIZE; + break; + default: + theApp.luaShowWindow=NULL; + } + } + theApp.OpenDocumentFile(temp); + return 0; +} + +int CFemmApp::lua_promptbox(lua_State *L) +{ + CPromptBox dlg; + + if(lua_gettop(L)>0) dlg.mytitle = lua_tostring(L,1); + dlg.DoModal(); + lua_pushstring(L,dlg.instring); + + return TRUE; +} + +int CFemmApp::lua_afxpause(lua_State * L) +{ + AfxMessageBox("LUA pause"); + + return 0; +} + +int CFemmApp::lua_messagebox(lua_State *L) +{ + + CString errmsg; + errmsg.Format("%s",lua_tostring(L,1)); + + AfxMessageBox(errmsg,MB_ICONINFORMATION); + + return 0; +} + +int CFemmApp::lua_ERROR(lua_State *L) +{ + + CString errmsg; + errmsg.Format("%s",lua_tostring(L,1)); + theApp.LuaErrmsg=errmsg; + + // Somthing went wrong in lua execution + // Windows dosn't have stdout so lets afxmessagebox it + if(theApp.bFileLink) + { + FILE* fp; + fp=fopen(theApp.OFile,"wt"); + if(fp!=NULL){ + errmsg.Replace("error:",""); + errmsg.Replace("\"","\\\""); + errmsg.Replace("\n","\\n"); + fprintf(fp,"error(\"FEMM returns:\\n%s\\n\")", (const char *) errmsg); + fclose(fp); + } + } + else if (!theApp.bActiveX) AfxMessageBox(errmsg); + + return 0; +} + +int CFemmApp::lua_newdocument(lua_State *L) +{ + if(lua_gettop(L)>0) theApp.CreateNewDocument((int) lua_todouble(L,1)); + return 0; +} + +void CFemmApp::CreateNewDocument(int n) +{ + // First, catch a special case where the new document + // is an XY plot and we want to open it in another window + // all together + if ((n==7) && (d_sepplot)) + { + char CommandLine[MAX_PATH]; + sprintf(CommandLine,"%sfemmplot.exe", (const char *) ((CFemmApp *)AfxGetApp())->GetExecutablePath()); + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,0, NULL, NULL, &StartupInfo2, &ProcessInfo2); + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + return; + } + + POSITION tpos; + CDocTemplate* pTemp; + int k=0; + + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(k=0;k<=n;k++) + if(tpos!=NULL) + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + if(pTemp!=NULL) pTemp->OpenDocumentFile(NULL); +} + +BOOL CFemmApp::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 CWinApp::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +CString CFemmApp::GetExecutablePath() +{ + char szPath[MAX_PATH]; + char szDrive[64]; + char szDir[MAX_PATH]; + + GetModuleFileName(NULL, szPath, MAX_PATH); + _splitpath(szPath, szDrive, szDir, NULL, NULL); + + return ((CString) szDrive) + szDir; +} + +int CFemmApp::HowManyDocs() +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + int k=0; + + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + while(tpos!=NULL) + { + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pTemp->GetNextDoc(dpos); + k++; + } + } + + return k; +} + +void CFemmApp::ForceViewPrefReload() +{ + // this is a kludge to get all of the views + // to reload their color mappings from disk. + + POSITION tpos,dpos,pos; + CDocTemplate* pTemp; + + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + + // femme + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CFemmeDoc *pDoc; + CFemmeView *pView; + pDoc = (CFemmeDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CFemmeView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // beladraw + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CbeladrawDoc *pDoc; + CbeladrawView *pView; + pDoc = (CbeladrawDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CbeladrawView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // hdraw + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + ChdrawDoc *pDoc; + ChdrawView *pView; + pDoc = (ChdrawDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(ChdrawView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // cdraw + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CcdrawDoc *pDoc; + CcdrawView *pView; + pDoc = (CcdrawDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CcdrawView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // femmview + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CFemmviewDoc *pDoc; + CFemmviewView *pView; + pDoc = (CFemmviewDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CFemmviewView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // belaview + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CbelaviewDoc *pDoc; + CbelaviewView *pView; + pDoc = (CbelaviewDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CbelaviewView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // hview + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + ChviewDoc *pDoc; + ChviewView *pView; + pDoc = (ChviewDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(ChviewView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // cview + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + CcviewDoc *pDoc; + CcviewView *pView; + pDoc = (CcviewDoc *)pTemp->GetNextDoc(dpos); + pos=pDoc->GetFirstViewPosition(); + pView=(CcviewView *)pDoc->GetNextView(pos); + pView->ScanPreferences(); + pDoc->ScanPreferences(); + pView->InvalidateRect(NULL); + } + + // general prefs + ScanPrefs(); + bShowOutputWindow=d_bShowOutputWindow; +} + +void CFemmApp::OnFileNew() +{ + CNewDocDlg dlg; + + if(dlg.DoModal()==IDOK) CreateNewDocument(dlg.doctype); +} + +char* StripKey(char *c); + +void CFemmApp::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "femm.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_luaconsole); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_sepplot); + q[0]=NULL; + } + + if( _strnicmp(q,"",18)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_bShowOutputWindow); + q[0]=NULL; + } + + if( _strnicmp(q,"",18)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_SmartMesh); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_defdoc); + q[0]=NULL; + } + } + fclose(fp); + } +} + +int CFemmApp::lua_showpointprops(lua_State *L) +{ + CMainFrame * pfrm; + pfrm=(CMainFrame *)AfxGetApp()->GetMainWnd(); + pfrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + + return 0; +} + + +int CFemmApp::lua_hidepointprops(lua_State *L) +{ + CMainFrame * pfrm; + pfrm=(CMainFrame *)AfxGetApp()->GetMainWnd(); + pfrm->m_dlgBar.ShowWindow(SW_HIDE); + + return 0; +} + +// override of LoadStdProfileSettings so that I can get +// the suffix in the MRU files list. + +AFX_STATIC_DATA const TCHAR _afxFileSection[] = _T("Recent File List"); +AFX_STATIC_DATA const TCHAR _afxFileEntry[] = _T("File%d"); +AFX_STATIC_DATA const TCHAR _afxPreviewSection[] = _T("Settings"); +AFX_STATIC_DATA const TCHAR _afxPreviewEntry[] = _T("PreviewPages"); + +void CFemmApp::LoadStdProfileSettings(UINT nMaxMRU) +{ + ASSERT_VALID(this); + ASSERT(m_pRecentFileList == NULL); + + if (nMaxMRU != 0) + { + // create file MRU since nMaxMRU not zero + // using MyCRecentFileList override + m_pRecentFileList = new MyCRecentFileList(0, _afxFileSection, _afxFileEntry, nMaxMRU); + m_pRecentFileList->ReadList(); + } + // 0 by default means not set + m_nNumPreviewPages = GetProfileInt(_afxPreviewSection, _afxPreviewEntry, 0); +} + +#ifdef MATHLINK + +int CFemmApp::lua_to_mathematica(lua_State *L) +{ + if (((CFemmApp *)AfxGetApp())->bMathLink==FALSE) return 0; + + int n = lua_gettop(L); + MLPutFunction(alink, "List", 1); + + for(int k=1;k<=n;k++) + { + MLPutFunction(alink, "Sequence", 2); + if(lua_type(L,k)==LUA_TNUMBER){ + CComplex z=lua_tonumber(L,k); + if (Im(z)==0) MLPutReal(alink,Re(z)); + else{ + MLPutFunction(alink, "Complex", 2); + MLPutReal(alink, Re(z)); + MLPutReal(alink, Im(z)); + } + } + else{ + CString s=lua_tostring(L,k); + MLPutString(alink,s); + } + } + MLPutFunction(alink, "Sequence", 0); + MLEndPacket(alink); + + return 0; +} + +int CFemmApp::lua_open_mathlink(lua_State *L) +{ + if (((CFemmApp *)AfxGetApp())->bMathLink==FALSE) + { + mathenv = MLInitialize(0); + alink = MLOpen(__argc,__argv); + if(alink==NULL) MsgBox("problem opening a MathLink link\n"); + else ((CFemmApp *)AfxGetApp())->bMathLink=TRUE; + } + + return 0; + +} + +int CFemmApp::lua_close_mathlink(lua_State *L) +{ + if (((CFemmApp *)AfxGetApp())->bMathLink==TRUE) + { + MLClose(alink); + MLDeinitialize(mathenv); + ((CFemmApp *)AfxGetApp())->bMathLink=FALSE; + } + + return 0; +} + +#endif + +BOOL CFemmApp::MOCheckIfAlreadyOpen(CString p) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CFemmviewDoc* pDoc; + CString DocTitle,ThisTitle,ThisTitleAlt; + + DocTitle=p; + DocTitle.MakeLower(); + + // get pointer to document template for FemmviewDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<5;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CFemmviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetPathName(); + ThisTitle.MakeLower(); + ThisTitleAlt="\"" + ThisTitle +"\""; + if((ThisTitle==DocTitle) || (ThisTitleAlt==DocTitle)) + { + lua_pushstring(lua,pDoc->GetTitle()); + pDoc->lua_switchfocus(lua); + pDoc->lua_reload((lua_State *) NULL); +// Alternate idea here is: +// pDoc->OnReload(); + return TRUE; + } + } + return FALSE; +} + +BOOL CFemmApp::EOCheckIfAlreadyOpen(CString p) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CbelaviewDoc* pDoc; + CString DocTitle,ThisTitle,ThisTitleAlt; + + DocTitle=p; + DocTitle.MakeLower(); + + // get pointer to document template for FemmviewDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<6;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CbelaviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetPathName(); + ThisTitle.MakeLower(); + ThisTitleAlt="\"" + ThisTitle +"\""; + if((ThisTitle==DocTitle) || (ThisTitleAlt==DocTitle)) + { + lua_pushstring(lua,pDoc->GetTitle()); + pDoc->lua_switchfocus(lua); + pDoc->lua_reload((lua_State *) NULL); +// Alternate idea here is: +// pDoc->OnReload(); + return TRUE; + } + } + return FALSE; +} + +BOOL CFemmApp::HOCheckIfAlreadyOpen(CString p) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + ChviewDoc* pDoc; + CString DocTitle,ThisTitle,ThisTitleAlt; + + DocTitle=p; + DocTitle.MakeLower(); + + // get pointer to document template for FemmviewDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<7;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(ChviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetPathName(); + ThisTitle.MakeLower(); + ThisTitleAlt="\"" + ThisTitle +"\""; + if((ThisTitle==DocTitle) || (ThisTitleAlt==DocTitle)) + { + lua_pushstring(lua,pDoc->GetTitle()); + pDoc->lua_switchfocus(lua); + pDoc->lua_reload((lua_State *) NULL); +// Alternate idea here is: +// pDoc->OnReload(); + return TRUE; + } + } + return FALSE; +} + +BOOL CFemmApp::COCheckIfAlreadyOpen(CString p) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CcviewDoc* pDoc; + CString DocTitle,ThisTitle,ThisTitleAlt; + + DocTitle=p; + DocTitle.MakeLower(); + + // get pointer to document template for FemmviewDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<8;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CcviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetPathName(); + ThisTitle.MakeLower(); + ThisTitleAlt="\"" + ThisTitle +"\""; + if((ThisTitle==DocTitle) || (ThisTitleAlt==DocTitle)) + { + lua_pushstring(lua,pDoc->GetTitle()); + pDoc->lua_switchfocus(lua); + pDoc->lua_reload((lua_State *) NULL); +// Alternate idea here is: +// pDoc->OnReload(); + return TRUE; + } + } + return FALSE; +} + +int CFemmApp::lua_to_filelink(lua_State *L) +{ + FILE *fp; + CString LuaResult,s; + + int n = lua_gettop(L); + + do{ + fp=fopen(((CFemmApp*) AfxGetApp())->OFile,"wt"); + } while(fp==NULL); + + if(n==0) LuaResult="[]\n"; + else{ + LuaResult="["; + for(int k=1;k<=n;k++) + { + s=lua_tostring(L,k); + if(k!=n) LuaResult = LuaResult + s + ","; + else LuaResult = LuaResult + s + "]\n"; + } + } + fprintf(fp,"%s", (const char *) LuaResult); + fclose(fp); + + return 0; +} + +void CFemmApp::OnFileOpen() +{ + CWinApp::OnFileOpen(); // Use just this line to recoup the default behavior; +} + +int CFemmApp::lua_compatibilitymode(lua_State *L) +{ + if (lua_gettop(L)!=0) ((CFemmApp*) AfxGetApp())->CompatibilityMode=(int) lua_todouble(L,1); + + return 0; +} + +int CFemmApp::lua_setcurrentdirectory(lua_State *L) +{ + if (lua_gettop(L)!=0) + { + CString temp; + temp.Format("%s",lua_tostring(L,1)); + SetCurrentDirectory(temp); + } + + return 0; +} + +int CFemmApp::lua_smartmesh(lua_State *L) +{ + // crowbar smartmesh off for entire program for the entire session + if (lua_gettop(L)!=0) ((CFemmApp*) AfxGetApp())->session_SmartMesh = (int)lua_todouble(L,1); + + return 0; +} + + +int CFemmApp::lua_Complex(lua_State *L) +{ + int n; + + CComplex y; + + n=lua_gettop(L); + if (n==2) + y=lua_tonumber(L,1)+I*lua_tonumber(L,2); + else if (n==1) + y=lua_tonumber(L,1); + else y=0; + + lua_pushnumber(L,y); + + return 1; +} + + +int CFemmApp::lua_makeplot(lua_State *L) +{ + CXYPlot xyplot; + int k; + int nTables=0; + int nStrings=0; + int n=lua_gettop(L); + + for(k=1;k<=n;k++) + { + if (lua_istable(L,k)){ + nTables++; + } + if (lua_isstring(L,k)){ + nStrings++; + } + } + + MsgBox("Tables = %i\nStrings = %i",nTables,nStrings); + + return 0; +} \ No newline at end of file diff --git a/femm/femm.h b/femm/femm.h new file mode 100644 index 0000000..0c51d37 --- /dev/null +++ b/femm/femm.h @@ -0,0 +1,110 @@ +// femm.h : main header file for the FEMM application +// + +#if !defined(AFX_FEMM_H__9E266B2B_F162_4533_8CBF_6ED85E61B8FA__INCLUDED_) +#define AFX_FEMM_H__9E266B2B_F162_4533_8CBF_6ED85E61B8FA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols +#include "lua.h" +#include "luadebug.h" + +///////////////////////////////////////////////////////////////////////////// +// CFemmApp: +// See femm.cpp for the implementation of this class +// + +class CFemmApp : public CWinApp +{ +public: + CFemmApp(); + + static int luaOpenDocument(lua_State *L); + static int lua_ERROR(lua_State *L); + static int lua_messagebox(lua_State *L); + static int lua_afxpause(lua_State *L); + static int lua_promptbox(lua_State *L); + static int lua_endapp(lua_State *L); + static int lua_newdocument(lua_State *L); + static int lua_Complex(lua_State *L); + static int lua_showpointprops(lua_State *L); + static int lua_hidepointprops(lua_State *L); + static void line_hook(lua_State *L, lua_Debug *ar); + BOOL MOCheckIfAlreadyOpen(CString p); + BOOL EOCheckIfAlreadyOpen(CString p); + BOOL HOCheckIfAlreadyOpen(CString p); + BOOL COCheckIfAlreadyOpen(CString p); + + int NumViews; + int luaShowWindow; + +#ifdef MATHLINK + static int lua_to_mathematica(lua_State *L); + static int lua_open_mathlink(lua_State *L); + static int lua_close_mathlink(lua_State *L); + BOOL bMathLink; +#endif + + static int lua_to_filelink(lua_State *L); + BOOL bFileLink; + BOOL bActiveX; + CString LuaErrmsg; + CString MatlabLoveNote; + + int CompatibilityMode; + static int CFemmApp::lua_compatibilitymode(lua_State *L); + static int CFemmApp::lua_setcurrentdirectory(lua_State *L); + static int CFemmApp::lua_smartmesh(lua_State *L); + static int CFemmApp::lua_makeplot(lua_State *L); + + CString CFemmApp::GetExecutablePath(); + int HowManyDocs(); + void CreateNewDocument(int n); + void ScanPrefs(); + void ForceViewPrefReload(); + + CString IFile,OFile; + + // general defaults + int d_luaconsole; + int d_sepplot; + int d_defdoc; + int d_SmartMesh; + int session_SmartMesh; + int d_bShowOutputWindow,bShowOutputWindow; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmApp) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + virtual BOOL OnIdle(LONG lCount); + virtual void LoadStdProfileSettings(UINT nMaxMRU); + //}}AFX_VIRTUAL + +// Implementation + //{{AFX_MSG(CFemmApp) + afx_msg void OnAppAbout(); + afx_msg void OnFileOpenLuaScript(); + afx_msg void OnFileNew(); + afx_msg void OnFileOpen(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FEMM_H__9E266B2B_F162_4533_8CBF_6ED85E61B8FA__INCLUDED_) diff --git a/femm/femmDoc.cpp b/femm/femmDoc.cpp new file mode 100644 index 0000000..9f1434e --- /dev/null +++ b/femm/femmDoc.cpp @@ -0,0 +1,84 @@ +// femmDoc.cpp : implementation of the CFemmDoc class +// + +#include "stdafx.h" +#include "femm.h" + +#include "femmDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmDoc + +IMPLEMENT_DYNCREATE(CFemmDoc, CDocument) + +BEGIN_MESSAGE_MAP(CFemmDoc, CDocument) + //{{AFX_MSG_MAP(CFemmDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmDoc construction/destruction + +CFemmDoc::CFemmDoc() +{ + // TODO: add one-time construction code here + +} + +CFemmDoc::~CFemmDoc() +{ +} + +BOOL CFemmDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CFemmDoc serialization + +void CFemmDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmDoc diagnostics + +#ifdef _DEBUG +void CFemmDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CFemmDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmDoc commands diff --git a/femm/femmDoc.h b/femm/femmDoc.h new file mode 100644 index 0000000..c8b99a5 --- /dev/null +++ b/femm/femmDoc.h @@ -0,0 +1,57 @@ +// femmDoc.h : interface of the CFemmDoc class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_FEMMDOC_H__8889277C_B515_4580_AEAA_E5095D7D94C9__INCLUDED_) +#define AFX_FEMMDOC_H__8889277C_B515_4580_AEAA_E5095D7D94C9__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class CFemmDoc : public CDocument +{ +protected: // create from serialization only + CFemmDoc(); + DECLARE_DYNCREATE(CFemmDoc) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmDoc) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FEMMDOC_H__8889277C_B515_4580_AEAA_E5095D7D94C9__INCLUDED_) diff --git a/femm/femmeLua.cpp b/femm/femmeLua.cpp new file mode 100644 index 0000000..d2dcd42 --- /dev/null +++ b/femm/femmeLua.cpp @@ -0,0 +1,3351 @@ +// femmeDoc.cpp : implementation of the CFemmeDoc class +// + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.h" +#include "femmeView.h" +#include "promptbox.h" +#include "MainFrm.h" +#include "ChildFrm.h" + +extern BOOL lua_byebye; +extern void *pFemmeDoc; +extern lua_State *lua; +extern BOOL bLinehook; +extern CLuaConsoleDlg *LuaConsole; +extern int m_luaWindowStatus; + +#define CatchNullDocument(); if (pFemmeDoc==NULL)\ + { CString msg="No current magnetics input in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//---------------------Lua Extensions------------------------ + +void CFemmeDoc::initalise_lua() +{ + // generalized lua functionality + // should put these in femm.cpp or something + + // register lua extensions + lua_register(lua,"mi_saveas",luaSaveDocument); + lua_register(lua,"mi_createmesh",lua_create_mesh); + lua_register(lua,"mi_smartmesh",lua_smartmesh); + lua_register(lua,"mi_showmesh",lua_show_mesh); + lua_register(lua,"mi_purgemesh",lua_purge_mesh); + lua_register(lua,"mi_probdef",lua_prob_def); + lua_register(lua,"mi_analyse",lua_analyze); + lua_register(lua,"mi_loadsolution",lua_runpost); + lua_register(lua,"mi_addnode",lua_addnode); + lua_register(lua,"mi_addblocklabel",lua_addlabel); + lua_register(lua,"mi_addsegment",lua_addline); + lua_register(lua,"mi_addarc",lua_addarc); + lua_register(lua,"mi_selectnode",lua_selectnode); + lua_register(lua,"mi_selectlabel",lua_selectlabel); + lua_register(lua,"mi_selectsegment",lua_selectsegment); + lua_register(lua,"mi_selectarcsegment",lua_selectarcsegment); + lua_register(lua,"mi_clearselected",lua_clearselected); + lua_register(lua,"mi_setnodeprop",lua_setnodeprop); + lua_register(lua,"mi_setblockprop",lua_setblockprop); + lua_register(lua,"mi_setsegmentprop",lua_setsegmentprop); + lua_register(lua,"mi_setarcsegmentprop",lua_setarcsegmentprop); + lua_register(lua,"mi_deleteselected",lua_deleteselected); + lua_register(lua,"mi_deleteselectednodes",lua_deleteselectednodes); + lua_register(lua,"mi_deleteselectedlabels",lua_deleteselectedlabels); + lua_register(lua,"mi_deleteselectedsegments",lua_deleteselectedsegments); + lua_register(lua,"mi_deleteselectedarcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"mi_zoomnatural",lua_zoomnatural); + lua_register(lua,"mi_zoomout",lua_zoomout); + lua_register(lua,"mi_zoomin",lua_zoomin); + lua_register(lua,"mi_zoom",lua_zoom); + lua_register(lua,"mi_addmaterial",lua_addmatprop); + lua_register(lua,"mi_addpointprop",lua_addpointprop); + lua_register(lua,"mi_addcircprop",lua_addcircuitprop); + lua_register(lua,"mi_addboundprop",lua_addboundprop); + lua_register(lua,"mi_modifymaterial",lua_modmatprop); + lua_register(lua,"mi_modifyboundprop",lua_modboundprop); + lua_register(lua,"mi_modifypointprop",lua_modpointprop); + lua_register(lua,"mi_modifycircprop",lua_modcircprop); + lua_register(lua,"mi_deletematerial",lua_delmatprop); + lua_register(lua,"mi_deleteboundprop",lua_delboundprop); + lua_register(lua,"mi_deletecircuit",lua_delcircuitprop); + lua_register(lua,"mi_deletepointprop",lua_delpointprop); + lua_register(lua,"mi_moverotate",lua_move_rotate); + lua_register(lua,"mi_movetranslate",lua_move_translate); + lua_register(lua,"mi_copyrotate",lua_copy_rotate); + lua_register(lua,"mi_copytranslate",lua_copy_translate); + lua_register(lua,"mi_mirror",lua_mirror); + lua_register(lua,"mi_scale",lua_scale); + lua_register(lua,"mi_seteditmode",lua_seteditmode); + lua_register(lua,"mi_selectgroup",lua_selectgroup); + lua_register(lua,"mi_newdocument",lua_newdocument); + lua_register(lua,"mi_savebitmap",lua_savebitmap); + lua_register(lua,"mi_savemetafile",lua_saveWMF); + lua_register(lua,"mi_close",lua_exitpre); + lua_register(lua,"mi_addbhpoint",lua_addbhpoint); + lua_register(lua,"mi_clearbhpoints",lua_clearbhpoints); + lua_register(lua,"mi_refreshview",lua_updatewindow); + lua_register(lua,"mi_shownames",lua_shownames); + lua_register(lua,"mi_showgrid",lua_showgrid); + lua_register(lua,"mi_hidegrid",lua_hidegrid); + lua_register(lua,"mi_gridsnap",lua_gridsnap); + lua_register(lua,"mi_setgrid",lua_setgrid); + lua_register(lua,"mi_setfocus",lua_switchfocus); + lua_register(lua,"mi_readdxf",lua_readdxf); + lua_register(lua,"mi_savedxf",lua_savedxf); + lua_register(lua,"mi_defineouterspace",lua_defineouterspace); + lua_register(lua,"mi_attachouterspace",lua_attachouterspace); + lua_register(lua,"mi_detachouterspace",lua_detachouterspace); + lua_register(lua,"mi_attachdefault",lua_attachdefault); + lua_register(lua,"mi_detachdefault",lua_detachdefault); + lua_register(lua,"mi_attach_default",lua_attachdefault); + lua_register(lua,"mi_detach_default",lua_detachdefault); + lua_register(lua,"mi_resize",luaResize); + lua_register(lua,"mi_minimize",luaMinimize); + lua_register(lua,"mi_maximize",luaMaximize); + lua_register(lua,"mi_restore", luaRestore); + lua_register(lua,"mi_createradius",lua_createradius); + lua_register(lua,"mi_gettitle",lua_gettitle); + lua_register(lua,"mi_setgroup",lua_setgroup); + lua_register(lua,"mi_getmaterial",lua_getmaterial); + lua_register(lua,"mi_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"mi_getboundingbox",lua_getboundingbox); + lua_register(lua,"mi_selectcircle",lua_selectcircle); + lua_register(lua,"mi_selectrectangle",lua_selectrectangle); + lua_register(lua,"mi_setprevious",lua_previous); + + // compatibility lua function names + lua_register(lua,"mi_select_rectangle",lua_selectrectangle); + lua_register(lua,"mi_select_circle",lua_selectcircle); + lua_register(lua,"mi_set_group",lua_setgroup); + lua_register(lua,"mi_get_title",lua_gettitle); + lua_register(lua,"mi_define_outer_space",lua_defineouterspace); + lua_register(lua,"mi_attach_outer_space",lua_attachouterspace); + lua_register(lua,"mi_detach_outer_space",lua_detachouterspace); + lua_register(lua,"mi_set_focus",lua_switchfocus); + lua_register(lua,"mi_save_as",luaSaveDocument); + lua_register(lua,"mi_create_mesh",lua_create_mesh); + lua_register(lua,"mi_show_mesh",lua_show_mesh); + lua_register(lua,"mi_purge_mesh",lua_purge_mesh); + lua_register(lua,"mi_prob_def",lua_prob_def); + lua_register(lua,"mi_analyze",lua_analyze); + lua_register(lua,"mi_load_solution",lua_runpost); + lua_register(lua,"mi_add_node",lua_addnode); + lua_register(lua,"mi_add_block_label",lua_addlabel); + lua_register(lua,"mi_add_segment",lua_addline); + lua_register(lua,"mi_add_arc",lua_addarc); + lua_register(lua,"mi_select_node",lua_selectnode); + lua_register(lua,"mi_select_label",lua_selectlabel); + lua_register(lua,"mi_select_segment",lua_selectsegment); + lua_register(lua,"mi_select_arcsegment",lua_selectarcsegment); + lua_register(lua,"mi_clear_selected",lua_clearselected); + lua_register(lua,"mi_set_node_prop",lua_setnodeprop); + lua_register(lua,"mi_set_block_prop",lua_setblockprop); + lua_register(lua,"mi_set_segment_prop",lua_setsegmentprop); + lua_register(lua,"mi_set_arcsegment_prop",lua_setarcsegmentprop); + lua_register(lua,"mi_delete_selected",lua_deleteselected); + lua_register(lua,"mi_delete_selected_nodes",lua_deleteselectednodes); + lua_register(lua,"mi_delete_selected_labels",lua_deleteselectedlabels); + lua_register(lua,"mi_delete_selected_segments",lua_deleteselectedsegments); + lua_register(lua,"mi_delete_selected_arcsegments",lua_deleteselectedarcsegments); + lua_register(lua,"mi_zoom_natural",lua_zoomnatural); + lua_register(lua,"mi_zoom_out",lua_zoomout); + lua_register(lua,"mi_zoom_in",lua_zoomin); + lua_register(lua,"mi_add_material",lua_addmatprop); + lua_register(lua,"mi_add_point_prop",lua_addpointprop); + lua_register(lua,"mi_add_circ_prop",lua_addcircuitprop); + lua_register(lua,"mi_add_bound_prop",lua_addboundprop); + lua_register(lua,"mi_modify_material",lua_modmatprop); + lua_register(lua,"mi_modify_bound_prop",lua_modboundprop); + lua_register(lua,"mi_modify_point_prop",lua_modpointprop); + lua_register(lua,"mi_modify_circ_prop",lua_modcircprop); + lua_register(lua,"mi_delete_material",lua_delmatprop); + lua_register(lua,"mi_delete_bound_prop",lua_delboundprop); + lua_register(lua,"mi_delete_circuit",lua_delcircuitprop); + lua_register(lua,"mi_delete_point_prop",lua_delpointprop); + lua_register(lua,"mi_move_rotate",lua_move_rotate); + lua_register(lua,"mi_move_translate",lua_move_translate); + lua_register(lua,"mi_copy_rotate",lua_copy_rotate); + lua_register(lua,"mi_copy_translate",lua_copy_translate); + lua_register(lua,"mi_set_edit_mode",lua_seteditmode); + lua_register(lua,"mi_select_group",lua_selectgroup); + lua_register(lua,"mi_new_document",lua_newdocument); + lua_register(lua,"mi_save_bitmap",lua_savebitmap); + lua_register(lua,"mi_save_metafile",lua_saveWMF); + lua_register(lua,"mi_add_bh_point",lua_addbhpoint); + lua_register(lua,"mi_clear_bh_points",lua_clearbhpoints); + lua_register(lua,"mi_refresh_view",lua_updatewindow); + lua_register(lua,"mi_show_grid",lua_showgrid); + lua_register(lua,"mi_hide_grid",lua_hidegrid); + lua_register(lua,"mi_grid_snap",lua_gridsnap); + lua_register(lua,"mi_set_grid",lua_setgrid); + lua_register(lua,"mi_show_names",lua_shownames); + lua_register(lua,"mi_read_dxf",lua_readdxf); + lua_register(lua,"mi_save_dxf",lua_savedxf); + lua_register(lua,"mi_create_radius",lua_createradius); + lua_register(lua,"mi_get_material",lua_getmaterial); + + pFemmeDoc=(CFemmeDoc *)this; +} + +int CFemmeDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CFemmeDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".fem") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CFemmeDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".fem") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pFemmeDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CFemmeDoc::lua_exitpre(lua_State *L) +{ + CatchNullDocument(); + ((CFemmeDoc *)pFemmeDoc)->OnCloseDocument( ); + + return 0; +} + +int CFemmeDoc::lua_readdxf(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + double DefTol; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + if (n==2) DefTol=lua_todouble(L,2); + else DefTol=0; + + result=thisDoc->ReadDXF(DocTitle,DefTol); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CFemmeDoc::lua_savedxf(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + CString DocTitle; + BOOL result; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return FALSE; + DocTitle.Format("%s",lua_tostring(L,1)); + + result=thisDoc->WriteDXF(DocTitle); + if (result) theView->InvalidateRect(NULL); + + return result; +} + +int CFemmeDoc::luaSaveDocument(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + int n; + n=lua_gettop(L); + + CString temp; + temp.Format("%s",lua_tostring(L,n)); + thisDoc->OnSaveDocument(temp); + thisDoc->SetPathName(temp); + + return 0; +} + +int CFemmeDoc::lua_previous(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + int n; + n=lua_gettop(L); + + CString PrevSoln; + if (n>0){ + PrevSoln.Format("%s",lua_tostring(L,1)); + thisDoc->PrevSoln=PrevSoln; + } + + if (n>1) thisDoc->PrevType = (int)lua_todouble(L, 2); + else thisDoc->PrevType = 0; + + return 0; +} + +int CFemmeDoc::lua_prob_def(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + CString units,type; + int n; + n=lua_gettop(L); + + // error traps + int LengthUnits=-1; + int ProblemType=-1; + double Frequency; + double Precision; + double MinAngle=-1; + int ACSolver=-1; + + // Frequency + Frequency=fabs(lua_todouble(L,1)); + thisDoc->Frequency=fabs(Frequency); + if(n==1) return 0; + + // Length Units + units.Format("%s",lua_tostring(L,2)); + if(units=="inches") LengthUnits=0; + if(units=="millimeters") LengthUnits=1; + if(units=="centimeters") LengthUnits=2; + if(units=="meters") LengthUnits=3; + if(units=="mills") LengthUnits=4; + if(units=="mils") LengthUnits=4; + if(units=="micrometers") LengthUnits=5; + if (LengthUnits==-1) + { + CString msg; + msg.Format("Unknown length unit %s",units); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + thisDoc->LengthUnits=LengthUnits; + if (n==2) return 0; + } + + // Problem type + type.Format("%s",lua_tostring(L,3)); + if(type=="planar") ProblemType=0; + if(type=="axi") ProblemType=1; + if (ProblemType==-1) + { + CString msg; + msg.Format("Unknown problem type %s",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->ProblemType=ProblemType; + if (n==3) return 0; + } + + Precision=lua_todouble(L,4); + if (Precision < 1.e-16 || Precision >1.e-8) + { + CString msg; + msg.Format("Invalid Precision %lf",Precision); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + else + { + thisDoc->Precision=Precision; + if (n==4) return 0; + } + + thisDoc->Depth=fabs(lua_todouble(L,5)); + if (thisDoc->Depth<=0) thisDoc->Depth=1; + if (n==5) return 0; + + MinAngle=lua_todouble(L,6); + if ((MinAngle>=1.) && (MinAngle<=MINANGLE_MAX)) + { + thisDoc->MinAngle=MinAngle; + } + if (n==6) return 0; + + ACSolver=(int)lua_todouble(L,7); + if ((ACSolver==0) || (ACSolver==1)) + { + thisDoc->ACSolver=ACSolver; + } + + return 0; +} + +int CFemmeDoc::lua_create_mesh(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + theView->lnuMakeMesh(); + + return 1; +} + +int CFemmeDoc::lua_smartmesh(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + if (lua_gettop(L)!=0) + { + int k = (int)lua_todouble(L,1); + if (k!=0) k=1; + thisDoc->SmartMesh=k; + } + + return 0; +} + +int CFemmeDoc::lua_show_mesh(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + theView->lnu_show_mesh(); + + return 0; +} + +int CFemmeDoc::lua_purge_mesh(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + theView->lnu_purge_mesh(); + + return 0; +} + +int CFemmeDoc::lua_analyze(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + int bHide=0; + if ((n==0) && (theApp.GetMainWnd()->GetStyle() & WS_MINIMIZE)) bHide=1; + if (n>0) bHide=(int)lua_todouble(L,1); + if (bHide!=0) bHide=1; + + theView->lnu_analyze(bHide); + + return 0; +} + +int CFemmeDoc::lua_runpost(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc=(CFemmeDoc *)pFemmeDoc; + CString pn = thisDoc->GetPathName(); + + if (pn.GetLength()==0){ + CString msg; + msg.Format("No results to display"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".ans\""; + if (((CFemmApp *) AfxGetApp())->MOCheckIfAlreadyOpen(rootname)==FALSE) + AfxGetApp( )->OpenDocumentFile(rootname); + + return 0; +} + + +int CFemmeDoc::lua_addnode(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + double x,y,d; + + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddNode(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + +int CFemmeDoc::lua_addlabel(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + double x,y,d; + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + +// if(thisDoc->Coords) +// { +// double r,t; +// r=mx; +// t=my*PI/180; +// x=mx*cos(t); +// y=mx*sin(t); +// } + + if (thisDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=thisDoc->nodelist[0].CC(); + p1=p0; + for(int i=1;inodelist.GetSize();i++) + { + p2=thisDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + BOOL flag; + flag=thisDoc->AddBlockLabel(x,y,d); + + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + + return 0; +} + + +int CFemmeDoc::lua_addline(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + double sx,sy,ex,ey; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CFemmeView *)thisDoc->GetNextView(pos); + BOOL flag; + + flag=thisDoc->AddSegment(thisDoc->ClosestNode(sx,sy),thisDoc->ClosestNode(ex,ey)); + + if(flag==TRUE) + { + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CFemmeDoc::lua_addarc(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + + double sx,sy,ex,ey; + double angle,maxseg; + + sx=lua_todouble(L,1); + sy=lua_todouble(L,2); + ex=lua_todouble(L,3); + ey=lua_todouble(L,4); + + angle=lua_todouble(L,5); + maxseg=lua_todouble(L,6); + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CFemmeView *)thisDoc->GetNextView(pos); + BOOL flag; + + CArcSegment asegm; + asegm.n0=thisDoc->ClosestNode(sx,sy); + asegm.n1=thisDoc->ClosestNode(ex,ey); + thisDoc->nodelist[asegm.n1].ToggleSelect(); + theView->DrawPSLG(); + + asegm.MaxSideLength=maxseg; + asegm.ArcLength=angle; + asegm.BoundaryMarker=""; + + flag=thisDoc->AddArcSegment(asegm); + flag=FALSE; + thisDoc->UnselectAll(); + if(flag==TRUE){ + theView->MeshUpToDate=FALSE; + if(theView->MeshFlag==TRUE) theView->lnu_show_mesh(); + else theView->DrawPSLG(); + } + else theView->DrawPSLG(); + + return 0; +} + +int CFemmeDoc::lua_selectnode(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->nodelist.GetSize()==0) return 0; + node=thisDoc->ClosestNode(mx,my); + thisDoc->nodelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[node].x); + lua_pushnumber(L,thisDoc->nodelist[node].y); + + return 2; +} + +int CFemmeDoc::lua_selectlabel(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->blocklist.GetSize()==0) return 0; + node=thisDoc->ClosestBlockLabel(mx,my); + thisDoc->blocklist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->blocklist[node].x); + lua_pushnumber(L,thisDoc->blocklist[node].y); + + return 2; +} + + +int CFemmeDoc::lua_selectsegment(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->linelist.GetSize()==0) return 0; + node=thisDoc->ClosestSegment(mx,my); + thisDoc->linelist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->linelist[node].n1].y); + + return 4; +} + + +int CFemmeDoc::lua_selectarcsegment(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + + double mx,my; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int node; + if(thisDoc->arclist.GetSize()==0) return 0; + node=thisDoc->ClosestArcSegment(mx,my); + thisDoc->arclist[node].ToggleSelect(); + + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n0].y); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].x); + lua_pushnumber(L,thisDoc->nodelist[thisDoc->arclist[node].n1].y); + + return 4; +} + +int CFemmeDoc::lua_clearselected(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + thisDoc->UnselectAll(); + return 0; +} + +int CFemmeDoc::lua_setnodeprop(lua_State *L) +{ + CatchNullDocument(); + CString nodeprop; + int groupno; + + nodeprop.Format("%s",lua_tostring(L,1)); + groupno=(int) lua_todouble(L,2); + + if (groupno<0) + { + CString msg; + msg.Format("Invalid group no %d",groupno); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CFemmeDoc *thisDoc=(CFemmeDoc *)pFemmeDoc; + int i; + + // check to see how many (if any) nodes are selected. + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].IsSelected==TRUE) + { + thisDoc->nodelist[i].InGroup=groupno; + thisDoc->nodelist[i].BoundaryMarker=nodeprop; + } + } + + return 0; +} + +int CFemmeDoc::lua_setblockprop(lua_State *L) +{ + CatchNullDocument(); + CString blocktype,incircuit,magdirfctn; + BOOL automesh; + double meshsize,magdirection; + int group,turns; + + int n=lua_gettop(L); + + blocktype=""; + automesh=1; + incircuit=""; + magdirection=0; + magdirfctn.Empty(); + group=0; + turns=1; + + if (n>0) blocktype.Format("%s",lua_tostring(L,1)); + if (n>1) automesh=(int) lua_todouble(L,2); + if (n>2) meshsize=lua_todouble(L,3); + if (n>3) incircuit.Format("%s",lua_tostring(L,4)); + if (n>4){ + if (lua_isnumber(L,5)) magdirection=lua_todouble(L,5); + else magdirfctn.Format("%s",lua_tostring(L,5)); + } + if (n>5) group=(int) lua_todouble(L,6); + if (n>6){ + turns=(int) lua_todouble(L,7); + if (turns==0) turns=1; + } + + CFemmeDoc *thisDoc=(CFemmeDoc *)pFemmeDoc; + int i; + + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].MaxArea=PI*meshsize*meshsize/4.; + thisDoc->blocklist[i].MagDir=magdirection; + thisDoc->blocklist[i].BlockType=blocktype; + thisDoc->blocklist[i].InCircuit=incircuit; + thisDoc->blocklist[i].InGroup=group; + thisDoc->blocklist[i].Turns=turns; + thisDoc->blocklist[i].MagDirFctn=magdirfctn; + if(automesh==1) thisDoc->blocklist[i].MaxArea=0; + } + } + + return 0; +} + +int CFemmeDoc::lua_setsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString prop; + double elesize; + int automesh,hide,group; + + prop.Format("%s",lua_tostring(L,1)); + elesize=lua_todouble(L,2); + automesh=(int) lua_todouble(L,3); + hide=(int) lua_todouble(L,4); + group=(int) lua_todouble(L,5); + + CFemmeDoc *thisDoc=(CFemmeDoc *)pFemmeDoc; + + for(int i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].IsSelected==TRUE){ + if (automesh==1) thisDoc->linelist[i].MaxSideLength=-1; + else{ + if (elesize>0) + thisDoc->linelist[i].MaxSideLength=elesize; + else elesize=-1; + } + thisDoc->linelist[i].BoundaryMarker=prop; + thisDoc->linelist[i].Hidden=hide; + thisDoc->linelist[i].InGroup=group; + } + } + + return 0; +} + +int CFemmeDoc::lua_setarcsegmentprop(lua_State *L) +{ + CatchNullDocument(); + CString boundprop; + double maxsegdeg; + int hide,group; + + maxsegdeg=lua_todouble(L,1); + if (maxsegdeg>10) maxsegdeg=10; + if (maxsegdeg<=0) maxsegdeg=1; + boundprop.Format("%s",lua_tostring(L,2)); + hide=(int) lua_todouble(L,3); + group=(int) lua_todouble(L,4); + + CFemmeDoc *thisDoc=(CFemmeDoc *)pFemmeDoc; + int i; + + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].IsSelected==TRUE){ + thisDoc->arclist[i].BoundaryMarker=boundprop; + thisDoc->arclist[i].MaxSideLength=maxsegdeg; + thisDoc->arclist[i].Hidden=hide; + thisDoc->arclist[i].InGroup=group; + } + } + + return 0; +} + +int CFemmeDoc::lua_deleteselectednodes(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + thisDoc->DeleteSelectedNodes(); + return 0; +} + +int CFemmeDoc::lua_deleteselectedlabels(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + thisDoc->DeleteSelectedBlockLabels(); + return 0; +} + +int CFemmeDoc::lua_deleteselectedsegments(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + thisDoc->DeleteSelectedSegments(); + return 0; +} + +int CFemmeDoc::lua_deleteselectedarcsegments(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + thisDoc->DeleteSelectedArcSegments(); + return 0; +} + +int CFemmeDoc::lua_deleteselected(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + thisDoc->DeleteSelectedSegments(); + thisDoc->DeleteSelectedArcSegments(); + thisDoc->DeleteSelectedNodes(); + thisDoc->DeleteSelectedBlockLabels(); + + return 0; +} + +int CFemmeDoc::lua_newdocument(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + thisDoc->OnNewDocument(); + thisDoc->SetPathName("Untitled",FALSE); + thisDoc->SetTitle("Untitled"); + return 0; +} + + +int CFemmeDoc::lua_zoomnatural(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + theView->lua_zoomnatural(); + + return 0; +} + + +int CFemmeDoc::lua_zoomout(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + theView->lua_zoomout(); + + return 0; +} + +int CFemmeDoc::lua_zoomin(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView *theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + theView->lua_zoomin(); + +// PostMessage(theView->m_hWnd,WM_COMMAND,0,ID_ZOOM_IN); +// it would be nice to use messages but I need to check the format first +// this would cut down on code used twice and some unnecessary code ! + + + return 0; +} + +int CFemmeDoc::lua_zoom(lua_State *L) +{ + CatchNullDocument(); + + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CRect r; + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CFemmeDoc::lua_copy_rotate(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc *thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + // IF N=5 WE Have an edit action, if n=4 we dont ! + + int EditAction,copies; + + double x,y,angle; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + angle=lua_todouble(L,3); + copies=(int) lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for copy rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + thisDoc->RotateCopy(CComplex(x,y),angle,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmeDoc::lua_copy_translate(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + int EditAction, copies; + double x,y; + x=lua_todouble(L,1); + y=lua_todouble(L,2); + copies=(int) lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for copy translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->TranslateCopy(x,y,copies,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + + return 0; +} + + +int CFemmeDoc::lua_move_translate(lua_State *L) +{ + CatchNullDocument(); + + double x,y; + int EditAction; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + + if (n==3) EditAction=(int) lua_todouble(L,3); + if (n==2) EditAction=theView->EditAction; + + if(n!=3 && n!=2) + { + CString msg; + msg.Format("Invalid number of parameters for move translate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->TranslateMove(x,y,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + +int CFemmeDoc::lua_move_rotate(lua_State *L) +{ + CatchNullDocument(); + + double x,y,shiftangle; + int EditAction; + + int n; + n=lua_gettop(L); + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + shiftangle=lua_todouble(L,3); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for move rotate"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + { + thisDoc->UpdateUndo(); + thisDoc->RotateMove(CComplex(x,y),shiftangle,EditAction); + thisDoc->meshnode.RemoveAll(); + thisDoc->meshline.RemoveAll(); + thisDoc->greymeshline.RemoveAll(); + theView->MeshFlag=FALSE; + theView->MeshUpToDate=FALSE; + theView->InvalidateRect(NULL); + } + + return 0; +} + + +int CFemmeDoc::lua_mirror(lua_State *L) +{ + CatchNullDocument(); + double m_pax,m_pay,m_pbx,m_pby; + int EditAction; + + CFemmeDoc *thisDoc; + CFemmeView *theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n; + n=lua_gettop(L); + + m_pax=lua_todouble(L,1); + m_pay=lua_todouble(L,2); + m_pbx=lua_todouble(L,3); + m_pby=lua_todouble(L,4); + + if (n==5) EditAction=(int) lua_todouble(L,5); + if (n==4) EditAction=theView->EditAction; + + if(n!=4 && n!=5) + { + CString msg; + msg.Format("Invalid number of parameters for mirror"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->MirrorSelected(m_pax,m_pay,m_pbx,m_pby,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmeDoc::lua_scale(lua_State *L) +{ + CatchNullDocument(); + int EditAction; + double x,y,scalefactor; + + int n; + n=lua_gettop(L); + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + scalefactor=lua_todouble(L,3); + EditAction=(int) lua_todouble(L,4); + + if (n==4) EditAction=(int) lua_todouble(L,4); + if (n==3) EditAction=theView->EditAction; + + if(n!=4 && n!=3) + { + CString msg; + msg.Format("Invalid number of parameters for scale"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + thisDoc->UpdateUndo(); + thisDoc->ScaleMove(x,y,scalefactor,EditAction); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CFemmeDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int iEditAction; + iEditAction=-1; + + if (EditAction=="nodes") iEditAction=0; + if (EditAction=="segments") iEditAction=1; + if (EditAction=="blocks") iEditAction=2; + if (EditAction=="arcsegments") iEditAction=3; + if (EditAction=="group") iEditAction=4; + + if(iEditAction==-1) + { + CString msg; + msg.Format("Invalid Edit Action %s",EditAction); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + else + { + theView->EditAction=iEditAction; + } + + + return 0; +} + +int CFemmeDoc::lua_selectgroup(lua_State *L) +{ + CatchNullDocument(); + + int group,i; + group=(int) lua_todouble(L,1); + + if(group<0) + { + CString msg; + msg.Format("Invalid group %d",group); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + +// thisDoc->UnselectAll(); + + // select nodes + for(i=0;inodelist.GetSize();i++) + { + if(thisDoc->nodelist[i].InGroup==group) + thisDoc->nodelist[i].IsSelected=TRUE; + } + + // select segments + for(i=0;ilinelist.GetSize();i++) + { + if(thisDoc->linelist[i].InGroup==group) + thisDoc->linelist[i].IsSelected=TRUE; + } + + // select arc segments + for(i=0;iarclist.GetSize();i++) + { + if(thisDoc->arclist[i].InGroup==group) + thisDoc->arclist[i].IsSelected=TRUE; + } + + // select blocks + for(i=0;iblocklist.GetSize();i++) + { + if(thisDoc->blocklist[i].InGroup==group) + thisDoc->blocklist[i].IsSelected=TRUE; + } + + + theView->EditAction=4; // set to group + + return 0; +} + + +int CFemmeDoc::lua_addmatprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_addmatprop(L); + + CatchNullDocument(); + + CMaterialProp m; + int n=lua_gettop(L); + + if (n>0) m.BlockName.Format("%s",lua_tostring(L,1)); + if (n>1){ + m.mu_x=lua_todouble(L,2); + m.mu_y=m.mu_x; + } + if (n>2) m.mu_y=lua_todouble(L,3); + if (n>3) m.H_c=lua_todouble(L,4); + if (n>4) m.Jsrc=lua_tonumber(L,5); + if (n>5) m.Cduct=lua_todouble(L,6); + if (n>6) m.Lam_d=lua_todouble(L,7); + if (n>7) m.Theta_hn=lua_todouble(L,8); + if (n>8){ + m.LamFill=lua_todouble(L,9); + if (m.LamFill<=0) m.LamFill=1; + if (m.LamFill>1) m.LamFill=1; + } + if (n>9){ + m.LamType=(int) lua_todouble(L,10); + if (m.LamType<0) m.LamType=0; + } + if(n>10) + { + m.Theta_hx=lua_todouble(L,11); + m.Theta_hy=lua_todouble(L,12); + } + else{ + m.Theta_hx=m.Theta_hn; + m.Theta_hy=m.Theta_hn; + } + if(n>12){ + m.NStrands=(int) lua_todouble(L,13); + m.WireD=lua_todouble(L,14); + } + + ((CFemmeDoc *)pFemmeDoc)->blockproplist.Add(m); + + return 0; +} + +int CFemmeDoc::lua_addbhpoint(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + CComplex v; + int j,k,n; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + // now, add the bhpoint for the specified material; + n=thisDoc->blockproplist[k].BHpoints; + v=lua_tonumber(L,2)+I*lua_tonumber(L,3); + if(n==0) // Make sure that (0,0) gets included as a data point; + { + n=1; + thisDoc->blockproplist[k].BHpoints=1; + thisDoc->blockproplist[k].BHdata=(CComplex *)malloc(sizeof(CComplex)); + thisDoc->blockproplist[k].BHdata[0]=0; + } + // make sure the point isn't a duplicate + for(j=0;jblockproplist[k].BHdata[j]==v) return 0; + } + CComplex *newBHdata=(CComplex *)calloc(n+1,sizeof(CComplex)); + for(j=0;jblockproplist[k].BHdata[j]; + thisDoc->blockproplist[k].BHpoints=n+1; + if (n!=0) free(thisDoc->blockproplist[k].BHdata); + thisDoc->blockproplist[k].BHdata=newBHdata; + newBHdata[n]=v; + + // make sure that the BH points are in the right order; + int flag; + for(j=0;jnewBHdata[k+1].re) + { + flag=1; + v=newBHdata[k]; + newBHdata[k]=newBHdata[k+1]; + newBHdata[k+1]=v; + } + } + if (flag==0) j=n; + } + + return 0; +} + +int CFemmeDoc::lua_clearbhpoints(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + // now, snuff the BH curve for the specified material + if (thisDoc->blockproplist[k].BHpoints>0) + { + thisDoc->blockproplist[k].BHpoints=0; + free(thisDoc->blockproplist[k].BHdata); + thisDoc->blockproplist[k].BHdata=NULL; + } + + return 0; +} + +int CFemmeDoc::lua_modmatprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_modmatprop(L); + + CatchNullDocument(); + CString BlockName; + int k,modprop; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->blockproplist[k].BlockName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->blockproplist[k].mu_x=lua_todouble(L,3); + break; + case 2: + thisDoc->blockproplist[k].mu_y=lua_todouble(L,3); + break; + case 3: + thisDoc->blockproplist[k].H_c=lua_todouble(L,3); + break; + case 4: + thisDoc->blockproplist[k].Jsrc=lua_tonumber(L,3); + break; + case 5: + thisDoc->blockproplist[k].Cduct=lua_todouble(L,3); + break; + case 6: + thisDoc->blockproplist[k].Lam_d=lua_todouble(L,3); + break; + case 7: + thisDoc->blockproplist[k].Theta_hn=lua_todouble(L,3); + break; + case 8: + thisDoc->blockproplist[k].LamFill=lua_todouble(L,3); + break; + case 9: + thisDoc->blockproplist[k].LamType=(int) lua_todouble(L,3); + break; + case 10: + thisDoc->blockproplist[k].Theta_hx=lua_todouble(L,3); + break; + case 11: + thisDoc->blockproplist[k].Theta_hy=lua_todouble(L,3); + break; + case 12: + thisDoc->blockproplist[k].NStrands=(int) lua_todouble(L,3); + break; + case 13: + thisDoc->blockproplist[k].WireD=lua_todouble(L,4); + default: + break; + } + + return 0; +} + +int CFemmeDoc::lua_addboundprop(lua_State *L) +{ + CatchNullDocument(); + + CBoundaryProp m; + int n=lua_gettop(L); + + if (n>0) m.BdryName.Format("%s",lua_tostring(L,1)); + if (n>1) m.A0=lua_todouble(L,2); + if (n>2) m.A1=lua_todouble(L,3); + if (n>3) m.A2=lua_todouble(L,4); + if (n>4) m.phi=lua_todouble(L,5); + if (n>5) m.Mu=lua_todouble(L,6); + if (n>6) m.Sig=lua_todouble(L,7); + if (n>7) m.c0=lua_tonumber(L,8); + if (n>8) m.c1=lua_tonumber(L,9); + if (n>9) m.BdryFormat=(int) lua_todouble(L,10); + if (n>10) m.InnerAngle=lua_todouble(L,11); + if (n>11) m.InnerAngle=lua_todouble(L,12); + if (n>12) m.InnerAngle=lua_todouble(L,13); + if (n>13) m.InnerAngle=lua_todouble(L,14); + + ((CFemmeDoc *)pFemmeDoc)->lineproplist.Add(m); + + return 0; +} + +int CFemmeDoc::lua_modboundprop(lua_State *L) +{ + CatchNullDocument(); + CString BdryName; + int k,modprop; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the boundary property to modify; + if (thisDoc->lineproplist.GetSize()==0) return TRUE; + BdryName.Format("%s",lua_tostring(L,1)); + for(k=0;klineproplist.GetSize();k++) + if(BdryName==thisDoc->lineproplist[k].BdryName) break; + + // get out of here if there's no matching material + if(k==thisDoc->lineproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->lineproplist[k].BdryName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->lineproplist[k].A0 =lua_todouble(L,3); + break; + case 2: + thisDoc->lineproplist[k].A1 =lua_todouble(L,3); + break; + case 3: + thisDoc->lineproplist[k].A2 =lua_todouble(L,3); + break; + case 4: + thisDoc->lineproplist[k].phi=lua_todouble(L,3); + break; + case 5: + thisDoc->lineproplist[k].Mu =lua_todouble(L,3); + break; + case 6: + thisDoc->lineproplist[k].Sig=lua_todouble(L,3); + break; + case 7: + thisDoc->lineproplist[k].c0 =lua_tonumber(L,3); + break; + case 8: + thisDoc->lineproplist[k].c1 =lua_tonumber(L,3); + break; + case 9: + thisDoc->lineproplist[k].BdryFormat=(int)lua_todouble(L,3); + break; + case 10: + thisDoc->lineproplist[k].InnerAngle=lua_todouble(L,3); + break; + case 11: + thisDoc->lineproplist[k].OuterAngle=lua_todouble(L,3); + break; + + default: + break; + } + + return 0; +} + +int CFemmeDoc::lua_addpointprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_addpointprop(L); + + CatchNullDocument(); + + CPointProp m; + int n=lua_gettop(L); + + if (n>0) m.PointName.Format("%s",lua_tostring(L,1)); + if (n>1) m.Ap=lua_tonumber(L,2); + if (n>2) m.Jp=lua_tonumber(L,3); + + ((CFemmeDoc *)pFemmeDoc)->nodeproplist.Add(m); + + return 0; +} + +int CFemmeDoc::lua_modpointprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_modpointprop(L); + + CatchNullDocument(); + CString PointName; + int k,modprop; + + CFemmeDoc * thisDoc;CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->nodeproplist.GetSize()==0) return TRUE; + PointName.Format("%s",lua_tostring(L,1)); + for(k=0;knodeproplist.GetSize();k++) + if(PointName==thisDoc->nodeproplist[k].PointName) break; + + // get out of here if there's no matching material + if(k==thisDoc->nodeproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->nodeproplist[k].PointName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->nodeproplist[k].Ap=lua_tonumber(L,3); + break; + case 2: + thisDoc->nodeproplist[k].Jp=lua_tonumber(L,3); + break; + default: + break; + } + + return 0; +} + +int CFemmeDoc::lua_addcircuitprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_addcircuitprop(L); + + CatchNullDocument(); + + CCircuit m; + int n=lua_gettop(L); + + if (n>0) m.CircName=lua_tostring(L,1); + if (n>1) m.Amps=lua_tonumber(L,2); + if (n>2) m.CircType=(int) lua_todouble(L,3); + + ((CFemmeDoc *)pFemmeDoc)->circproplist.Add(m); + + return 0; +} + +int CFemmeDoc::lua_modcircprop(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmeDoc *)pFemmeDoc)->old_lua_modcircprop(L); + + CatchNullDocument(); + CString CircName; + int k,modprop; + + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + // find the index of the material to modify; + if (thisDoc->circproplist.GetSize()==0) return TRUE; + CircName.Format("%s",lua_tostring(L,1)); + for(k=0;kcircproplist.GetSize();k++) + if(CircName==thisDoc->circproplist[k].CircName) break; + + // get out of here if there's no matching circuit + if(k==thisDoc->circproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->circproplist[k].CircName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->circproplist[k].Amps=lua_tonumber(L,3); + break; + case 2: + thisDoc->circproplist[k].CircType=(int) lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CFemmeDoc::lua_delcircuitprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CFemmeDoc * thisDoc;CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + for(int i=0;icircproplist.GetSize();i++) + { + if (thisDoc->circproplist[i].CircName==name) + thisDoc->circproplist.RemoveAt(i); + + } + + return 0; +} + +int CFemmeDoc::lua_delmatprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CFemmeDoc * thisDoc;CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + for(int i=0;iblockproplist.GetSize();i++) + { + if (thisDoc->blockproplist[i].BlockName==name) + thisDoc->blockproplist.RemoveAt(i); + + } + + return 0; +} + + +int CFemmeDoc::lua_delboundprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + for(int i=0;ilineproplist.GetSize();i++) + { + if (thisDoc->lineproplist[i].BdryName==name) + thisDoc->lineproplist.RemoveAt(i); + } + + + return 0; +} + +int CFemmeDoc::lua_delpointprop(lua_State *L) +{ + CatchNullDocument(); + CString name; + name.Format("%s",lua_tostring(L,1)); + CFemmeDoc * thisDoc;CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + for(int i=0;inodeproplist.GetSize();i++) + { + if (thisDoc->nodeproplist[i].PointName==name) + thisDoc->nodeproplist.RemoveAt(i); + } + + return 0; +} + +int CFemmeDoc::lua_updatewindow(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CDC tempDC; + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // force redraw + theView->OnDraw(pDC); + + return 0; +} + + +int CFemmeDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + return 0; +} + + +PBITMAPINFO CFemmeDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy17"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits != 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CFemmeDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy18"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy19"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy20"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy21"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy22"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy23"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy24"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + + +int CFemmeDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CFemmeDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CFemmeDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->InvalidateRect(NULL); + + return 0; +} + + +int CFemmeDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FE_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CFemmeDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmeDoc::lua_shownames(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmeDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CFemmeDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CFemmeDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CFemmeDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int CFemmeDoc::lua_defineouterspace(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + int n=lua_gettop(L); + if (n!=3) return 0; + + thisDoc->extZo = fabs(lua_todouble(L,1)); + thisDoc->extRo = fabs(lua_todouble(L,2)); + thisDoc->extRi = fabs(lua_todouble(L,3)); + + if((thisDoc->extRo==0) || (thisDoc->extRi==0)) + { + thisDoc->extZo = 0; + thisDoc->extRo = 0; + thisDoc->extRi = 0; + } + + return 0; +} + +int CFemmeDoc::lua_attachouterspace(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=TRUE; + + return 0; +} + +int CFemmeDoc::lua_detachouterspace(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsExternal=FALSE; + + return 0; +} + +int CFemmeDoc::lua_createradius(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n!=3) return 0; + + double x,y,r; + int k; + + x = lua_todouble(L,1); + y = lua_todouble(L,2); + r = fabs(lua_todouble(L,3)); + + if ((k=thisDoc->ClosestNode(x,y))<0) return 0; // catch case where no nodes have been drawn yet; + + if (thisDoc->CanCreateRadius(k)==FALSE) + { + CString msg; + msg.Format("The specified point is not suitable for conversion into a radius"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + if (thisDoc->CreateRadius(k,r)) + { + theView->InvalidateRect(NULL); + theView->MeshUpToDate=FALSE; + } + else{ + CString msg; + msg.Format("Could not make a radius of the prescribed dimension"); + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// compatibility with previous versions +// +////////////////////////////////////////////////////////////////////////////// + +int CFemmeDoc::old_lua_addmatprop(lua_State *L) +{ + CatchNullDocument(); + + CMaterialProp m; + int n=lua_gettop(L); + + if (n>0) m.BlockName.Format("%s",lua_tostring(L,1)); + if (n>1){ + m.mu_x=lua_todouble(L,2); + m.mu_y=m.mu_x; + } + if (n>2) m.mu_y=lua_todouble(L,3); + if (n>3) m.H_c=lua_todouble(L,4); + if (n>4) m.Jsrc.re=lua_todouble(L,5); + if (n>5) m.Jsrc.im=lua_todouble(L,6); + if (n>6) m.Cduct=lua_todouble(L,7); + if (n>7) m.Lam_d=lua_todouble(L,8); + if (n>8) m.Theta_hn=lua_todouble(L,9); + if (n>9) m.LamFill=lua_todouble(L,10); + if (n>10) m.LamType=(int) lua_todouble(L,11); + if (n>11) + { + m.Theta_hx=lua_todouble(L,12); + m.Theta_hy=lua_todouble(L,13); + } + else{ + m.Theta_hx=m.Theta_hn; + m.Theta_hy=m.Theta_hn; + } + if(n>13){ + m.NStrands=(int) lua_todouble(L,14); + m.WireD=lua_todouble(L,15); + } + + // do some sanity checking + + // shouldn't have a zero or negative permeability + if (m.mu_x<=0) m.mu_x=1; + if (m.mu_y<=0) m.mu_y=1; + + // checks for wire definitions + if (m.LamType>=3) + { + // should always have at least one strand if this is a wire + if (m.NStrands<=0) m.NStrands=1; + } + + ((CFemmeDoc *)pFemmeDoc)->blockproplist.Add(m); + + return 0; +} + +int CFemmeDoc::old_lua_modmatprop(lua_State *L) +{ + CatchNullDocument(); + CString BlockName; + int k,modprop; + + CFemmeDoc * thisDoc;CFemmeView * theView; + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->blockproplist.GetSize()==0) return TRUE; + BlockName.Format("%s",lua_tostring(L,1)); + for(k=0;kblockproplist.GetSize();k++) + if(BlockName==thisDoc->blockproplist[k].BlockName) break; + + // get out of here if there's no matching material + if(k==thisDoc->blockproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->blockproplist[k].BlockName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->blockproplist[k].mu_x=lua_todouble(L,3); + break; + case 2: + thisDoc->blockproplist[k].mu_y=lua_todouble(L,3); + break; + case 3: + thisDoc->blockproplist[k].H_c=lua_todouble(L,3); + break; + case 4: + thisDoc->blockproplist[k].Jsrc.re=lua_todouble(L,3); + break; + case 5: + thisDoc->blockproplist[k].Jsrc.im=lua_todouble(L,3); + break; + case 6: + thisDoc->blockproplist[k].Cduct=lua_todouble(L,3); + break; + case 7: + thisDoc->blockproplist[k].Lam_d=lua_todouble(L,3); + break; + case 8: + thisDoc->blockproplist[k].Theta_hn=lua_todouble(L,3); + break; + case 9: + thisDoc->blockproplist[k].LamFill=lua_todouble(L,3); + break; + case 10: + thisDoc->blockproplist[k].LamType=(int) lua_todouble(L,3); + break; + case 11: + thisDoc->blockproplist[k].Theta_hx=lua_todouble(L,3); + break; + case 12: + thisDoc->blockproplist[k].Theta_hy=lua_todouble(L,3); + break; + case 13: + thisDoc->blockproplist[k].NStrands=(int) lua_todouble(L,3); + break; + case 14: + thisDoc->blockproplist[k].WireD=lua_todouble(L,4); + default: + break; + } + + return 0; +} + +int CFemmeDoc::old_lua_addpointprop(lua_State *L) +{ + CatchNullDocument(); + + CPointProp m; + int n=lua_gettop(L); + + if (n>0) m.PointName.Format("%s",lua_tostring(L,1)); + if (n>1) m.Ap.re=lua_todouble(L,2); + if (n>2) m.Ap.im=lua_todouble(L,3); + if (n>3) m.Jp.re=lua_todouble(L,4); + if (n>4) m.Jp.im=lua_todouble(L,5); + ((CFemmeDoc *)pFemmeDoc)->nodeproplist.Add(m); + + return 0; +} + +int CFemmeDoc::old_lua_modpointprop(lua_State *L) +{ + CatchNullDocument(); + CString PointName; + int k,modprop; + + CFemmeDoc * thisDoc;CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + // find the index of the material to modify; + if (thisDoc->nodeproplist.GetSize()==0) return TRUE; + PointName.Format("%s",lua_tostring(L,1)); + for(k=0;knodeproplist.GetSize();k++) + if(PointName==thisDoc->nodeproplist[k].PointName) break; + + // get out of here if there's no matching material + if(k==thisDoc->nodeproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->nodeproplist[k].PointName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->nodeproplist[k].Ap.re=lua_todouble(L,3); + break; + case 2: + thisDoc->nodeproplist[k].Ap.im=lua_todouble(L,3); + break; + case 3: + thisDoc->nodeproplist[k].Jp.re=lua_todouble(L,3); + break; + case 4: + thisDoc->nodeproplist[k].Jp.im=lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CFemmeDoc::old_lua_addcircuitprop(lua_State *L) +{ + CatchNullDocument(); + + CCircuit m; + int n=lua_gettop(L); + + if (n>0) m.CircName=lua_tostring(L,1); + if (n>1) m.Amps.re=lua_todouble(L,2); + if (n>2) m.Amps.im=lua_todouble(L,3); + if (n>3) m.CircType=(int) lua_todouble(L,4); + + ((CFemmeDoc *)pFemmeDoc)->circproplist.Add(m); + + return 0; +} + +int CFemmeDoc::old_lua_modcircprop(lua_State *L) +{ + CatchNullDocument(); + CString CircName; + int k,modprop; + + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + // find the index of the material to modify; + if (thisDoc->circproplist.GetSize()==0) return TRUE; + CircName.Format("%s",lua_tostring(L,1)); + for(k=0;kcircproplist.GetSize();k++) + if(CircName==thisDoc->circproplist[k].CircName) break; + + // get out of here if there's no matching circuit + if(k==thisDoc->circproplist.GetSize()) return TRUE; + + modprop=(int) lua_todouble(L,2); + + // now, modify the specified attribute... + switch(modprop) + { + case 0: + thisDoc->circproplist[k].CircName.Format("%s",lua_tostring(L,3)); + break; + case 1: + thisDoc->circproplist[k].Amps.re=lua_todouble(L,3); + break; + case 2: + thisDoc->circproplist[k].Amps.im=lua_todouble(L,3); + break; + case 3: + thisDoc->circproplist[k].CircType=(int) lua_todouble(L,3); + break; + default: + break; + } + + return 0; +} + +int CFemmeDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + +int CFemmeDoc::lua_setgroup(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + int grp,i; + + int n=lua_gettop(L); + + if (n>0) grp =(int) lua_todouble(L,1); + else return 0; + + for(i=0;inodelist.GetSize();i++) + if(thisDoc->nodelist[i].IsSelected==TRUE) + thisDoc->nodelist[i].InGroup=grp; + + for(i=0;ilinelist.GetSize();i++) + if(thisDoc->linelist[i].IsSelected==TRUE) + thisDoc->linelist[i].InGroup=grp; + + for(i=0;iarclist.GetSize();i++) + if(thisDoc->arclist[i].IsSelected==TRUE) + thisDoc->arclist[i].InGroup=grp; + + for(i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].InGroup=grp; + + thisDoc->UnselectAll(); + + return 0; +} + +int CFemmeDoc::lua_getmaterial(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + CString matname; + int n=lua_gettop(L); + + if (n>0) matname=lua_tostring(L,1); + else return 0; + + CString LibName=thisDoc->BinDir+"matlib.dat"; + + FILE *fp; + int i,j,k; + char s[1024],q[1024]; + char *v; + + CMaterialProp MProp; + + if ((fp=fopen(LibName,"rt"))==NULL){ + CString msg; + msg.Format("Couldn't open %s",LibName); + lua_error(L,msg.GetBuffer(1)); + return FALSE; + } + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + if (sscanf(s,"%s",q)==EOF) 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); + 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){ + if (MProp.BlockName==matname){ + thisDoc->blockproplist.Add(MProp); + MProp.BHpoints=0; + fclose(fp); + return 0; + } + else{ + free(MProp.BHdata); + MProp.BHdata=NULL; + MProp.BHpoints=0; + } + q[0]=NULL; + } + } + + fclose(fp); + + CString msg; + msg.Format("Couldn't load \"%s\" from the materials library",matname); + lua_error(L,msg.GetBuffer(1)); + return FALSE; +} + +int CFemmeDoc::lua_attachdefault(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + for(int i=0,j=0;iblocklist.GetSize();i++) + { + if ((thisDoc->blocklist[i].IsSelected==TRUE) && (j==0)) + { + thisDoc->blocklist[i].IsDefault=2; + j++; + } + else thisDoc->blocklist[i].IsDefault=FALSE; + } + + return 0; +} + +int CFemmeDoc::lua_getprobleminfo(lua_State * L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Frequency); + lua_pushnumber(L,thisDoc->Depth); + switch (thisDoc->LengthUnits) + { + case 1: // mm + lua_pushnumber(L,0.001); + break; + case 2: // cm + lua_pushnumber(L,0.01); + break; + case 3: // m + lua_pushnumber(L,1.0); + break; + case 4: // mils + lua_pushnumber(L,2.54e-05); + break; + case 5: // um + lua_pushnumber(L,1.0e-06); + break; + default:// inches + lua_pushnumber(L,0.0254); + break; + } + + return 4; +} + +int CFemmeDoc::lua_getboundingbox(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + CFemmeView * theView; + + thisDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmeView *)thisDoc->GetNextView(pos); + + double x[2],y[2]; + if (theView->GetBoundingBox(x,y)) + { + lua_pushnumber(L,x[0]); + lua_pushnumber(L,x[1]); + lua_pushnumber(L,y[0]); + lua_pushnumber(L,y[1]); + return 4; + } + else return 0; + +} + +int CFemmeDoc::lua_detachdefault(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * thisDoc; + thisDoc=(CFemmeDoc *)pFemmeDoc; + + for(int i=0;iblocklist.GetSize();i++) + if(thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsDefault=FALSE; + + return 0; +} + +int CFemmeDoc::lua_selectcircle(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * pDoc; + CFemmeView * theView; + + pDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CFemmeView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double R; + CComplex c,q; + + n=lua_gettop(L); + if (n<3) return 0; + c=lua_tonumber(L,1)+I*lua_tonumber(L,2); + R=lua_todouble(L,3); + if (n>3) EditAction=(int) lua_todouble(L,4); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} + +int CFemmeDoc::lua_selectrectangle(lua_State *L) +{ + CatchNullDocument(); + CFemmeDoc * pDoc; + CFemmeView * theView; + + pDoc=(CFemmeDoc *)pFemmeDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CFemmeView *)pDoc->GetNextView(pos); + + int i,k,n,EditAction; + double mx,my,wzx,wzy,x,y,z; + + n=lua_gettop(L); + if (n<4) return 0; + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + wzx=lua_todouble(L,3); + wzy=lua_todouble(L,4); + if (n>4) EditAction=(int) lua_todouble(L,5); + else EditAction=theView->EditAction; + if ((EditAction>4) || (EditAction<0)) return 0; + + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + + theView->InvalidateRect(NULL); + return 0; +} \ No newline at end of file diff --git a/femm/femmplotDoc.cpp b/femm/femmplotDoc.cpp new file mode 100644 index 0000000..deb6aa1 --- /dev/null +++ b/femm/femmplotDoc.cpp @@ -0,0 +1,168 @@ +// femmplotDoc.cpp : implementation of the CFemmplotDoc class +// + +#include "stdafx.h" +#include "femm.h" + +#include "femmplotDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc + +IMPLEMENT_DYNCREATE(CFemmplotDoc, CDocument) + +BEGIN_MESSAGE_MAP(CFemmplotDoc, CDocument) + //{{AFX_MSG_MAP(CFemmplotDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc construction/destruction + +CFemmplotDoc::CFemmplotDoc() +{ + // TODO: add one-time construction code here + hMetaPlot=NULL; + HasBoundingBox=FALSE; +} + +CFemmplotDoc::~CFemmplotDoc() +{ + DeleteEnhMetaFile(hMetaPlot); +} + +BOOL CFemmplotDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // clear out any old metafile; + DeleteEnhMetaFile(hMetaPlot); + HasBoundingBox=FALSE; + + // grab a new metafile from the clipboard; + GrabMetafile(); + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc serialization + +void CFemmplotDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc diagnostics + +#ifdef _DEBUG +void CFemmplotDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CFemmplotDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc commands + +BOOL CFemmplotDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + if (!CDocument::OnOpenDocument(lpszPathName)) + return FALSE; + + // clear out any old metafile; + DeleteEnhMetaFile(hMetaPlot); + HasBoundingBox=FALSE; + HENHMETAFILE hMetaPlotFile = GetEnhMetaFile(lpszPathName); + if (hMetaPlotFile!=NULL){ + DWORD len =(DWORD) GetEnhMetaFileBits(hMetaPlotFile,NULL,NULL); + unsigned char *buff=(unsigned char *) malloc(len); + if(GetEnhMetaFileBits(hMetaPlotFile,len,buff)==0) + MsgBox("MetaFile not copied"); + hMetaPlot=SetEnhMetaFileBits(len,buff); + } + else MsgBox("Problem opening specified file"); + + DeleteEnhMetaFile(hMetaPlotFile); + + // TODO: Add your specialized creation code here + + return TRUE; +} + +BOOL CFemmplotDoc::OnSaveDocument(LPCTSTR lpszPathName) +{ + // TODO: Add your specialized code here and/or call the base class + BOOL flag=TRUE; + + HENHMETAFILE hMetaCopy=CopyEnhMetaFile(hMetaPlot,lpszPathName); + if (hMetaCopy==NULL){ + MsgBox("Problem writing file to disk"); + flag=FALSE; + } + DeleteEnhMetaFile(hMetaCopy); + + return flag; // CDocument::OnSaveDocument(lpszPathName); +} + +BOOL CFemmplotDoc::GrabMetafile() +{ + if (IsClipboardFormatAvailable(CF_ENHMETAFILE)==FALSE){ + hMetaPlot=NULL; + return FALSE; + + } + if (OpenClipboard(NULL)==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + HENHMETAFILE hMetaClip = (HENHMETAFILE) GetClipboardData(CF_ENHMETAFILE); + HGLOBAL hBound = (HGLOBAL) GetClipboardData(CF_TEXT); + if(hMetaClip==NULL) + { + MsgBox("Couldn't GetClipboardData"); + } + else{ + DWORD len =(DWORD) GetEnhMetaFileBits(hMetaClip,NULL,NULL); + unsigned char *buff=(unsigned char *) malloc(len); + if(GetEnhMetaFileBits(hMetaClip,len,buff)==0) + MsgBox("MetaFile not copied"); + hMetaPlot=SetEnhMetaFileBits(len,buff); + if(hBound!=NULL){ + sscanf((char *) hBound,"%lf %lf %lf %lf", + &bb_left,&bb_bottom,&bb_right,&bb_top); + HasBoundingBox=TRUE; + } + EmptyClipboard(); + } + + CloseClipboard(); + } + + return TRUE; +} + diff --git a/femm/femmplotDoc.h b/femm/femmplotDoc.h new file mode 100644 index 0000000..e1b100a --- /dev/null +++ b/femm/femmplotDoc.h @@ -0,0 +1,51 @@ +// femmplotDoc.h : interface of the CFemmplotDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CFemmplotDoc : public CDocument +{ +protected: // create from serialization only + CFemmplotDoc(); + DECLARE_DYNCREATE(CFemmplotDoc) + +// Attributes +public: + HENHMETAFILE hMetaPlot; + double bb_top,bb_bottom,bb_left,bb_right; + BOOL HasBoundingBox; + +// Operations +public: + + BOOL CFemmplotDoc::GrabMetafile(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmplotDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmplotDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmplotDoc) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/femm/femmplotView.cpp b/femm/femmplotView.cpp new file mode 100644 index 0000000..7713787 --- /dev/null +++ b/femm/femmplotView.cpp @@ -0,0 +1,243 @@ +// femmplotView.cpp : implementation of the CFemmplotView class +// + +#include "stdafx.h" +#include "femm.h" +#include + +#include "lua.h" +#include "luadebug.h" +#include "luaconsoledlg.h" + +#include "femmplotDoc.h" +#include "femmplotView.h" +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern BOOL bLinehook; +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView + +IMPLEMENT_DYNCREATE(CFemmplotView, CView) + +BEGIN_MESSAGE_MAP(CFemmplotView, CView) + //{{AFX_MSG_MAP(CFemmplotView) + ON_COMMAND(ID_FP_EDIT_COPY, OnEditCopy) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_FP_COPY_METAFILE, OnEditCopyAsMetafile) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView construction/destruction + +CFemmplotView::CFemmplotView() +{ + // TODO: add construction code here + +} + +CFemmplotView::~CFemmplotView() +{ +} + +BOOL CFemmplotView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView drawing + +void CFemmplotView::OnDraw(CDC* pDC) +{ + CFemmplotDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + RECT r; + GetClientRect(&r); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + + r.bottom--; + r.right--; + pDC->PlayMetaFile(pDoc->hMetaPlot,&r); + + + // TODO: add draw code for native data here +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView printing + +BOOL CFemmplotView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CFemmplotView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CFemmplotView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView diagnostics + +#ifdef _DEBUG +void CFemmplotView::AssertValid() const +{ + CView::AssertValid(); +} + +void CFemmplotView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CFemmplotDoc* CFemmplotView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFemmplotDoc))); + return (CFemmplotDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView message handlers + +void CFemmplotView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CFemmplotView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} +void CFemmplotView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + // Grab pointer to the Status Bar + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetParentFrame(); + if (MFrm==NULL) MsgBox("Null GetParentFrame"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + +} + +void CFemmplotView::OnMouseMove(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + static char statmsg[256]; + double x,y,ww,wh,pw,ph,ox,oy; + RECT r; + CFemmplotDoc *pDoc=GetDocument(); + + if(pDoc->HasBoundingBox==FALSE) return; + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + ww=fabs((double) (r.right-r.left))+1.; + wh=fabs((double) (r.top-r.bottom))+1.; + pw=pDoc->bb_right-pDoc->bb_left; + ph=pDoc->bb_top-pDoc->bb_bottom; + ox=pDoc->bb_left; + oy=pDoc->bb_bottom; + + x=((double) point.x)*pw/ww + ox; + y=((double) (r.bottom-point.y-1))*ph/wh+oy; + + sprintf(statmsg,"(x=%g,y=%g)",x,y); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void CFemmplotView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if (bActivate && pActivateView==this) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(0); + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL CFemmplotView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} diff --git a/femm/femmplotView.h b/femm/femmplotView.h new file mode 100644 index 0000000..a1d9f22 --- /dev/null +++ b/femm/femmplotView.h @@ -0,0 +1,59 @@ +// femmplotView.h : interface of the CFemmplotView class +// +///////////////////////////////////////////////////////////////////////////// + +class CFemmplotView : public CView +{ +protected: // create from serialization only + CFemmplotView(); + DECLARE_DYNCREATE(CFemmplotView) + +// Attributes +public: + CStatusBar *StatBar; + CFemmplotDoc* GetDocument(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmplotView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmplotView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmplotView) + afx_msg void OnEditCopy(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnEditCopyAsMetafile(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in femmplotView.cpp +inline CFemmplotDoc* CFemmplotView::GetDocument() + { return (CFemmplotDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/femm/femmviewLua.cpp b/femm/femmviewLua.cpp new file mode 100644 index 0000000..f464fad --- /dev/null +++ b/femm/femmviewLua.cpp @@ -0,0 +1,2778 @@ +#include "stdafx.h" +#include +#include +#include "problem.h" +#include "femm.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewview.h" +#include "MainFrm.h" +#include "windows.h" //necessary for bitmap saving +#include "lua.h" +#include "mycommandlineinfo.h" +#include "promptbox.h" +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern lua_State *lua; +extern BOOL bLinehook; +extern void *pFemmviewdoc; +extern CLuaConsoleDlg *LuaConsole; +extern BOOL lua_byebye; +extern int m_luaWindowStatus; + +#define CatchNullDocument(); if (pFemmviewdoc==NULL)\ + { CString msg="No magnetics output in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//-------------------Lua Extensions------------------------- + +void CFemmviewDoc::initalise_lua() +{ + // use a messagebox to display errors + lua_register(lua,"mo_setfocus",lua_switchfocus); + lua_register(lua,"mo_getpointvalues",lua_getpointvals); + lua_register(lua,"mo_close",lua_exitpost); + lua_register(lua,"mo_addcontour",lua_addcontour); + lua_register(lua,"mo_clearcontour",lua_clearcontour); + lua_register(lua,"mo_lineintegral",lua_lineintegral); + lua_register(lua,"mo_selectblock",lua_selectblock); + lua_register(lua,"mo_groupselectblock",lua_groupselectblock); + lua_register(lua,"mo_clearblock",lua_clearblock); + lua_register(lua,"mo_blockintegral",lua_blockintegral); + lua_register(lua,"mo_zoomnatural",lua_zoomnatural); + lua_register(lua,"mo_zoomin",lua_zoomin); + lua_register(lua,"mo_zoomout",lua_zoomout); + lua_register(lua,"mo_zoom",lua_zoom); + lua_register(lua,"mo_showgrid",lua_showgrid); + lua_register(lua,"mo_hidegrid",lua_hidegrid); + lua_register(lua,"mo_gridsnap",lua_gridsnap); + lua_register(lua,"mo_setgrid",lua_setgrid); + lua_register(lua,"mo_showmesh",lua_showmesh); + lua_register(lua,"mo_hidemesh",lua_hidemesh); + lua_register(lua,"mo_hidedensityplot",lua_hidedensity); + lua_register(lua,"mo_showdensityplot",lua_showdensity); + lua_register(lua,"mo_hidecontourplot",lua_hidecountour); + lua_register(lua,"mo_showcontourplot",lua_showcountour); + lua_register(lua,"mo_showvectorplot",lua_vectorplot); + lua_register(lua,"mo_smooth",lua_smoothing); + lua_register(lua,"mo_showpoints",lua_showpoints); + lua_register(lua,"mo_hidepoints",lua_hidepoints); + lua_register(lua,"mo_shownames",lua_shownames); + lua_register(lua,"mo_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"mo_savebitmap",lua_savebitmap); + lua_register(lua,"mo_getcircuitproperties",lua_getcircuitprops); + lua_register(lua,"mo_savemetafile",lua_saveWMF); + lua_register(lua,"mo_refreshview",lua_refreshview); + lua_register(lua,"mo_selectpoint",lua_selectline); + lua_register(lua,"mo_seteditmode",lua_seteditmode); + lua_register(lua,"mo_bendcontour",lua_bendcontour); + lua_register(lua,"mo_makeplot",lua_makeplot); + lua_register(lua,"mo_reload",lua_reload); + lua_register(lua,"mo_gradient",lua_gradient); + lua_register(lua,"mo_gettitle",lua_gettitle); + lua_register(lua,"mo_get_title",lua_gettitle); + lua_register(lua,"mo_set_weighting_scheme",lua_weighting); + lua_register(lua,"mo_setweightingscheme",lua_weighting); + + lua_register(lua,"mo_resize",luaResize); + lua_register(lua,"mo_minimize",luaMinimize); + lua_register(lua,"mo_maximize",luaMaximize); + lua_register(lua,"mo_restore", luaRestore); + + // compatibility with alternate lua function naming convention + lua_register(lua,"mo_set_focus",lua_switchfocus); + lua_register(lua,"mo_get_point_values",lua_getpointvals); + lua_register(lua,"mo_add_contour",lua_addcontour); + lua_register(lua,"mo_clear_contour",lua_clearcontour); + lua_register(lua,"mo_line_integral",lua_lineintegral); + lua_register(lua,"mo_select_block",lua_selectblock); + lua_register(lua,"mo_group_select_block",lua_groupselectblock); + lua_register(lua,"mo_clear_block",lua_clearblock); + lua_register(lua,"mo_block_integral",lua_blockintegral); + lua_register(lua,"mo_zoom_natural",lua_zoomnatural); + lua_register(lua,"mo_zoom_in",lua_zoomin); + lua_register(lua,"mo_zoom_out",lua_zoomout); + lua_register(lua,"mo_show_grid",lua_showgrid); + lua_register(lua,"mo_hide_grid",lua_hidegrid); + lua_register(lua,"mo_show_mesh",lua_showmesh); + lua_register(lua,"mo_hide_mesh",lua_hidemesh); + lua_register(lua,"mo_hide_density_plot",lua_hidedensity); + lua_register(lua,"mo_show_density_plot",lua_showdensity); + lua_register(lua,"mo_hide_contour_plot",lua_hidecountour); + lua_register(lua,"mo_show_contour_plot",lua_showcountour); + lua_register(lua,"mo_show_vector_plot",lua_vectorplot); + lua_register(lua,"mo_show_points",lua_showpoints); + lua_register(lua,"mo_hide_points",lua_hidepoints); + lua_register(lua,"mo_grid_snap",lua_gridsnap); + lua_register(lua,"mo_set_grid",lua_setgrid); + lua_register(lua,"mo_get_problem_info",lua_getprobleminfo); + lua_register(lua,"mo_save_bitmap",lua_savebitmap); + lua_register(lua,"mo_get_circuit_properties",lua_getcircuitprops); + lua_register(lua,"mo_save_metafile",lua_saveWMF); + lua_register(lua,"mo_refresh_view",lua_refreshview); + lua_register(lua,"mo_select_point",lua_selectline); + lua_register(lua,"mo_set_edit_mode",lua_seteditmode); + lua_register(lua,"mo_bend_contour",lua_bendcontour); + lua_register(lua,"mo_make_plot",lua_makeplot); + lua_register(lua,"mo_show_names",lua_shownames); + + // functions to access low-level mesh info + lua_register(lua,"mo_numnodes",lua_numnodes); + lua_register(lua,"mo_numelements",lua_numelements); + lua_register(lua,"mo_getnode",lua_getnode); + lua_register(lua,"mo_getelement",lua_getelement); + + lua_register(lua,"mo_num_nodes",lua_numnodes); + lua_register(lua,"mo_num_elements",lua_numelements); + lua_register(lua,"mo_get_node",lua_getnode); + lua_register(lua,"mo_get_element",lua_getelement); + + lua_register(lua,"mo_get_gap_b",lua_getAGEflux); + lua_register(lua,"mo_getgapb",lua_getAGEflux); + lua_register(lua,"mo_gap_integral",lua_gapintegral); + lua_register(lua,"mo_gapintegral",lua_gapintegral); + lua_register(lua,"mo_get_gap_a",lua_getgapa); + lua_register(lua,"mo_getgapa",lua_getgapa); + lua_register(lua,"mo_getgapharmonics",lua_getgapharmonics); + lua_register(lua,"mo_get_gap_harmonics",lua_getgapharmonics); + + pFemmviewdoc=this; + +} + +int CFemmviewDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + CFemmviewDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".ans") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<5;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(CFemmviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".ans") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + pFemmviewdoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int CFemmviewDoc::lua_dumpheader(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + return 0; +} + +int CFemmviewDoc::lua_getpointvals(lua_State * L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmviewDoc *)pFemmviewdoc)->old_lua_getpointvals(L); + + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CPointVals u; + CComplex Jtot; + + if(thisDoc->GetPointValues(px, py, u)==TRUE) + { + lua_pushnumber(L,u.A); + lua_pushnumber(L,u.B1); + lua_pushnumber(L,u.B2); + lua_pushnumber(L,u.c); + lua_pushnumber(L,u.E); + lua_pushnumber(L,u.H1); + lua_pushnumber(L,u.H2); + lua_pushnumber(L,u.Je); + lua_pushnumber(L,u.Js); + lua_pushnumber(L,u.mu1); + lua_pushnumber(L,u.mu2); + lua_pushnumber(L,u.Pe); + lua_pushnumber(L,u.Ph); + lua_pushnumber(L,u.ff); + return 14; + } + + return 0; +} + +int CFemmviewDoc::lua_exitpost(lua_State * L) +{ + CatchNullDocument(); + ((CFemmviewDoc *)pFemmviewdoc)->OnCloseDocument( ); + + return 0; +} + +int CFemmviewDoc::lua_reload(lua_State * L) +{ + CatchNullDocument(); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + // theView->BeginWaitCursor(); + thisDoc->OnReload(); + // theView->EndWaitCursor(); + if (theView->d_ResetOnReload==FALSE) thisDoc->FirstDraw=FALSE; + theView->RedrawView(); + theView->LuaViewInfo(); + return 0; +} + +void CFemmviewView::LuaViewInfo() +{ + OnViewInfo(); +} + +int CFemmviewDoc::lua_addcontour(lua_State * L) +{ + CatchNullDocument(); + CComplex z; + int i; + z.Set(lua_todouble(L,1),lua_todouble(L,2)); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + i=(int) thisDoc->contour.GetSize(); + + if(i>0){ + if (z!=thisDoc->contour[i-1]) + thisDoc->contour.Add(z); + } + else thisDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + + return 0; +} + +int CFemmviewDoc::lua_clearcontour(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + + return 0; +} + +int CFemmviewDoc::lua_lineintegral(lua_State * L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmviewDoc *)pFemmviewdoc)->old_lua_lineintegral(L); + + CatchNullDocument(); + int type; + CComplex *z; + z=(CComplex *)calloc(4,sizeof(CComplex)); + + type=(int) lua_todouble(L,1); + // 0- B.n + // 1 - H.t + // 2 - Cont length + // 3 - Force from stress tensor + // 4 - Torque from stress tensor + // 5 - (B.n)^2 + + if (type<0 || type >5) + { + CString msg; + msg.Format("Invalid line integral selected %d",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + thisDoc->LineIntegral(type,z); + + switch(type) + { + case 2: // length result + lua_pushnumber(lua,z[0].re); // contour length + lua_pushnumber(lua,z[0].im); // swept area + free(z); + return 2; + + case 3: // force results + if (thisDoc->Frequency!=0){ + lua_pushnumber(lua,z[2].re); + lua_pushnumber(lua,z[3].re); + lua_pushnumber(lua,z[0]); + lua_pushnumber(lua,z[1]); + + free(z); + return 4; + } + else{ + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,z[1].re); + + free(z); + return 2; + } + + + case 4: // torque results + if(thisDoc->Frequency!=0){ + lua_pushnumber(lua,z[1].re); + lua_pushnumber(lua,z[0]); + + free(z); + return 2; + } + else + { + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,0); + + free(z); + return 2; + } + + default: + lua_pushnumber(lua,z[0]); + lua_pushnumber(lua,z[1]); + + free(z); + return 2; + } + + free(z); + return 0; +} + +int CFemmviewDoc::lua_selectblock(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int k; + + if (thisDoc->meshelem.GetSize()>0){ + k=thisDoc->InTriangle(px,py); + if(k>=0){ + thisDoc->bHasMask=FALSE; + thisDoc->blocklist[thisDoc->meshelem[k].lbl].ToggleSelect(); + // RedrawView(); + theView->DrawSelected=thisDoc->meshelem[k].lbl; + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + } + + return 0; +} + +int CFemmviewDoc::lua_groupselectblock(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int j,k,n; + + if (thisDoc->meshelem.GetSize()>0) + { + n=lua_gettop(L); + k=0; if (n>0) k=(int)lua_todouble(L,1); + + for(j=0;jblocklist.GetSize();j++) + { + if ((thisDoc->blocklist[j].InGroup==k) || (n==0)) + thisDoc->blocklist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } +/* + for(j=0;jlinelist.GetSize();j++) + { + if ((thisDoc->linelist[j].InGroup==k) || (n==0)) + thisDoc->linelist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } + + for(j=0;jarclist.GetSize();j++) + { + if ((thisDoc->arclist[j].InGroup==k) || (n==0)) + thisDoc->arclist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } +*/ + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + + return 0; +} + +int CFemmviewDoc::lua_clearblock(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + thisDoc->bHasMask=FALSE; + for(int i=0;iblocklist.GetSize();i++) + { + if (thisDoc->blocklist[i].IsSelected==TRUE) + thisDoc->blocklist[i].IsSelected=FALSE; + } + + + theView->EditAction=0; + + theView->RedrawView(); + + // HDC myDCH=GetDC(theView->m_hWnd); + // CDC tempDC; + // CDC *pDC; + // pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + // theView->OnDraw(pDC); + // theView->DrawSelected=-1; + // theView->ReleaseDC(pDC); + // thisDoc->UpdateAllViews(theView); + + return 0; +} + + +int CFemmviewDoc::lua_blockintegral(lua_State * L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmviewDoc *)pFemmviewdoc)->old_lua_blockintegral(L); + + CatchNullDocument(); + int type; + type=(int) lua_todouble(L,1); + + CFemmviewDoc *thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + CatchNullDocument(); + + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CComplex z; + + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (thisDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE) + { + CString msg="Cannot integrate\nNo area has been selected"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + z=thisDoc->BlockIntegral(type); + + lua_pushnumber(L,z); + + return 1; +} + +int CFemmviewDoc::lua_zoomin(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + + theView->ox=theView->ox+0.25*x/theView->mag; + theView->oy=theView->oy+0.25*y/theView->mag; + theView->mag*=2.; + + theView->RedrawView(); + + + + + return 0; +} + +int CFemmviewDoc::lua_zoom(lua_State * L) +{ + CatchNullDocument(); + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CRect r; + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int CFemmviewDoc::lua_zoomnatural(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + + CFemmviewDoc *pDoc=theView->GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return 0; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + theView->GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + if(pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else theView->RedrawView(); + + + + return 0; +} + +int CFemmviewDoc::lua_zoomout(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + theView->ox=theView->ox-0.5*x/theView->mag; + theView->oy=theView->oy-0.5*y/theView->mag; + theView->mag/=2.; + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_showmesh(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_hidemesh(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_FV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->RedrawView(); + + return 0; +} + + +int CFemmviewDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->RedrawView(); + + return 0; +} + + +int CFemmviewDoc::lua_showdensity(lua_State * L) +{ + CatchNullDocument(); + BOOL showlegend; + BOOL gscale; + double m_ub1,m_lb1; + CString type; + int btnState; + //type real,imag,mag; + + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + showlegend=(int) lua_todouble(L,1); + gscale=(int) lua_todouble(L,2); + m_ub1=lua_todouble(L,3); + m_lb1=lua_todouble(L,4); + + if(m_lb1>m_ub1) + { + double temp=m_lb1; + m_lb1=m_ub1; + m_ub1=temp; + } + + type.Format("%s",lua_tostring(L,5)); + + + btnState=0; + + if (thisDoc->Frequency==0) + { + if((type=="mag") || (type=="bmag")) btnState=1; + if((type=="real") || (type=="breal")) btnState=1; + if((type=="imag") || (type=="bimag")) btnState=1; + if(type=="hmag") btnState=2; + if(type=="hreal") btnState=2; + if(type=="himag") btnState=2; + if(type=="jmag") btnState=3; + if(type=="jreal") btnState=3; + if(type=="jimag") btnState=3; + } + else{ + if((type=="mag") || (type=="bmag")) btnState=1; + if((type=="real") || (type=="breal")) btnState=2; + if((type=="imag") || (type=="bimag")) btnState=3; + if(type=="hmag") btnState=4; + if(type=="hreal") btnState=5; + if(type=="himag") btnState=6; + if(type=="jmag") btnState=7; + if(type=="jreal") btnState=8; + if(type=="jimag") btnState=9; + } + + if (showlegend==-1) + { + m_lb1=thisDoc->d_PlotBounds[btnState-1][0]; + m_ub1=thisDoc->d_PlotBounds[btnState-1][1]; + showlegend=1; + gscale=0; + } + + theView->DensityPlot=btnState; + theView->LegendFlag=showlegend; + theView->GreyContours=gscale; + if(btnState>0) + { + thisDoc->PlotBounds[btnState-1][0]=m_lb1; + thisDoc->PlotBounds[btnState-1][1]=m_ub1; + } + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_hidedensity(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + theView->DensityPlot=0; + + theView->RedrawView(); + + return 0; +} + + +int CFemmviewDoc::lua_showcountour(lua_State * L) +{ + CatchNullDocument(); + int m_numcontours; + double m_alow,m_ahigh; + CString type; + m_numcontours=(int) lua_todouble(L,1); + m_alow=lua_todouble(L,2); + m_ahigh=lua_todouble(L,3); + type=lua_tostring(L,4); + type.MakeLower(); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + if(thisDoc->Frequency!=0) + { + if(type=="real") + { + theView->ShowAr=true; + theView->ShowAi=false; + } + if(type=="imag") + { + theView->ShowAi=true; + theView->ShowAr=false; + } + if(type=="both") + { + theView->ShowAi=theView->ShowAr=true; + } + + thisDoc->A_Low=m_alow; + thisDoc->A_High=m_ahigh; + theView->NumContours=m_numcontours; + theView->RedrawView(); + } + else{ + theView->ShowAr=true; + theView->ShowAi=FALSE; + thisDoc->A_Low=m_alow; + thisDoc->A_High=m_ahigh; + theView->NumContours=m_numcontours; + theView->RedrawView(); + } + + if(m_numcontours==-1) + { + thisDoc->A_Low=thisDoc->A_lb; + thisDoc->A_High=thisDoc->A_ub; + theView->NumContours=19; + } + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_hidecountour(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + theView->ShowAr=FALSE; + theView->ShowAi=FALSE; + + theView->RedrawView(); + return 0; +} + +int CFemmviewDoc::lua_smoothing(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + + if (temp=="off") + { + thisDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + + } + if (temp=="on") + { + thisDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for smoothing"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + + theView->RedrawView(); + + return 0; +} + + +int CFemmviewDoc::lua_showpoints(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_hidepoints(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int CFemmviewDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->RedrawView(); + + return 0; +} + +int CFemmviewDoc::lua_getprobleminfo(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Frequency); + lua_pushnumber(L,thisDoc->Depth); + lua_pushnumber(L,thisDoc->LengthConv[thisDoc->LengthUnits]); + + return 4; +} + +int CFemmviewDoc::lua_savebitmap(lua_State * L) +{ + + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CBitmap *oldbitmap; + + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + oldbitmap=tempDC.SelectObject(&bitmap); + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + // tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + tempDC.SelectObject(oldbitmap); + theView->ReleaseDC(pDC); + tempDC.DeleteDC(); + bitmap.DeleteObject(); + + // to save a bitmap file we need + // a bitmapheader lets use the v5 + + // OpenClipboard(); + // EmptyClipboard(); + // SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + // CloseClipboard(); +return 0; +} + + +PBITMAPINFO CFemmviewDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy25"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits >= 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void CFemmviewDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy26"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy27"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy28"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy29"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy30"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy31"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy32"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + +int CFemmviewDoc::lua_getcircuitprops(lua_State *L) +{ + // for compatibility with 4.0 and 4.1 Lua implementation + if (((CFemmApp*) AfxGetApp())->CompatibilityMode!=0) + return ((CFemmviewDoc *)pFemmviewdoc)->old_lua_getcircuitprops(L); + + CatchNullDocument(); + CFemmviewDoc * TheDoc; // note normally thisdoc + CFemmviewView * theView; + TheDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=TheDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)TheDoc->GetNextView(pos); + + + int NumCircuits,k; + CString circuitname; + circuitname=lua_tostring(L,1); + k=-1; + + // ok we need to find the correct entry for the circuit name + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(int i=0;icircproplist[i].CircName==circuitname) + { + k=i; + i=NumCircuits; // that will break it + } + } + +// trap errors + + if(k==-1) + { + CString msg="Unknown circuit"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CComplex amps,volts,fluxlinkage; + + amps =TheDoc->circproplist[k].Amps; + volts=TheDoc->GetVoltageDrop(k); + fluxlinkage=TheDoc->GetFluxLinkage(k); + + lua_pushnumber(L,amps); + lua_pushnumber(L,volts); + lua_pushnumber(L,fluxlinkage); + + return 3; +} + +int CFemmviewDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int CFemmviewDoc::lua_refreshview(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // redraw the view + theView->OnDraw(pDC); + + return 0; +} + +int CFemmviewDoc::lua_selectline(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * pDoc; // note normally thisdoc + CFemmviewView * theView; + pDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)pDoc->GetNextView(pos); + + theView->EditAction=1; // make sure things update OK + + double mx,my; + int i,j,k,m; + + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + + +//*************** + { + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return 0; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + theView->DrawUserContour(FALSE); + return 0; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(y); + theView->DrawUserContour(FALSE); + } + } + } + } + + +//************* + return 0; +} + +int CFemmviewDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + if (EditAction=="point") + { + if (theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + if (theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) + { + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=0; + } + if (EditAction=="contour") + { + if(theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=1; + } + if (EditAction=="area") + { + if(theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + theView->EditAction=2; + } + + return 0; +} + +int CFemmviewDoc::lua_bendcontour(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + thisDoc->BendContour(lua_todouble(L,1),lua_todouble(L,2)); + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmviewDoc::lua_makeplot(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc *pDoc; + CFemmviewView *pView; + pDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + pView=(CFemmviewView *)pDoc->GetNextView(pos); + + int PlotType,npoints,FileFormat,n; + CString ToFile; + +// if ((pView->EditAction!=1) || (pDoc->contour.GetSize()==0)){ + if (pDoc->contour.GetSize()==0){ + CString outmsg; + outmsg.Format("*** Cannot create a plot;\r\n*** No contour has been defined\r\n"); + LuaConsole->ToOutput(outmsg); + return FALSE; + } + + n=lua_gettop(L); + + if(n>0) PlotType=(int) lua_todouble(L,1); + else return FALSE; + + if(n>1) npoints=(int) lua_todouble(L,2); + else npoints=pView->d_PlotPoints; + + CXYPlot xyplot; + pDoc->GetLineValues(xyplot,PlotType,npoints); + + if(n<3) + { + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (pView->OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else{ + ToFile.Format("%s",lua_tostring(L,3)); + + if(n>3){ + FileFormat=(int) lua_todouble(L,4); + if (xyplot.ToDisk(FileFormat,ToFile)==FALSE) + LuaConsole->ToOutput("*** Couldn't write data to disk\r\n"); + } + else{ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,ToFile)); + DeleteEnhMetaFile(hMeta); + } + } + + return TRUE; +} + +int CFemmviewDoc::lua_shownames(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +int CFemmviewDoc::lua_vectorplot(lua_State * L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n>0) theView->VectorPlot=(int)lua_todouble(L,1); + if (n>1) theView->VectorScaleFactor=lua_todouble(L,2); + + theView->InvalidateRect(NULL); + + return 0; +} + +/* +int CFemmviewDoc::lua_gradient(lua_State *L) +{ + // computes the gradients of the B field by differentiating + // the shape functions that are used to represent the smoothed + // B in an element. + + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + double x,y; + int i,n[3]; + double b[3],c[3],da; + CComplex dbxdx,dbxdy,dbydx,dbydy; + CElement elm; + + x=lua_todouble(L,1); + y=lua_todouble(L,2); + i=thisDoc->InTriangle(x,y); + if(i<0){ + for(i=0;i<8;i++) lua_pushnumber(L,0); + return 8; + } + + elm=thisDoc->meshelem[i]; + for(i=0;i<3;i++) n[i]=elm.p[i]; + b[0]=thisDoc->meshnode[n[1]].y - thisDoc->meshnode[n[2]].y; + b[1]=thisDoc->meshnode[n[2]].y - thisDoc->meshnode[n[0]].y; + b[2]=thisDoc->meshnode[n[0]].y - thisDoc->meshnode[n[1]].y; + c[0]=thisDoc->meshnode[n[2]].x - thisDoc->meshnode[n[1]].x; + c[1]=thisDoc->meshnode[n[0]].x - thisDoc->meshnode[n[2]].x; + c[2]=thisDoc->meshnode[n[1]].x - thisDoc->meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0])*thisDoc->LengthConv[thisDoc->LengthUnits]; + + dbxdx=0; dbxdy=0; dbydx=0; dbydy=0; + for(i=0;i<3;i++) + { + dbxdx+=elm.b1[i]*b[i]/da; + dbxdy+=elm.b1[i]*c[i]/da; + dbydx+=elm.b2[i]*b[i]/da; + dbydy+=elm.b2[i]*c[i]/da; + } + + if (thisDoc->ProblemType==PLANAR) + { + // in a source-free region, we can get a little bit + // of smoothing by enforcing the dependencies that + // are implied by the differential equation. + dbxdx=(dbxdx-dbydy)/2.; + dbydy=-dbxdx; + dbydx=(dbydx+dbxdy)/2; + dbxdy=dbydx; + } + + lua_pushnumber(L,Re(dbxdx)); + lua_pushnumber(L,Im(dbxdx)); + lua_pushnumber(L,Re(dbxdy)); + lua_pushnumber(L,Im(dbxdy)); + lua_pushnumber(L,Re(dbydx)); + lua_pushnumber(L,Im(dbydx)); + lua_pushnumber(L,Re(dbydy)); + lua_pushnumber(L,Im(dbydy)); + + return 8; +} +*/ + +int CFemmviewDoc::lua_gradient(lua_State *L) +{ + // computes the gradients of the B field by differentiating + // the shape functions that are used to represent the smoothed + // B in an element. + + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + int i; + double xo,yo,x,y,da,p0,p1,p2; + CComplex dbxdx,dbxdy,dbydx,dbydy,Mx,My; + + xo=lua_todouble(L,1); + yo=lua_todouble(L,2); + + dbxdx=0; + dbxdy=0; + dbydx=0; + dbydy=0; + + for(i=0;imeshelem.GetSize();i++) + { + thisDoc->GetMagnetization(i,Mx,My); + da=muo*thisDoc->ElmArea(i)/thisDoc->LengthConv[thisDoc->LengthUnits]; + x=Re(thisDoc->meshelem[i].ctr); + y=Im(thisDoc->meshelem[i].ctr); + + p0=PI*pow(pow(x - xo,2.) + pow(y - yo,2.),3.); + p1=(-3.*pow(x - xo,2.) + pow(y - yo,2.))*(y - yo); + p2=(x - xo)*(pow(x - xo,2.) - 3.*pow(y - yo,2.)); + dbxdx+=(da*(-(My*p1) + Mx*p2))/p0; + dbydx+=(da*(-(Mx*p1) - My*p2))/p0; + dbxdy+=(da*(-(Mx*p1) - My*p2))/p0; + dbydy+=-(da*(-(My*p1) + Mx*p2))/p0; + } + + lua_pushnumber(L,Re(dbxdx)); + lua_pushnumber(L,Im(dbxdx)); + lua_pushnumber(L,Re(dbxdy)); + lua_pushnumber(L,Im(dbxdy)); + lua_pushnumber(L,Re(dbydx)); + lua_pushnumber(L,Im(dbydx)); + lua_pushnumber(L,Re(dbydy)); + lua_pushnumber(L,Im(dbydy)); + + return 8; +} + +int CFemmviewDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int CFemmviewDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int CFemmviewDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int CFemmviewDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////// +// +// old versions for compatibility +// +//////////////////////////////////////////////////////////////////////////////////// + +int CFemmviewDoc::old_lua_lineintegral(lua_State * L) +{ + CatchNullDocument(); + int type; + CComplex *z; + z=(CComplex *)calloc(4,sizeof(CComplex)); + + type=(int) lua_todouble(L,1); + // 0- B.n + // 1 - H.t + // 2 - Cont length + // 3 - Force from stress tensor + // 4 - Torque from stress tensor + // 5 - (B.n)^2 + + if (type<0 || type >5) + { + CString msg; + msg.Format("Invalid line integral selected %d",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + thisDoc->LineIntegral(type,z); + + switch(type) + { + case 3: // force results + if (thisDoc->Frequency!=0){ + lua_pushnumber(lua,z[2].re); + lua_pushnumber(lua,0); + lua_pushnumber(lua,z[3].re); + lua_pushnumber(lua,0); + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,z[0].im); + lua_pushnumber(lua,z[1].re); + lua_pushnumber(lua,z[1].im); + free(z); + return 8; + } + else{ + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,0); + lua_pushnumber(lua,z[1].re); + lua_pushnumber(lua,0); + free(z); + return 4; + } + + + case 4: // torque results + if(thisDoc->Frequency!=0){ + lua_pushnumber(lua,z[1].re); + lua_pushnumber(lua,0); + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,z[0].im); + free(z); + return 4; + } + else + { + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,0); + lua_pushnumber(lua,0); + lua_pushnumber(lua,0); + + free(z); + return 4; + } + + default: + lua_pushnumber(lua,z[0].re); + lua_pushnumber(lua,z[0].im); + + lua_pushnumber(lua,z[1].re); + lua_pushnumber(lua,z[1].im); + + free(z); + return 4; + } + + free(z); + return 0; +} + +int CFemmviewDoc::old_lua_getpointvals(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + CFemmviewDoc * thisDoc; + CFemmviewView * theView; + + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CPointVals u; + CComplex Jtot; + + if(thisDoc->GetPointValues(px, py, u)==TRUE) + { + lua_pushnumber(L,u.A.re); + lua_pushnumber(L,u.A.im); + lua_pushnumber(L,u.B1.re); + lua_pushnumber(L,u.B1.im); + lua_pushnumber(L,u.B2.re); + lua_pushnumber(L,u.B2.im); + lua_pushnumber(L,u.c); + lua_pushnumber(L,u.E); + lua_pushnumber(L,u.H1.re); + lua_pushnumber(L,u.H1.im); + lua_pushnumber(L,u.H2.re); + lua_pushnumber(L,u.H2.im); + lua_pushnumber(L,u.Je.re); + lua_pushnumber(L,u.Je.im); + lua_pushnumber(L,u.Js.re); + lua_pushnumber(L,u.Js.im); + lua_pushnumber(L,u.mu1.re); + lua_pushnumber(L,u.mu1.im); + lua_pushnumber(L,u.mu2.re); + lua_pushnumber(L,u.mu2.im); + lua_pushnumber(L,u.Pe); + lua_pushnumber(L,u.Ph); + lua_pushnumber(L,u.ff); + return 23; + } + + return 0; +} + +int CFemmviewDoc::old_lua_blockintegral(lua_State * L) +{ + CatchNullDocument(); + int type; + type=(int) lua_todouble(L,1); + + CFemmviewDoc *thisDoc; + CFemmviewView * theView; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + CatchNullDocument(); + + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)thisDoc->GetNextView(pos); + + CComplex z; + + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (thisDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE) + { + CString msg="Cannot integrate\nNo area has been selected"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + z=thisDoc->BlockIntegral(type); + + lua_pushnumber(L,z.re); + lua_pushnumber(L,z.im); + + return 2; +} + +int CFemmviewDoc::old_lua_getcircuitprops(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * TheDoc; // note normally thisdoc + CFemmviewView * theView; + TheDoc=(CFemmviewDoc *)pFemmviewdoc; + POSITION pos; + pos=TheDoc->GetFirstViewPosition(); + theView=(CFemmviewView *)TheDoc->GetNextView(pos); + + + int NumCircuits,k; + CString circuitname; + circuitname=lua_tostring(L,1); + k=-1; + + // ok we need to find the correct entry for the circuit name + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(int i=0;icircproplist[i].CircName==circuitname) + { + k=i; + i=NumCircuits; // that will break it + } + } + + // trap errors + + if(k==-1) + { + CString msg="Unknown circuit"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + CComplex amps,volts,fluxlinkage; + + amps =TheDoc->circproplist[k].Amps; + volts=TheDoc->GetVoltageDrop(k); + fluxlinkage=TheDoc->GetFluxLinkage(k); + + lua_pushnumber(L,Re(amps)); + lua_pushnumber(L,Im(amps)); + lua_pushnumber(L,Re(volts)); + lua_pushnumber(L,Im(volts)); + lua_pushnumber(L,Re(fluxlinkage)); + lua_pushnumber(L,Im(fluxlinkage)); + + return 6; +} + +int CFemmviewDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + + + + +/////////////////////////////////////////////////////// +// Functions that provide low-level access to the mesh +/////////////////////////////////////////////////////// + +int CFemmviewDoc::lua_numnodes(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + lua_pushnumber(L,(int) thisDoc->meshnode.GetSize()); + + return 1; +} + +int CFemmviewDoc::lua_numelements(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + lua_pushnumber(L,(int) thisDoc->meshelem.GetSize()); + + return 1; +} + +int CFemmviewDoc::lua_getnode(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshnode.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshnode[k].x); + lua_pushnumber(L,thisDoc->meshnode[k].y); + + return 2; +} + +int CFemmviewDoc::lua_getelement(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshelem.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshelem[k].p[0]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[1]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[2]+1); + lua_pushnumber(L,Re(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,Im(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,thisDoc->ElmArea(k)); + lua_pushnumber(L,thisDoc->blocklist[thisDoc->meshelem[k].lbl].InGroup); + + return 7; +} + + +int CFemmviewDoc::lua_weighting(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + thisDoc->WeightingScheme=(int)lua_todouble(L,1); + thisDoc->bHasMask=FALSE; + + return 0; +} + +int CFemmviewDoc::lua_getAGEflux(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + int i,k; + CString myBdryName; + CComplex br=0; + CComplex bt=0; + double n,tta; + + myBdryName.Format("%s",lua_tostring(L,1)); + + // figure out which AGE is being asked for + i=-1; + for(k=0;kagelist.GetSize();k++) + if (thisDoc->agelist[k].BdryName==myBdryName) i=k; + + // if the requested AGE exists, roll up the flux density + // at the specified angle. Note: angle is specified in degrees + if (i>=0){ + tta=lua_todouble(L,2)*PI/180; + for(k=0;kagelist[i].nn;k++) + { + n=thisDoc->agelist[i].nh[k]; + br += thisDoc->agelist[i].brc[k]*cos(n*tta) + thisDoc->agelist[i].brs[k]*sin(n*tta); + bt += thisDoc->agelist[i].btc[k]*cos(n*tta) + thisDoc->agelist[i].bts[k]*sin(n*tta); + } + } + + lua_pushnumber(L,br); + lua_pushnumber(L,bt); + + return 2; +} + +int CFemmviewDoc::lua_gapintegral(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + CString myBdryName; + int i,k,IntegralType; + + myBdryName.Format("%s",lua_tostring(L,1)); + + // figure out which AGE is being asked for + i=-1; + for(k=0;kagelist.GetSize();k++) + if (thisDoc->agelist[k].BdryName==myBdryName) i=k; + + if (i<0){ + // Case where named AGE is not found + lua_pushnumber(L,0); + return 1; + } + + IntegralType=(int)lua_todouble(L,2); + double R = (thisDoc->agelist[i].ri + thisDoc->agelist[i].ro)/2.; + + + if (IntegralType==0) // DC torque version using harmonic solution in airgap + { + int k; + double tq=0; + + for(k=0;kagelist[i].nn;k++) + { + tq += Re(thisDoc->agelist[i].brc[k]*conj(thisDoc->agelist[i].btc[k]) + + thisDoc->agelist[i].brs[k]*conj(thisDoc->agelist[i].bts[k])); + } + tq*=(PI*R*R*thisDoc->Depth)/muo; + + if (thisDoc->Frequency!=0) tq/=2.; + + lua_pushnumber(L,tq); + + return 1; + } + +/* + if (IntegralType==0) // DC torque + { + int k; + CComplex tq=0; + + double dt=(PI/180.)*(thisDoc->agelist[i].totalArcLength/thisDoc->agelist[i].totalArcElements); + CComplex br,bt; + + for(k=0;kagelist[i].totalArcElements;k++) + { + br = thisDoc->agelist[i].br[k]; + bt = thisDoc->agelist[i].bt[k]; + // add in torque contribution for this element + tq = tq + (br*conj(bt) + conj(br)*bt)/(2.*muo)*R*dt*R*thisDoc->Depth; + } + + tq *= 360./((double) thisDoc->agelist[i].totalArcLength); + if (thisDoc->Frequency!=0) tq/=2.; + + lua_pushnumber(L,tq); + + return 1; + } +*/ + if (IntegralType==3) // 2X torque + { + int k; + CComplex tq=0; + + if (thisDoc->Frequency!=0) + { + for(k=0;kagelist[i].nn;k++) + { + tq += thisDoc->agelist[i].brc[k]*thisDoc->agelist[i].btc[k] + + thisDoc->agelist[i].brs[k]*thisDoc->agelist[i].bts[k]; + } + tq*=(PI*R*R*thisDoc->Depth)/(2.*muo); + } + + lua_pushnumber(L,tq); + + return 1; + } + + if (IntegralType==1) // DC Force + { + int k; + CComplex fx=0; + CComplex fy=0; + CComplex dfx,dfy; + + if (round(thisDoc->agelist[i].totalArcLength)==360) + { + for(k=1;kagelist[i].nn;k++) + { + + dfx = (((thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k])*conj(thisDoc->agelist[i].brs[k-1] - thisDoc->agelist[i].btc[k-1]) + + (thisDoc->agelist[i].brs[k-1] - thisDoc->agelist[i].btc[k-1])*conj(thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k]) + + (thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k])*conj(thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1]) + + (thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1])*conj(thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k]))); + + dfy = (((-thisDoc->agelist[i].brc[k] + thisDoc->agelist[i].bts[k])*conj(thisDoc->agelist[i].brs[k-1] - thisDoc->agelist[i].btc[k-1]) + + (thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1])*conj(thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k]) + + (thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k])*conj(thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1]) + + (-thisDoc->agelist[i].brs[k-1] + thisDoc->agelist[i].btc[k-1])*conj(thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k]))); + + fx+=Re(dfx); + fy+=Re(dfy); + } + fx*=thisDoc->Depth*PI*R/(4.*muo); + fy*=thisDoc->Depth*PI*R/(4.*muo); + if (thisDoc->Frequency!=0) + { + fx/=2.; + fy/=2.; + } + } + + lua_pushnumber(L,fx); + lua_pushnumber(L,fy); + + return 2; + } + + if (IntegralType==4) // 2X Force + { + int k; + CComplex fx=0; + CComplex fy=0; + CComplex dfx,dfy; + + if ((round(thisDoc->agelist[i].totalArcLength)==360) && (thisDoc->Frequency!=0)) + { + for(k=1;kagelist[i].nn;k++) + { + + dfx = (thisDoc->agelist[i].brs[k-1] - thisDoc->agelist[i].btc[k-1])*(thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k]) + + (thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1])*(thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k]); + + dfy = (thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k])*(thisDoc->agelist[i].brc[k-1] + thisDoc->agelist[i].bts[k-1]) - + (thisDoc->agelist[i].brs[k-1] - thisDoc->agelist[i].btc[k-1])*(thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k]); + + fx+=dfx; + fy+=dfy; + } + fx*=thisDoc->Depth*PI*R/(4.*muo); + fy*=thisDoc->Depth*PI*R/(4.*muo); + } + + lua_pushnumber(L,fx); + lua_pushnumber(L,fy); + + return 2; + } + + if (IntegralType==5) // Incremental Torque + { + int k; + CComplex tq=0; + + for(k=0;kagelist[i].nn;k++) + { + tq += thisDoc->agelist[i].btcPrev[k] * thisDoc->agelist[i].brc[k] + + thisDoc->agelist[i].brcPrev[k] * thisDoc->agelist[i].btc[k] + + thisDoc->agelist[i].btsPrev[k] * thisDoc->agelist[i].brs[k] + + thisDoc->agelist[i].brsPrev[k] * thisDoc->agelist[i].bts[k]; + } + tq*=(PI*R*R*thisDoc->Depth)/muo; + + lua_pushnumber(L,tq); + + return 1; + } + + if (IntegralType==6) // Incremental Force + { + int k; + CComplex fx=0; + CComplex fy=0; + CComplex dfx,dfy; + + if ((round(thisDoc->agelist[i].totalArcLength)==360) && (thisDoc->Frequency!=0)) + { + for(k=1;kagelist[i].nn;k++) + { + + dfx = (thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k])*(thisDoc->agelist[i].brsPrev[k-1] - + thisDoc->agelist[i].btcPrev[k-1]) + (thisDoc->agelist[i].brs[k-1] - + thisDoc->agelist[i].btc[k-1])*(thisDoc->agelist[i].brsPrev[k] + thisDoc->agelist[i].btcPrev[k]) + + (thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k])*(thisDoc->agelist[i].brcPrev[k-1] + + thisDoc->agelist[i].btsPrev[k-1]) + (thisDoc->agelist[i].brc[k-1] + + thisDoc->agelist[i].bts[k-1])*(thisDoc->agelist[i].brcPrev[k] - thisDoc->agelist[i].btsPrev[k]); + + dfy = (thisDoc->agelist[i].brsPrev[k] + thisDoc->agelist[i].btcPrev[k])*(thisDoc->agelist[i].brc[k-1] + + thisDoc->agelist[i].bts[k-1]) - (thisDoc->agelist[i].brsPrev[k-1] - + thisDoc->agelist[i].btcPrev[k-1])*(thisDoc->agelist[i].brc[k] - thisDoc->agelist[i].bts[k]) + + (thisDoc->agelist[i].brs[k] + thisDoc->agelist[i].btc[k])*(thisDoc->agelist[i].brcPrev[k-1] + + thisDoc->agelist[i].btsPrev[k-1]) - (thisDoc->agelist[i].brs[k-1] - + thisDoc->agelist[i].btc[k-1])*(thisDoc->agelist[i].brcPrev[k] - thisDoc->agelist[i].btsPrev[k]); + + fx+=dfx; + fy+=dfy; + } + fx*=thisDoc->Depth*PI*R/(2.*muo); + fy*=thisDoc->Depth*PI*R/(2.*muo); + } + + lua_pushnumber(L,fx); + lua_pushnumber(L,fy); + + return 2; + } + + if (IntegralType==2) // (Time-Average) Stored Energy + { + int k,n; + CComplex W=0; + + double Ri = thisDoc->agelist[i].ri/R; + double Ro = thisDoc->agelist[i].ro/R; + double dr = R*(Ro-Ri); + + for(k=0;kagelist[i].nn;k++) + { + n=thisDoc->agelist[i].nh[k]; + + if (n!=0) + W+= (thisDoc->agelist[i].brs[k]*thisDoc->agelist[i].brs[k] + + thisDoc->agelist[i].brc[k]*thisDoc->agelist[i].brc[k] + + thisDoc->agelist[i].bts[k]*thisDoc->agelist[i].bts[k] + + thisDoc->agelist[i].btc[k]*thisDoc->agelist[i].btc[k])*dr; + else + W+=2*dr*thisDoc->agelist[i].btc[k]*thisDoc->agelist[i].btc[k]; + } + W=Re(W)*(PI*R*thisDoc->Depth)/(2.*muo); + if (thisDoc->Frequency!=0) W/=2; + + lua_pushnumber(L,W); + + return 1; + } + + + return 0; +} + +int CFemmviewDoc::lua_getgapa(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + int i,k; + CString myBdryName; + CComplex ac=0; + double n,tta,R; + + myBdryName.Format("%s",lua_tostring(L,1)); + + // figure out which AGE is being asked for + i=-1; + for(k=0;kagelist.GetSize();k++) + if (thisDoc->agelist[k].BdryName==myBdryName) i=k; + + // if the requested AGE exists, roll up the flux density + // at the specified angle. Note: angle is specified in degrees + if (i>=0){ + R=(thisDoc->agelist[i].ri+thisDoc->agelist[i].ro)/2.; + tta=lua_todouble(L,2)*PI/180; + for(k=0;kagelist[i].nn;k++) + { + n=thisDoc->agelist[i].nh[k]; + if (n==0) ac+=thisDoc->agelist[i].aco; + else + ac += (R/n)*(-thisDoc->agelist[i].brs[k]*cos(n*tta) + thisDoc->agelist[i].brc[k]*sin(n*tta)); + } + } + + lua_pushnumber(L,ac); + + return 1; +} + +int CFemmviewDoc::lua_getgapharmonics(lua_State *L) +{ + CatchNullDocument(); + CFemmviewDoc * thisDoc; + thisDoc=(CFemmviewDoc *)pFemmviewdoc; + + CString myBdryName; + int i,k; + + if (lua_gettop(L)==0) return 0; + + // figure out which AGE is being asked for + myBdryName.Format("%s",lua_tostring(L,1)); + for(k=0,i=-1;kagelist.GetSize();k++) + if (thisDoc->agelist[k].BdryName==myBdryName) i=k; + + if (i<0) return 0; // no AGE here by that name; + + // if _just_ the name is specified, return the number of the highest harmonic + if (lua_gettop(L)==1) + { + k=thisDoc->agelist[i].nn; + if (k==0) lua_pushnumber(L,0); + else lua_pushnumber(L,thisDoc->agelist[i].nh[k-1]); + return 1; + } + + // otherwise, give all the magnitudes of the harmonic; + if (thisDoc->agelist[i].nn==0) return 0; // error case + + double n = lua_todouble(L,2); + CComplex acc=0; + CComplex acs=0; + CComplex brs=0; + CComplex brc=0; + CComplex bts=0; + CComplex btc=0; + + if (n<0) return 0; + for(k=0;kagelist[i].nn;k++) + { + if (thisDoc->agelist[i].nh[k]==n) break; + } + if (kagelist[i].nn) + { + if (n==0) + { + acc=thisDoc->agelist[i].aco; + acs=0; + } + else{ + double R = (thisDoc->agelist[i].ri+thisDoc->agelist[i].ro)/2.; + acc = - (R/n)*thisDoc->agelist[i].brs[k]; + acs = (R/n)*thisDoc->agelist[i].brc[k]; + brc = thisDoc->agelist[i].brc[k]; + brs = thisDoc->agelist[i].brs[k]; + btc = thisDoc->agelist[i].btc[k]; + bts = thisDoc->agelist[i].bts[k]; + } + } + + lua_pushnumber(L,acc); + lua_pushnumber(L,acs); + lua_pushnumber(L,brc); + lua_pushnumber(L,brs); + lua_pushnumber(L,btc); + lua_pushnumber(L,bts); + + return 6; +} \ No newline at end of file diff --git a/femm/fullmatrix.cpp b/femm/fullmatrix.cpp new file mode 100644 index 0000000..c4e2634 --- /dev/null +++ b/femm/fullmatrix.cpp @@ -0,0 +1,186 @@ +#include"stdafx.h" +#include +#include"fullmatrix.h" + +CFullMatrix::CFullMatrix() +{ + n=0; + M=NULL; + b=NULL; +} + +CFullMatrix::CFullMatrix(int d) +{ + n=0; + M=NULL; + b=NULL; + Create(d); +} + +CFullMatrix::~CFullMatrix() +{ + if(n==0) return; + + int i; + for(i=0;ifabs(max)) + { + max=M[j][i]; + q=j; + } + if(max==0) return FALSE; + z=M[i];M[i]=M[q];M[q]=z; + f=b[i];b[i]=b[q];b[q]=f; + for(j=i+1;j=0;i--) + { + for(j=n-1,f=0;j>i;j--) + f+=M[i][j]*b[j]; + b[i]=(b[i]-f)/M[i][i]; + } + return TRUE; +} + +CComplexFullMatrix::CComplexFullMatrix() +{ + n=0; + M=NULL; + b=NULL; +} + +CComplexFullMatrix::CComplexFullMatrix(int d) +{ + n=0; + M=NULL; + b=NULL; + Create(d); +} + +CComplexFullMatrix::~CComplexFullMatrix() +{ + if(n==0) return; + + int i; + for(i=0;iabs(max)) + { + max=M[j][i]; + q=j; + } + if(max==0) return FALSE; + z=M[i];M[i]=M[q];M[q]=z; + f=b[i];b[i]=b[q];b[q]=f; + for(j=i+1;j=0;i--) + { + for(j=n-1,f=0;j>i;j--) + f+=M[i][j]*b[j]; + b[i]=(b[i]-f)/M[i][i]; + } + return TRUE; +} + diff --git a/femm/fullmatrix.h b/femm/fullmatrix.h new file mode 100644 index 0000000..d6c94e4 --- /dev/null +++ b/femm/fullmatrix.h @@ -0,0 +1,42 @@ + +class CFullMatrix{ + + public: + + // data members + double **M; // Matrix on LHS + double *b; // vector on RHS + long n; // dimension of the matrix + + // member functions + CFullMatrix(); + CFullMatrix(int d); + ~CFullMatrix(); + void Wipe(); + BOOL Create(int d); + BOOL GaussSolve(); + + private: + +}; + +class CComplexFullMatrix{ + + public: + + // data members + CComplex **M; // Matrix on LHS + CComplex *b; // vector on RHS + int n; // dimension of the matrix + + // member functions + CComplexFullMatrix(); + CComplexFullMatrix(int d); + ~CComplexFullMatrix(); + void Wipe(); + BOOL Create(int d); + BOOL GaussSolve(); + + private: + +}; \ No newline at end of file diff --git a/femm/hd_BdryDlg.cpp b/femm/hd_BdryDlg.cpp new file mode 100644 index 0000000..ab35f3b --- /dev/null +++ b/femm/hd_BdryDlg.cpp @@ -0,0 +1,151 @@ +// BdryDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hd_BdryDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCBdryDlg dialog + + +hdCBdryDlg::hdCBdryDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCBdryDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCBdryDlg) + m_BdryName = _T(""); + m_qs = 0.0; + m_beta = 0.0; + m_htc = 0.0; + m_To2 = 0.0; + m_To1 = 0.0; + m_Tset = 0.0; + //}}AFX_DATA_INIT +} + + +void hdCBdryDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCBdryDlg) + DDX_Control(pDX, IDC_HD_BDRYFORMAT, m_BdryFormat); + DDX_Text(pDX, IDC_HD_BDRYNAME, m_BdryName); + DDX_Text(pDX, IDC_HD_QS, m_qs); + DDX_Text(pDX, IDC_HD_BETA, m_beta); + DDX_Text(pDX, IDC_HD_HTC, m_htc); + DDX_Text(pDX, IDC_HD_TINF2, m_To2); + DDX_Text(pDX, IDC_HD_TINF1, m_To1); + DDX_Text(pDX, IDC_HD_TBDRY, m_Tset); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_TBDRY, m_IDC_Tset); + DDX_Control(pDX, IDC_HD_QS, m_IDC_QS); + DDX_Control(pDX, IDC_HD_BDRYNAME, m_IDC_BDRYNAME); + DDX_Control(pDX, IDC_HD_BETA, m_IDC_beta); + DDX_Control(pDX, IDC_HD_HTC, m_IDC_htc); + DDX_Control(pDX, IDC_HD_TINF1, m_IDC_To1); + DDX_Control(pDX, IDC_HD_TINF2, m_IDC_To2); +} + + +BEGIN_MESSAGE_MAP(hdCBdryDlg, CDialog) + //{{AFX_MSG_MAP(hdCBdryDlg) + ON_CBN_SELCHANGE(IDC_HD_BDRYFORMAT, OnSelchangeBdryformat) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCBdryDlg message handlers + +void hdCBdryDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + + CFont symbfont; + +// Dialog Data + //{{AFX_DATA(hdCBdryDlg) + enum { IDD = IDD_HD_BDRYDLG }; + CComboBox m_BdryFormat; + CString m_BdryName; + double m_qs; + double m_beta; + double m_htc; + double m_To2; + double m_To1; + double m_Tset; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCBdryDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCBdryDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeBdryformat(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_IDC_Tset, m_IDC_To1, m_IDC_QS, m_IDC_BDRYNAME; + CLuaEdit m_IDC_beta, m_IDC_htc, m_IDC_To2; + +}; diff --git a/femm/hd_CircProp.cpp b/femm/hd_CircProp.cpp new file mode 100644 index 0000000..adc1d0f --- /dev/null +++ b/femm/hd_CircProp.cpp @@ -0,0 +1,102 @@ +// CircProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCCircProp dialog + + +hdCCircProp::hdCCircProp(CWnd* pParent /*=NULL*/) + : CDialog(hdCCircProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCCircProp) + m_circname = _T(""); + m_v = 0.0; + m_q = 0.0; + //}}AFX_DATA_INIT +} + + +void hdCCircProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCCircProp) + DDX_Text(pDX, IDC_HD_CIRCNAME, m_circname); + DDX_Text(pDX, IDC_HD_V, m_v); + DDX_Text(pDX, IDC_HD_Q, m_q); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_CIRCNAME, m_idc_circname); + DDX_Control(pDX, IDC_HD_V, m_idc_v); + DDX_Control(pDX, IDC_HD_Q, m_idc_q); +} + + +BEGIN_MESSAGE_MAP(hdCCircProp, CDialog) + //{{AFX_MSG_MAP(hdCCircProp) + ON_BN_CLICKED(IDC_HD_RADIOAMP, OnRadioamp) + ON_BN_CLICKED(IDC_HD_RADIOVOLT, OnRadiovolt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCCircProp message handlers + +void hdCCircProp::OnRadioamp() +{ + m_circtype=0; + m_idc_q.EnableWindow(TRUE); + m_idc_v.EnableWindow(FALSE); +} + +void hdCCircProp::OnRadiovolt() +{ + m_circtype=1; + m_idc_q.EnableWindow(FALSE); + m_idc_v.EnableWindow(TRUE); +} + +BOOL hdCCircProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + SetEm=IDC_HD_RADIOAMP; + if(m_circtype==1){ + SetEm=IDC_HD_RADIOVOLT; + OnRadiovolt(); + } + else OnRadioamp(); + + CheckRadioButton( + IDC_HD_RADIOVOLT,// identifier of first radio button in group + IDC_HD_RADIOAMP, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hdCCircProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + +// Dialog Data + //{{AFX_DATA(hdCCircProp) + enum { IDD = IDD_HD_CIRCPROP }; + CString m_circname; + double m_v; + double m_q; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCCircProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCCircProp) + afx_msg void OnRadioamp(); + afx_msg void OnRadiovolt(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + + CLuaEdit m_idc_circname; + CLuaEdit m_idc_v; + CLuaEdit m_idc_q; +}; diff --git a/femm/hd_MatDlg.cpp b/femm/hd_MatDlg.cpp new file mode 100644 index 0000000..c7e0f5f --- /dev/null +++ b/femm/hd_MatDlg.cpp @@ -0,0 +1,155 @@ +// MatDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hd_MatDlg.h" +#include "KCurve.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCMatDlg dialog + + +hdCMatDlg::hdCMatDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCMatDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCMatDlg) + m_BlockName = _T(""); + m_Kx = 1.0; + m_Ky = 1.0; + m_qv = 0.0; + m_Kt = 3; + m_mu1label = _T(""); + m_mu2label = _T(""); + //}}AFX_DATA_INIT + + m_nlflag=FALSE; + m_npts=0; +} + + +void hdCMatDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCMatDlg) + DDX_Control(pDX, IDC_EDITCURVE, m_editcurve); + DDX_Control(pDX, IDC_NLCOMBO, m_nlcurve); + DDX_Text(pDX, IDC_HD_BLOCKNAME, m_BlockName); + DDX_Text(pDX, IDC_HD_EX, m_Kx); + DDX_Text(pDX, IDC_HD_EY, m_Ky); + DDX_Text(pDX, IDC_HD_KT, m_Kt); + DDX_Text(pDX, IDC_HD_QV, m_qv); + DDX_Text(pDX, IDC_HD_MU1LABEL, m_mu1label); + DDX_Text(pDX, IDC_HD_MU2LABEL, m_mu2label); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_BLOCKNAME, m_IDC_BlockName); + DDX_Control(pDX, IDC_HD_EX, m_IDC_EX); + DDX_Control(pDX, IDC_HD_EY, m_IDC_EY); + DDX_Control(pDX, IDC_HD_QV, m_IDC_QV); + DDX_Control(pDX, IDC_HD_KT, m_IDC_KT); +} + + +BEGIN_MESSAGE_MAP(hdCMatDlg, CDialog) + //{{AFX_MSG_MAP(hdCMatDlg) + ON_BN_CLICKED(IDC_EDITCURVE, OnEditCurve) + ON_CBN_SELCHANGE(IDC_NLCOMBO, OnSelchangeNlcombo) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCMatDlg message handlers + +BOOL hdCMatDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + symbfont.CreateFont(0, 0, 0, 0, FW_BOLD, TRUE, 0, 0, + SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, DEFAULT_PITCH | FF_DECORATIVE, "Symbol"); + + if (m_npts==0) m_nlcurve.SetCurSel(0); + else m_nlcurve.SetCurSel(1); + + OnSelchangeNlcombo(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hdCMatDlg::OnOK() +{ + UpdateData(); + for(int nn=0;nn0)) + { + if(m_npts==1) m_nlflag=FALSE; + m_Kx=Im(m_Kn[0]); + m_Ky=m_Kx; + } + + if (m_nlflag==FALSE) m_npts=0; + + UpdateData(FALSE); + + CDialog::OnOK(); +} + + +void hdCMatDlg::OnSelchangeNlcombo() +{ + m_nlflag=m_nlcurve.GetCurSel(); + + if(m_nlflag==TRUE) + { + m_IDC_EX.EnableWindow( FALSE ); + m_IDC_EY.EnableWindow( FALSE ); + m_editcurve.EnableWindow( TRUE ); + } + else{ + m_IDC_EX.EnableWindow( TRUE ); + m_IDC_EY.EnableWindow( TRUE ); + m_editcurve.EnableWindow( FALSE ); + } +} + +void hdCMatDlg::OnEditCurve() +{ + CTKData dlg; + + int k; + + dlg.T.RemoveAll(); + dlg.K.RemoveAll(); + dlg.npts=m_npts; + + for(k=0;k128) m_npts=128; + for(k=0;k namelist; + + CFont symbfont; + CFont bfont; + +// Dialog Data + //{{AFX_DATA(hdCMatDlg) + enum { IDD = IDD_HD_MATDLG }; + CButton m_editcurve; + CComboBox m_nlcurve; + CString m_BlockName; + double m_Kx; + double m_Ky; + double m_Kt; + double m_qv; + CString m_mu1label; + CString m_mu2label; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCMatDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCMatDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnEditCurve(); + afx_msg void OnSelchangeNlcombo(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_EX, m_IDC_EY, m_IDC_BlockName, m_IDC_QV, m_IDC_KT; + +}; diff --git a/femm/hd_NodeProp.cpp b/femm/hd_NodeProp.cpp new file mode 100644 index 0000000..22549b5 --- /dev/null +++ b/femm/hd_NodeProp.cpp @@ -0,0 +1,110 @@ +// NodeProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hd_NodeProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCNodeProp dialog + + +hdCNodeProp::hdCNodeProp(CWnd* pParent /*=NULL*/) + : CDialog(hdCNodeProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCNodeProp) + m_nodename = _T(""); + m_qp = 0.0; + m_vp = 0.0; + //}}AFX_DATA_INIT +} + + +void hdCNodeProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCNodeProp) + DDX_Text(pDX, IDC_HD_NODENAME, m_nodename); + DDX_Text(pDX, IDC_HD_QP, m_qp); + DDX_Text(pDX, IDC_HD_VP, m_vp); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_VP, m_IDC_vp); + DDX_Control(pDX, IDC_HD_QP, m_IDC_qp); + DDX_Control(pDX, IDC_HD_NODENAME, m_IDC_nodename); +} + + +BEGIN_MESSAGE_MAP(hdCNodeProp, CDialog) + //{{AFX_MSG_MAP(hdCNodeProp) + ON_BN_CLICKED(IDC_HD_SETA, OnSetA) + ON_BN_CLICKED(IDC_HD_SETI, OnSetI) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCNodeProp message handlers + +void hdCNodeProp::OnSetA() +{ + // TODO: Add your control notification handler code here + m_IDC_qp.EnableWindow(FALSE); + m_IDC_vp.EnableWindow(TRUE); + SetDlgItemText(IDC_HD_QP,"0"); m_qp=0; +} + +void hdCNodeProp::OnSetI() +{ + // TODO: Add your control notification handler code here + m_IDC_vp.EnableWindow(FALSE); + m_IDC_qp.EnableWindow(TRUE); + SetDlgItemText(IDC_HD_VP,"0"); m_vp=0; +} + +BOOL hdCNodeProp::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int SetEm; + + if(m_qp!=0){ + SetEm=IDC_HD_SETI; + + m_IDC_vp.EnableWindow(FALSE); + m_IDC_qp.EnableWindow(TRUE); + } + else{ + SetEm=IDC_HD_SETA; + m_IDC_qp.EnableWindow(FALSE); + m_IDC_vp.EnableWindow(TRUE); + } + + + CheckRadioButton( + IDC_HD_SETA,// identifier of first radio button in group + IDC_HD_SETI, // identifier of last radio button in group + SetEm // identifier of radio button to select + ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hdCNodeProp::OnOK() +{ + UpdateData(); + for(int nn=0;nn namelist; + CFont bfont; + +// Dialog Data + //{{AFX_DATA(hdCNodeProp) + enum { IDD = IDD_HD_NODEPROP }; + CString m_nodename; + double m_qp; + double m_vp; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCNodeProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCNodeProp) + afx_msg void OnSetA(); + afx_msg void OnSetI(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_vp, m_IDC_qp, m_IDC_nodename; +}; diff --git a/femm/hd_OpArcSegDlg.cpp b/femm/hd_OpArcSegDlg.cpp new file mode 100644 index 0000000..3314e2c --- /dev/null +++ b/femm/hd_OpArcSegDlg.cpp @@ -0,0 +1,86 @@ +// OpArcSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_OpArcSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCOpArcSegDlg dialog + + +hdCOpArcSegDlg::hdCOpArcSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCOpArcSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCOpArcSegDlg) + m_MaxSeg = 0.0; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void hdCOpArcSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCOpArcSegDlg) + DDX_Control(pDX, IDC_HD_ARCSEG_COND, m_arcsegcond); + DDX_Control(pDX, IDC_HD_ARCSEGBDRY2, m_ArcSegBdry); + DDX_Text(pDX, IDC_HD_MAXSEG2, m_MaxSeg); + DDX_Check(pDX, IDC_HD_ARCHIDE, m_hide); + DDX_Text(pDX, IDC_HD_ARCGRP, m_ingroup); + DDV_MinMaxDouble(pDX, m_MaxSeg, 1.e-002, 10.); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_ARCGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_HD_MAXSEG2, m_IDC_MaxSeg); +} + + +BEGIN_MESSAGE_MAP(hdCOpArcSegDlg, CDialog) + //{{AFX_MSG_MAP(hdCOpArcSegDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCOpArcSegDlg message handlers + +BOOL hdCOpArcSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ArcSegBdry.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_arcsegcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(hdCOpArcSegDlg) + enum { IDD = IDD_HD_OPARCSEGDLG }; + CComboBox m_arcsegcond; + CComboBox m_ArcSegBdry; + double m_MaxSeg; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCOpArcSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCOpArcSegDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_MaxSeg; +}; diff --git a/femm/hd_OpBlkDlg.cpp b/femm/hd_OpBlkDlg.cpp new file mode 100644 index 0000000..9429cc6 --- /dev/null +++ b/femm/hd_OpBlkDlg.cpp @@ -0,0 +1,118 @@ +// OpBlkDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_OpBlkDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCOpBlkDlg dialog + + +hdCOpBlkDlg::hdCOpBlkDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCOpBlkDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCOpBlkDlg) + m_sidelength = 0.0; + m_ingroup = 0; + m_isexternal = FALSE; + m_isdefault = FALSE; + //}}AFX_DATA_INIT + ProblemType=0; +} + + +void hdCOpBlkDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCOpBlkDlg) + DDX_Control(pDX, IDC_HD_AUTOMESHCHECK, m_automesh); + DDX_Control(pDX, IDC_HD_ACKBLK, m_ackblk); + DDX_Check(pDX, IDC_HD_EXTERNAL, m_isexternal); + DDX_Check(pDX, IDC_HD_ISDEFAULT, m_isdefault); + DDX_Text(pDX, IDC_HD_SIDELENGTH, m_sidelength); + DDX_Text(pDX, IDC_HD_BLKGROUP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_SIDELENGTH, m_IDC_sidelength); + DDX_Control(pDX, IDC_HD_BLKGROUP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(hdCOpBlkDlg, CDialog) + //{{AFX_MSG_MAP(hdCOpBlkDlg) + ON_CBN_SELCHANGE(IDC_HD_ACKBLK, OnSelchangeAckblk) + ON_BN_CLICKED(IDC_HD_AUTOMESHCHECK, OnAutomeshcheck) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCOpBlkDlg message handlers + +void hdCOpBlkDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackblk.GetCurSel(); + CDialog::OnOK(); +} + +BOOL hdCOpBlkDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CArray &blockproplist=*pblockproplist; + CArray &circproplist=*pcircproplist; + + int i; + + // TODO: Add extra initialization here + m_ackblk.AddString(""); + m_ackblk.AddString(""); + for(i=0;iEnableWindow(ProblemType); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hdCOpBlkDlg::OnSelchangeAckblk() +{ + CArray &blockproplist=*pblockproplist; + BOOL bEnable=FALSE; + + cursel=m_ackblk.GetCurSel(); +} + +void hdCOpBlkDlg::OnAutomeshcheck() +{ + // TODO: Add your control notification handler code here + int k=m_automesh.GetCheck(); + if (k==TRUE) k=FALSE; + else k=TRUE; + + SendDlgItemMessage( + IDC_HD_SIDELENGTH, // identifier of control + WM_ENABLE, // message to send + (WPARAM) k, // first message parameter + (LPARAM) 0 // second message parameter + ); + if (k==FALSE){ + m_sidelength=0; + SetDlgItemText(IDC_HD_SIDELENGTH, "0" ); + } +} diff --git a/femm/hd_OpBlkDlg.h b/femm/hd_OpBlkDlg.h new file mode 100644 index 0000000..44148f8 --- /dev/null +++ b/femm/hd_OpBlkDlg.h @@ -0,0 +1,50 @@ +// hd_OpBlkDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hdCOpBlkDlg dialog + +class hdCOpBlkDlg : public CDialog +{ +// Construction +public: + hdCOpBlkDlg(CWnd* pParent = NULL); // standard constructor + int cursel; + int ProblemType; + CArray *pblockproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(hdCOpBlkDlg) + enum { IDD = IDD_HD_OPBLKDLG }; + CButton m_automesh; + CComboBox m_ackblk; + BOOL m_isexternal; + BOOL m_isdefault; + double m_sidelength; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCOpBlkDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCOpBlkDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAckblk(); + afx_msg void OnAutomeshcheck(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_sidelength; + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/hd_OpNodeDlg.cpp b/femm/hd_OpNodeDlg.cpp new file mode 100644 index 0000000..71e20ff --- /dev/null +++ b/femm/hd_OpNodeDlg.cpp @@ -0,0 +1,80 @@ +// OpNodeDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_OpNodeDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCOpNodeDlg dialog + + +hdCOpNodeDlg::hdCOpNodeDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCOpNodeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCOpNodeDlg) + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void hdCOpNodeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCOpNodeDlg) + DDX_Control(pDX, IDC_HD_NODE_COND, m_nodecond); + DDX_Control(pDX, IDC_HD_ACKNODE, m_acknode); + DDX_Text(pDX, IDC_HD_PTGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_PTGRP, m_IDC_ingroup); +} + + +BEGIN_MESSAGE_MAP(hdCOpNodeDlg, CDialog) + //{{AFX_MSG_MAP(hdCOpNodeDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCOpNodeDlg message handlers + +BOOL hdCOpNodeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &nodeproplist=*pnodeproplist; + + int i; + + // TODO: Add extra initialization here + m_acknode.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_nodecond.AddString(""); + for(i=0;i *pnodeproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(hdCOpNodeDlg) + enum { IDD = IDD_HD_OPNODEDLG }; + CComboBox m_nodecond; + CComboBox m_acknode; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCOpNodeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCOpNodeDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup; +}; diff --git a/femm/hd_OpSegDlg.cpp b/femm/hd_OpSegDlg.cpp new file mode 100644 index 0000000..7fc9aed --- /dev/null +++ b/femm/hd_OpSegDlg.cpp @@ -0,0 +1,126 @@ +// OpSegDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_OpSegDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCOpSegDlg dialog + + +hdCOpSegDlg::hdCOpSegDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCOpSegDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCOpSegDlg) + m_linemeshsize = 0.0; + m_automesh = FALSE; + m_hide = FALSE; + m_ingroup = 0; + //}}AFX_DATA_INIT +} + + +void hdCOpSegDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCOpSegDlg) + DDX_Control(pDX, IDC_HD_SEG_COND, m_segcond); + DDX_Control(pDX, IDC_HD_ACKSEG, m_ackseg); + DDX_Text(pDX, IDC_HD_LINEMESHSIZE, m_linemeshsize); + DDX_Check(pDX, IDC_HD_AUTOMESH, m_automesh); + DDX_Check(pDX, IDC_HD_SEGHIDE, m_hide); + DDX_Text(pDX, IDC_HD_SEGGRP, m_ingroup); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_SEGGRP, m_IDC_ingroup); + DDX_Control(pDX, IDC_HD_LINEMESHSIZE, m_IDC_linemeshsize); +} + + +BEGIN_MESSAGE_MAP(hdCOpSegDlg, CDialog) + //{{AFX_MSG_MAP(hdCOpSegDlg) + ON_BN_CLICKED(IDC_HD_AUTOMESH, OnAutomesh) + ON_CBN_SELCHANGE(IDC_HD_ACKSEG, OnSelchangeAckseg) + ON_CBN_SELCHANGE(IDC_HD_SEG_COND, OnSelchangeSegCond) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCOpSegDlg message handlers + +void hdCOpSegDlg::OnOK() +{ + // TODO: Add extra validation here + cursel=m_ackseg.GetCurSel(); + condsel=m_segcond.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL hdCOpSegDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CArray &lineproplist=*plineproplist; + int i; + + // TODO: Add extra initialization here + m_ackseg.AddString(""); + for(i=0;i &circproplist=*pcircproplist; + m_segcond.AddString(""); + for(i=0;i *plineproplist; + CArray *pcircproplist; + +// Dialog Data + //{{AFX_DATA(hdCOpSegDlg) + enum { IDD = IDD_HD_OPSEGDLG }; + CComboBox m_segcond; + CComboBox m_ackseg; + double m_linemeshsize; + BOOL m_automesh; + BOOL m_hide; + int m_ingroup; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCOpSegDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCOpSegDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnAutomesh(); + afx_msg void OnSelchangeAckseg(); + afx_msg void OnSelchangeSegCond(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_ingroup, m_IDC_linemeshsize; +}; diff --git a/femm/hd_PtProp.cpp b/femm/hd_PtProp.cpp new file mode 100644 index 0000000..b64715b --- /dev/null +++ b/femm/hd_PtProp.cpp @@ -0,0 +1,423 @@ +// PtProp.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_PtProp.h" +#include "hd_NodeProp.h" +#include "hd_MatDlg.h" +#include "hd_BdryDlg.h" +#include "hd_CircProp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCPtProp dialog + + +hdCPtProp::hdCPtProp(CWnd* pParent /*=NULL*/) + : CDialog(hdCPtProp::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCPtProp) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void hdCPtProp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCPtProp) + DDX_Control(pDX, IDC_NAME_LIST, m_namelist); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(hdCPtProp, CDialog) + //{{AFX_MSG_MAP(hdCPtProp) + ON_BN_CLICKED(IDC_ADD_PROP, OnAddProp) + ON_BN_CLICKED(IDC_DEL_PROP, OnDelProp) + ON_BN_CLICKED(IDC_MOD_PROP, OnModProp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCPtProp message handlers + +void hdCPtProp::OnAddProp() +{ + + // Code to deal with adding a Point Property. + if (PropType==0){ + CPointProp PProp; + CArray &nodeproplist=*pnodeproplist; + hdCNodeProp zDlg; + + for(int nn=0;nn &circproplist=*pcircproplist; + hdCCircProp zDlg; + for(int nn=0;nn &lineproplist=*plineproplist; + hdCBdryDlg zDlg; + for(int nn=0;nn &blockproplist=*pblockproplist; + hdCMatDlg zDlg; + for(int nn=0;nn &nodeproplist=*pnodeproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (nodeproplist.GetSize()!=0)) + { + nodeproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (circproplist.GetSize()!=0)) + { + circproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (lineproplist.GetSize()!=0)) + { + lineproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + int k=m_namelist.GetCurSel(); + if((k!=CB_ERR) && (blockproplist.GetSize()!=0)) + { + blockproplist.RemoveAt(k); + m_namelist.DeleteString(k); + m_namelist.SetCurSel(0); + } + } +} + +void hdCPtProp::OnModProp() +{ + // TODO: Add your control notification handler code here + if (PropType==0){ + CArray &nodeproplist=*pnodeproplist; + hdCNodeProp zDlg; + + if (nodeproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_vp=nodeproplist[k].T; + zDlg.m_qp=nodeproplist[k].qp; + zDlg.m_nodename=nodeproplist[k].PointName; + + for(int nn=0;nn &circproplist=*pcircproplist; + + if (circproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + hdCCircProp zDlg; + + zDlg.m_circname = circproplist[k].CircName; + zDlg.m_circtype = circproplist[k].CircType; + zDlg.m_q = circproplist[k].q; + zDlg.m_v = circproplist[k].T; + for(int nn=0;nn &lineproplist=*plineproplist; + hdCBdryDlg zDlg; + + if (lineproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_Tset = lineproplist[k].Tset; + zDlg.m_qs = lineproplist[k].qs; + zDlg.m_beta = lineproplist[k].beta; + zDlg.m_htc = lineproplist[k].h; + zDlg.m_To1 = lineproplist[k].Tinf; + zDlg.m_To2 = lineproplist[k].Tinf; + zDlg.BdryFormat=lineproplist[k].BdryFormat; + zDlg.m_BdryName=lineproplist[k].BdryName; + for(int nn=0;nn &blockproplist=*pblockproplist; + hdCMatDlg zDlg; + + if (blockproplist.GetSize()==0) return; + int k=m_namelist.GetCurSel(); + if (k==CB_ERR) return; + + zDlg.m_Kx=blockproplist[k].Kx; + zDlg.m_Ky=blockproplist[k].Ky; + zDlg.m_Kt=blockproplist[k].Kt; + zDlg.m_qv=blockproplist[k].qv; + zDlg.m_BlockName=blockproplist[k].BlockName; + zDlg.m_npts=blockproplist[k].npts; + for(int i=0;i &nodeproplist=*pnodeproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==1){ + CArray &lineproplist=*plineproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==2){ + CArray &blockproplist=*pblockproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + if (PropType==3){ + CArray &circproplist=*pcircproplist; + for(i=0;i0) m_namelist.SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/hd_PtProp.h b/femm/hd_PtProp.h new file mode 100644 index 0000000..ff7c24c --- /dev/null +++ b/femm/hd_PtProp.h @@ -0,0 +1,48 @@ +// hd_PtProp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hdCPtProp dialog + +class hdCPtProp : public CDialog +{ +// Construction +public: + hdCPtProp(CWnd* pParent = NULL); // standard constructor + + // variables CPrProp needs; + int PropType; + int ProblemType; + CArray *pnodeproplist; + CArray *plineproplist; + CArray *pblockproplist; + CArray *pcircproplist; + + +// Dialog Data + //{{AFX_DATA(hdCPtProp) + enum { IDD = IDD_PTPROP }; + CComboBox m_namelist; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCPtProp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCPtProp) + afx_msg void OnAddProp(); + afx_msg void OnDelProp(); + afx_msg void OnModProp(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/hd_libdlg.cpp b/femm/hd_libdlg.cpp new file mode 100644 index 0000000..9f7b5ff --- /dev/null +++ b/femm/hd_libdlg.cpp @@ -0,0 +1,1220 @@ +// treetestDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hdrawDoc.h" +#include "hd_MatDlg.h" +#include "hd_libdlg.h" +#include "libfolderinfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hdCLibDlg dialog + + +// CLuaConsoleDlg dialog + +hdCLibDlg::hdCLibDlg(CWnd* pParent /*=NULL*/) + : CResizableDialog(hdCLibDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCLibDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + // m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void hdCLibDlg::DoDataExchange(CDataExchange* pDX) +{ + CResizableDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCLibDlg) + DDX_Control(pDX, IDC_MYLIST, m_mylist); + DDX_Control(pDX, IDC_MYTREE, m_mytree); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(hdCLibDlg, CResizableDialog) + //{{AFX_MSG_MAP(hdCLibDlg) + ON_WM_QUERYDRAGICON() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYTREE, OnBegindragMytree) + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + ON_NOTIFY(TVN_BEGINDRAG, IDC_MYLIST, OnBegindragMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYLIST, OnRclickMylist) + ON_NOTIFY(NM_RCLICK, IDC_MYTREE, OnRclickMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYTREE, OnDblclkMytree) + ON_NOTIFY(NM_DBLCLK, IDC_MYLIST, OnDblclkMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYLIST, OnKeydownMylist) + ON_NOTIFY(TVN_KEYDOWN, IDC_MYTREE, OnKeydownMytree) + ON_WM_TIMER() + //}}AFX_MSG_MAP + ON_COMMAND(ID_EDIT_CUT, Zappit) + ON_COMMAND(ID_EDIT_COPY, AddNewProperty) + ON_COMMAND(ID_EDIT_PASTE, AddNewFolder) + ON_COMMAND(ID_EDIT_REPLACE, MouseModify) + ON_COMMAND(ID_EDIT_PASTE_LINK, VendorLink) + ON_COMMAND(ID_EDIT_FIND, ImportMaterials) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hdCLibDlg message handlers + +BOOL hdCLibDlg::OnInitDialog() +{ + CResizableDialog::OnInitDialog(); + + // TODO: Add extra initialization here + ////////////////////////////////////////////////////////////////// + + // preset layout + AddAnchor(IDOK,BOTTOM_RIGHT); + AddAnchor(IDCANCEL,BOTTOM_RIGHT); + AddAnchor(IDC_MYTREE,TOP_LEFT,BOTTOM_CENTER); + AddAnchor(IDC_MYLIST,TOP_CENTER,BOTTOM_RIGHT); + + CString LibName=BinDir+"heatlib.dat"; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int i,k; + + Ancestors.RemoveAll(); + Parent=NULL; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + + // set up materials library tree control + m_bIsDragging = FALSE; + m_dragTargetTree = NULL; + m_dragTargetList = NULL; + m_dragItem = NULL; + m_imageList.Create( IDB_TREE, 16, 1, RGB(255,0,0) ); + m_mytree.SetImageList( &m_imageList, TVSIL_NORMAL ); + m_mylist.SetImageList( &m_imageList, TVSIL_NORMAL ); + + LibParent = m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Library Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + Parent=LibParent; + ModelParent = m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE, + "Model Materials",1,1,TVIS_EXPANDED ,TVIS_EXPANDED ,-9999,NULL,NULL); + + // Put Model's properties into the InModel edit box; + LibProps.RemoveAll(); + HTREEITEM hResult; + CArray &blockproplist=pDoc->blockproplist; + for(i=0;i=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + break; + + default: + + break; + } + } + + fclose(fp); + +/* + // tutorial example + HTREEITEM hChapter; + hChapter = m_mytree.InsertItem( "Chapter 1", 0, 1 ); + m_mytree.InsertItem( "What", 2, 2, hChapter ); +*/ + + Focus=NULL; + + return TRUE; // return TRUE unless you set the focus to a control +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR hdCLibDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + + + + + +/////////////////////////////////////////////////// +// Implementation of library-specific file I/O +/////////////////////////////////////////////////// + +char* hdCLibDlg::StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderName=v; + m_mytree.SetItemText(Parent,v); + 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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderURL=v; + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==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; + } + } + FoldProps[FoldProps.GetUpperBound()].FolderVendor=v; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"",12)==0){ + MProp.BlockName="New Material"; + MProp.Kx=1.; + MProp.Ky=1.; + MProp.Kt=0; + MProp.qv=0.; + MProp.npts=0; + q[0]=NULL; + } + + // Library Hierarchy + if( _strnicmp(q,"",11)==0){ + q[0]=NULL; + return 3; + } + + 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){ + q[0]=NULL; + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////// +// Drag-n-Drop Implementation + +void hdCLibDlg::OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=LibParent) // can't drag top-level folder + { + CImageList* pDragImage; + pDragImage = m_mytree.CreateDragImage( m_dragItem ); + m_mytree.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + SetTimer ( 1, 75, NULL ) ; + bDragFromLibrary=TRUE; + } + + *pResult = 0; + +} + +void hdCLibDlg::OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + m_dragItem = pNMTreeView->itemNew.hItem; + + if(m_dragItem!=ModelParent) + { + CImageList* pDragImage; + pDragImage = m_mylist.CreateDragImage( m_dragItem ); + m_mylist.SelectItem( m_dragItem ); + pDragImage->BeginDrag( 0, CPoint(0,-14) ); + pDragImage->DragEnter(this, pNMTreeView->ptDrag); + SetCapture(); + m_bIsDragging = TRUE; + delete pDragImage; + bDragFromLibrary=FALSE; + SetTimer ( 1, 75, NULL ) ; + } + + *pResult = 0; +} + +void hdCLibDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + CPoint ptDrag( point ); + CPoint ptTree( point ); + CPoint ptList( point ); + UINT uHitTest = TVHT_ONITEM; + + MapWindowPoints( this, &ptDrag, 1 ); + MapWindowPoints( &m_mytree, &ptTree, 1 ); + MapWindowPoints( &m_mylist, &ptList, 1 ); + + CImageList::DragMove( ptDrag ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + } + + CResizableDialog::OnMouseMove(nFlags, point); +} + +void hdCLibDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + if( m_bIsDragging != FALSE ) + { + KillTimer ( 1 ) ; + CImageList::DragLeave( &m_mytree ); + CImageList::EndDrag(); + ReleaseCapture(); + m_bIsDragging = FALSE; + + // Do some logic to drop onto the main tree if the property is + // dropped onto the tree's window, but not exactly on the list + if((m_dragTargetTree==NULL) && (m_dragTargetList==NULL)) + { + POINT point; + GetCursorPos(&point); + void* pVoid = (void*)GetDesktopWindow()->WindowFromPoint(point); + if((void *) &m_mytree==pVoid) m_dragTargetTree=LibParent; + if((void *) &m_mylist==pVoid) m_dragTargetList=ModelParent; + } + + // Drop onto the Library tree + if( m_dragTargetTree != NULL ) + { + if(!IsTailChasing(m_dragItem,m_dragTargetTree)) + { + CopyItemToLibrary(m_dragItem,m_dragTargetTree); + if(bDragFromLibrary) m_mytree.DeleteItem( m_dragItem ); + } + } + + // Drop onto the model materials + if( m_dragTargetList != NULL ) + { + CopyItemToModel(m_dragItem,m_dragTargetList); + if(!bDragFromLibrary) m_mylist.DeleteItem( m_dragItem ); + } + } + else CResizableDialog::OnLButtonUp(nFlags, point); +} + +BOOL hdCLibDlg::IsFolder(HTREEITEM hItem) +{ + int nImage1, nImage2, nSelImage; + m_mytree.GetItemImage(hItem,nImage1,nSelImage); + m_mylist.GetItemImage(hItem,nImage2,nSelImage); + if ((nImage1!=2) && (nImage2!=2)) return TRUE; + return FALSE; +} + +HTREEITEM hdCLibDlg::CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(IsFolder(hTarget)) + { + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hTarget, TVI_LAST ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hTarget, TVI_LAST); + m_mytree.SetItemData(hResult,ItemData); + } + } + else + { + hParent = m_mytree.GetParentItem(hTarget); + + if (IsFolder(hItem)) + { + hResult = m_mytree.InsertItem( szLabel, 0, 1, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToLibrary(hChild,hResult) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + } + else{ + if(!bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + hResult = m_mytree.InsertItem( szLabel, 2, 2, hParent, hTarget ); + m_mytree.SetItemData(hResult,ItemData); + } + } + + + return hResult; +} + +HTREEITEM hdCLibDlg::CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget) +{ + HTREEITEM hResult,hParent,hChild; + + if (IsFolder(hItem)) + { + hChild=m_mytree.GetChildItem(hItem) ; + hParent=hTarget; + while (hChild!=NULL) + { + hParent=CopyItemToModel(hChild,hParent) ; + hChild = m_mytree.GetNextSiblingItem(hChild); + } + hResult=hParent; + } + else{ + + CString szLabel; + int ItemData; + if(!bDragFromLibrary) + { + szLabel = m_mylist.GetItemText(hItem); + ItemData = (int) m_mylist.GetItemData(hItem); + } + else{ + szLabel = m_mytree.GetItemText(hItem); + ItemData = (int) m_mytree.GetItemData(hItem); + } + + if(bDragFromLibrary) + { + CMaterialProp MProp=LibProps[ItemData]; + LibProps.Add(MProp); + int NewItemData=(int) LibProps.GetUpperBound(); + ItemData=NewItemData; + } + + hParent = m_mylist.GetParentItem( hTarget ); + if( hParent != NULL ) + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, hTarget); + else + hResult=m_mylist.InsertItem( szLabel, 2, 2, ModelParent, TVI_LAST ); + m_mylist.SetItemData(hResult,ItemData); + } + + return hResult; +} + +void hdCLibDlg::AddNewProperty() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetList!=NULL) + { + hParent = m_mylist.GetParentItem(m_dragTargetList); + if( hParent != NULL ) + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, m_dragTargetList); + else + hResult=m_mylist.InsertItem("New Material", 2, 2, ModelParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mylist.SetItemData(hResult,LibProps.GetUpperBound()); + } + + if(m_dragTargetTree!=NULL) + { + if(IsFolder(m_dragTargetTree)) hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Material", 2, 2, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Material", 2, 2, LibParent, TVI_LAST ); + + CMaterialProp MProp; + LibProps.Add(MProp); + m_mytree.SetItemData(hResult,LibProps.GetUpperBound()); + } +} + +void hdCLibDlg::AddNewFolder() +{ + HTREEITEM hParent,hResult; + + if(m_dragTargetTree!=NULL) + { + if (IsFolder(m_dragTargetTree)) + hParent=m_dragTargetTree; + else hParent = m_mytree.GetParentItem(m_dragTargetTree); + if( hParent != NULL ) + hResult=m_mytree.InsertItem("New Folder", 0, 1, hParent, m_dragTargetTree); + else + hResult=m_mytree.InsertItem("New Folder", 0, 1, LibParent, TVI_LAST ); + + CFolderProp FProp; + FProp.FolderName="New Folder"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(hResult,FoldProps.GetUpperBound()); + } +} + +void hdCLibDlg::Zappit() +{ + if ((m_dragTargetTree!=NULL) && (m_dragTargetTree!=LibParent)) + m_mytree.DeleteItem(m_dragTargetTree); + if ((m_dragTargetList!=NULL) && (m_dragTargetList!=ModelParent)) + m_mylist.DeleteItem(m_dragTargetList); +} + +void hdCLibDlg::OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptTree(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptTree, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptTree, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree==NULL) m_dragTargetTree=LibParent; + + VERIFY(pMenu->CreatePopupMenu()); + if(m_dragTargetTree!=LibParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Add New Folder")); + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)) + { + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + HTREEITEM hParent=m_mytree.GetParentItem(m_dragTargetTree); + if(hParent!=LibParent) + { + int k=(int) m_mytree.GetItemData(hParent); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + else if(m_dragTargetTree!=LibParent){ + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Edit Folder Info")); + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + if (FoldProps[k].FolderVendor!="") + { + CString VendorBlurb; + VendorBlurb="Visit " + FoldProps[k].FolderVendor; + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE_LINK, VendorBlurb)); + VendorURL=FoldProps[k].FolderURL; + VendorName=FoldProps[k].FolderVendor; + } + } + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("hdCLibDlg::OnRclickMytree failed to destroy menu resource\n"); + pMenu = FALSE; + } + + + *pResult = 0; +} + +void hdCLibDlg::OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + CMenu* pMenu = NULL; + try + { + pMenu = new CMenu; + } + catch(...) + { + pMenu = NULL; + } + ASSERT(pMenu); + + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList==NULL) m_dragTargetList=ModelParent; + + VERIFY(pMenu->CreatePopupMenu()); + if (m_dragTargetList!=ModelParent) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Delete Selected")); + else + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_FIND, "Import Materials")); + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Add New Material")); + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)) + VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_REPLACE, "Modify Material")); + } + + pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this); + + try + { + delete pMenu; + } + catch(...) + { + ASSERT(FALSE); + TRACE("hdCLibDlg::OnRclickMylist failed to destroy menu resource\n"); + pMenu = FALSE; + } + + *pResult = 0; +} + +void hdCLibDlg::OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mylist, &ptList, 1 ); + m_dragTargetList = m_mylist.HitTest( ptList, &uHitTest ); + m_dragTargetTree = NULL; + + if(m_dragTargetList!=NULL) + { + if(!IsFolder(m_dragTargetList)){ + int k=(int) m_mylist.GetItemData(m_dragTargetList); + ModifyMaterial(k); + m_mylist.SetItemText(m_dragTargetList,LibProps[k].BlockName); + } + } + + + *pResult = 0; +} + +void hdCLibDlg::OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT point; + GetCursorPos(&point); + CPoint ptList(point); + UINT uHitTest = TVHT_ONITEM; + GetDesktopWindow()->MapWindowPoints( &m_mytree, &ptList, 1 ); + m_dragTargetTree = m_mytree.HitTest( ptList, &uHitTest ); + m_dragTargetList = NULL; + + if(m_dragTargetTree!=NULL) + { + if(!IsFolder(m_dragTargetTree)){ + int k=(int) m_mytree.GetItemData(m_dragTargetTree); + ModifyMaterial(k); + m_mytree.SetItemText(m_dragTargetTree,LibProps[k].BlockName); + } + } + + *pResult = 0; +} + +void hdCLibDlg::ModifyMaterial(int k) +{ + hdCMatDlg zDlg; + + zDlg.m_Kx=LibProps[k].Kx; + zDlg.m_Ky=LibProps[k].Ky; + zDlg.m_Kt=LibProps[k].Kt; + zDlg.m_qv=LibProps[k].qv; + zDlg.m_BlockName=LibProps[k].BlockName; + zDlg.m_npts=LibProps[k].npts; + for(int i=0;iProblemType==0){ + zDlg.m_mu1label="x"; + zDlg.m_mu2label="y"; + } + else{ + zDlg.m_mu1label="r"; + zDlg.m_mu2label="z"; + } + if(zDlg.DoModal()==IDOK){ + LibProps[k].BlockName=zDlg.m_BlockName; + LibProps[k].Kx=zDlg.m_Kx; + LibProps[k].Ky=zDlg.m_Ky; + LibProps[k].Kt=zDlg.m_Kt; + LibProps[k].qv=zDlg.m_qv; + LibProps[k].npts=zDlg.m_npts; + for(int i=0;i &blockproplist=pDoc->blockproplist; + int k; + + // copy Model Materials into the model + blockproplist.RemoveAll(); + hChild=m_mylist.GetChildItem(ModelParent) ; + while (hChild!=NULL) + { + k=(int) m_mylist.GetItemData(hChild); + blockproplist.Add(LibProps[k]); + hChild = m_mylist.GetNextSiblingItem(hChild) ; + } + + // write Library Materials to disk + + CString LibName=BinDir+"heatlib.dat"; + FILE *fp; + + if ((fp=fopen(LibName,"wt"))==NULL) return; + + hChild=m_mytree.GetChildItem(LibParent); + while(hChild!=NULL) + { + CopyItemToDisk(hChild,fp); + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fclose(fp); + + + CResizableDialog::OnOK(); +} + +void hdCLibDlg::CopyItemToDisk(HTREEITEM hItem, FILE *fp) +{ + HTREEITEM hChild; + int i =(int) m_mytree.GetItemData(hItem); + int j; + + if (IsFolder(hItem)) + { + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderName); + if(FoldProps[i].FolderURL!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderURL); + if(FoldProps[i].FolderVendor!="") + fprintf(fp," = \"%s\"\n", (const char *) FoldProps[i].FolderVendor); + + hChild=m_mytree.GetChildItem(hItem) ; + while (hChild!=NULL) + { + CopyItemToDisk(hChild,fp) ; + hChild = m_mytree.GetNextSiblingItem(hChild) ; + } + + fprintf(fp,"\n"); + } + else{ + fprintf(fp,"\n"); + fprintf(fp," = \"%s\"\n", (const char *) LibProps[i].BlockName); + fprintf(fp," = %.17g\n",LibProps[i].Kx); + fprintf(fp," = %.17g\n",LibProps[i].Ky); + fprintf(fp," = %.17g\n",LibProps[i].Kt); + fprintf(fp," = %.17g\n",LibProps[i].qv); + if (LibProps[i].npts>0) + { + fprintf(fp," = %i\n",LibProps[i].npts); + for (j=0;j\n\n"); + } +} + +void hdCLibDlg::VendorLink() +{ + if (VendorURL!="") + ShellExecute(m_hWnd,"open",VendorURL,"","",SW_SHOWMAXIMIZED); + else + MsgBox("No URL available for %s",VendorName); +} + +void hdCLibDlg::ImportMaterials() +{ + CFileDialog *fname_dia; + CString SourceFile; + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "Magnetostatic Input File (*.fem) | *.fem; *.FEM | All Files (*.*) | *.*||", + NULL); + + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + + SourceFile=fname_dia->GetPathName(); + delete[] fname_dia; + + // Add selected properties to the library; + FILE *fp; + CMaterialProp MProp; + CFolderProp FProp; + char s[1024]; + int k; + BOOL bToLibrary=TRUE; + + if ((fp=fopen(SourceFile,"rt"))==NULL) return; + + Ancestors.RemoveAll(); + if(m_dragTargetTree!=NULL){ + // importing into the library + // put the imported materials in a new folder + Parent=m_mytree.InsertItem("Imported Materials", 0, 1, LibParent, TVI_FIRST ); + FProp.FolderName="Imported Materials"; + FProp.FolderURL=""; + FProp.FolderVendor=""; + FoldProps.Add(FProp); + m_mytree.SetItemData(Parent,FoldProps.GetUpperBound()); + } + else if(m_dragTargetList!=NULL){ + Parent=ModelParent; + bToLibrary=FALSE; + } + else return; + + while (fgets(s,1024,fp)!=NULL) + { + switch(ParseLine(s,fp,MProp)) + { + case 1: + + // add a material to library + k=(int) LibProps.GetSize(); + LibProps.Add(MProp); + if(bToLibrary) + m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + else + m_mylist.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + MProp.BlockName,2,2,NULL,NULL,k,Parent,NULL); + break; + + case 2: + if (bToLibrary) + { + // open a new folder + if (Parent!=NULL) Ancestors.Add(Parent); + k=(int) FoldProps.GetSize(); + FoldProps.Add(FProp); + Parent=m_mytree.InsertItem(TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT, + FProp.FolderName,0,1,NULL,NULL,k,Parent,NULL); + } + + break; + + case 3: + if (bToLibrary) + { + // close a folder + k=(int) Ancestors.GetUpperBound(); + if (k>=0){ + Parent=Ancestors[k]; + Ancestors.RemoveAt(k); + } + } + break; + + default: + + break; + } + } + + fclose(fp); +} + +BOOL hdCLibDlg::IsTailChasing(HTREEITEM hSource, HTREEITEM hDest) +{ + HTREEITEM hItem; + + hItem=hDest; + while(hItem!=NULL) + { + if(hSource==hItem) return TRUE; + hItem=m_mytree.GetParentItem(hItem); + } + + return FALSE; +} + +void hdCLibDlg::OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mylist.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=ModelParent)) + m_mylist.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetList=m_mylist.GetSelectedItem(); + m_dragTargetTree=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + +void hdCLibDlg::OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + + if(pTVKeyDown->wVKey==VK_DELETE){ + HTREEITEM hItem=m_mytree.GetSelectedItem(); + if ((hItem!=NULL) && (hItem!=LibParent)) + m_mytree.DeleteItem(hItem); + } + + if(pTVKeyDown->wVKey==VK_INSERT){ + m_dragTargetTree=m_mytree.GetSelectedItem(); + m_dragTargetList=NULL; + AddNewProperty(); + } + + *pResult = 0; +} + + +void hdCLibDlg::OnTimer(UINT_PTR nIDEvent) +{ + POINT pt ; + GetCursorPos ( &pt ) ; + RECT rect ; + + + // check if Library needs to be scrolled and do it; + m_mytree.GetClientRect ( &rect ) ; + m_mytree.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mytree.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + // check if Model Materials needs to be scrolled and do it; + m_mylist.GetClientRect ( &rect ) ; + m_mylist.ClientToScreen ( &rect ) ; + if((pt.x>rect.left) && (pt.x rect.bottom - 10 ) + { + CImageList::DragShowNolock ( FALSE ) ; + m_mylist.SendMessage ( WM_VSCROLL, SB_LINEDOWN ) ; + CImageList::DragShowNolock ( TRUE ) ; + } + } + } + + CResizableDialog::OnTimer(nIDEvent); +} + + + + + diff --git a/femm/hd_libdlg.h b/femm/hd_libdlg.h new file mode 100644 index 0000000..db06e86 --- /dev/null +++ b/femm/hd_libdlg.h @@ -0,0 +1,105 @@ +#pragma once + +#include "ResizableDialog.h" + +// treetestDlg.h : header file +// + +#if !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) +#define AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// hdCLibDlg dialog + +class hdCLibDlg : public CResizableDialog +{ +// Construction +public: + hdCLibDlg(CWnd* pParent = NULL); // standard constructor + + ChdrawDoc *pDoc; + CArray LibProps; + CArray FoldProps; + CArray Ancestors; + HTREEITEM Parent; + HTREEITEM ModelParent; + HTREEITEM LibParent; + BOOL bDragFromLibrary; + CString BinDir; + CString VendorURL; + CString VendorName; + int Focus; + + int ParseLine(char *s, FILE *fp, CMaterialProp &MProp); + char* StripKey(char *c); + BOOL IsFolder(HTREEITEM hItem); + HTREEITEM CopyItemToLibrary(HTREEITEM hItem, HTREEITEM hTarget); + HTREEITEM CopyItemToModel(HTREEITEM hItem, HTREEITEM hTarget); + void CopyItemToDisk(HTREEITEM hItem, FILE *fp); + void VendorLink(); + void Zappit(); + void MouseModify(); + void AddNewProperty(); + void AddNewFolder(); + void ImportMaterials(); + void ModifyMaterial(int k); + BOOL IsTailChasing(HTREEITEM hSource, HTREEITEM hDest); + +// Dialog Data + //{{AFX_DATA(hdCLibDlg) + enum { IDD = IDD_TREETEST_DIALOG }; + CTreeCtrl m_mylist; + CTreeCtrl m_mytree; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCLibDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + HICON m_hIcon; + + // stuff needed to do CTreeCtrl properly + CImageList m_imageList; + BOOL m_bIsDragging; + HTREEITEM m_dragItem; + HTREEITEM m_dragTargetTree; + HTREEITEM m_dragTargetList; + + // Generated message map functions + //{{AFX_MSG(hdCLibDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnBegindragMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnBegindragMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMylist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeydownMytree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTimer(UINT_PTR nIDEvent); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TREETESTDLG_H__5B8113A6_69AB_44C9_A4F6_E868EE363479__INCLUDED_) + + + + + diff --git a/femm/hd_movecopy.cpp b/femm/hd_movecopy.cpp new file mode 100644 index 0000000..7e7cd29 --- /dev/null +++ b/femm/hd_movecopy.cpp @@ -0,0 +1,2274 @@ +// hdrawDoc.cpp : implementation of the ChdrawDoc class (continued...) +// + +#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 "ArcDlg.h" +#include "DXFImport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern BOOL bLinehook; +//----------------------------------------------------------------- + +BOOL ChdrawDoc::ReadDXF(CString fname,double DefTol) +{ + FILE *fp; + int j,k; + CArray layerlist; + CString myLayer; + + if( (fp=fopen(fname,"rt"))==NULL ) return FALSE; + NoDraw=TRUE; + + // clear out any old drawing that we might have; +// 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(); + + char s[256]; + char v[256]; + BOOL PolylineFlag=FALSE; + CNode n[4]; + CSegment segm; + CArcSegment asegm; + CComplex c,p,q; + double R,a0,a1; + int xx,PolyLineClosed,firstpoint; + double angle=0; + + while (fgets(s,256,fp)!=NULL) + { + if (strncmp(s,"LAYER",5)==0) + { + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==2){ + sscanf(v,"%s",s); + myLayer=s; + layerlist.Add(myLayer); + } + } while(1>0); + } + + if (strncmp(s,"POINT",5)==0) + { + xx=0; + n[0].InGroup=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==10) { n[0].x=atof(v); xx=xx | 1; } + if (k==20) { n[0].y=atof(v); xx=xx | 2; } + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + if (xx==3) nodelist.Add(n[0]); + } + + if (strncmp(s,"LWPOLYLINE",10)==0) + { + int segs=0; + PolyLineClosed=FALSE; + firstpoint=-1; + angle = 0; + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + int n0,n1; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) angle=360.; + } + if (k==70) PolyLineClosed=TRUE; + if (xx==3){ + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + xx=0; + if(segs==0) firstpoint=j; + else{ + if(angle==0) + { + segm.n0=j; + segm.n1=j-1; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j-1; n1=j; } + else{ n0=j; n1=j-1; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + if ((PolyLineClosed==TRUE) && (firstpoint>=0) && (segs>0)) + { + // take care of closing the contour, if required. + j=(int) nodelist.GetSize()-1; + if(angle==0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else{ + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + angle=0; + } + } + } + + + if (strncmp(s,"POLYLINE",8)==0) + { + PolylineFlag=-1; + firstpoint=-1; + PolyLineClosed=FALSE; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==70) { + j=atoi(v); + if (j==1) PolyLineClosed=TRUE; + } + } while(1>0); + + } + + if (strncmp(s,"SEQEND",6)==0) + { + PolylineFlag=FALSE; + int j = ((int) nodelist.GetSize())-1; + if ((PolyLineClosed==TRUE) && (firstpoint>=0)) + { + if (angle == 0.0) + { + segm.n0=j; + segm.n1=firstpoint; + linelist.Add(segm); + } + else + { + int n0, n1; + if(angle>0) { n0=j; n1=firstpoint; } + else{ n0=firstpoint; n1=j; angle=fabs(angle); } + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.Add(n[0]); + j++; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n0>n1){ + asegm.n0=n0; + asegm.n1=j; + } + else{ + asegm.n0=j; + asegm.n1=n1; + } + arclist.Add(asegm); + + if(n1==j-1) n1=j; + else n0=j; + + } + asegm.n0=n0; + asegm.n1=n1; + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + arclist.Add(asegm); + } + } + PolyLineClosed=FALSE; + angle = 0.0; + } + + if (strncmp(s,"VERTEX",6)==0) + { + n[0].InGroup=0; + segm.InGroup=0; + asegm.InGroup=0; + double next_angle = 0.0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j360.) next_angle=360.; + } + } while(1>0); + + if(xx==3) + { + nodelist.Add(n[0]); + if (angle != 0.0) + { + j = (int)nodelist.GetSize(); + + int n0, n1; + if(angle>0) { n0=j-2; n1=j-1; } + else{ n0=j-1; n1=j-2; angle=fabs(angle); } + + if(angle>180.) + { + CComplex p0,p1,p2; + angle/=2.; + p0=nodelist[n0].x + I*nodelist[n0].y; + p1=nodelist[n1].x + I*nodelist[n1].y; + p2=(p0+p1)/2. - I*(1.-cos(angle*PI/180.))*(p1-p0)/ + (2.*sin(angle*PI/180.)); + n[0].x=Re(p2); + n[0].y=Im(p2); + nodelist.InsertAt(j,n[0]); + asegm.ArcLength=angle; + asegm.MaxSideLength=5.; + if (n00); + + if (xx==15) + { + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + segm.n0=j; segm.n1=j+1; + linelist.Add(segm); + } + } + + // catch ARCALIGNEDTEXT, which derails the ARC code... + if (strncmp(s,"ARCA",4)==0) s[0]=NULL; + + if (strncmp(s,"ARC",3)==0) + { + n[0].InGroup=0; + n[1].InGroup=0; + asegm.InGroup=0; + xx=0; + do{ + if (fgets(s,256,fp)==NULL) break; + k=atoi(s); + if (k==0) break; + fgets(v,256,fp); + if (k==8){ + sscanf(v,"%s",s); + myLayer=s; + for(j=0;j0); + + if(xx==31) + { + if (a10); + + if(xx==7) + { + n[0].x=c.re+R; n[1].x=c.re-R; + n[0].y=c.im; n[1].y=c.im; + j=(int) nodelist.GetSize(); + nodelist.Add(n[0]); + nodelist.Add(n[1]); + asegm.n0=j; asegm.n1=j+1; + asegm.MaxSideLength=5.; + asegm.ArcLength=180.; + arclist.Add(asegm); + asegm.n1=j; asegm.n0=j+1; + arclist.Add(asegm); + } + } + + } + + fclose(fp); + + // could be that nothing actually got read. We want to + // catch this case and tell the user about it. + if(nodelist.GetSize()==0) return FALSE; + + // suggest the proper tolerance + CComplex p0,p1; + CDXFImport dlg; + int i; + + p0=nodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=nodelist[i].x; + if(nodelist[i].yp1.im) p1.im=nodelist[i].y; + } + + R=abs(p1-p0)*1.e-04; + dlg.m_dxftol=floor(R/pow(10.,floor(log10(R))))*pow(10.,floor(log10(R))); + + if(DefTol<0) + { + dlg.DoModal(); + FancyEnforcePSLG(dlg.m_dxftol); + } + else + { + if (DefTol==0) DefTol=dlg.m_dxftol; + FancyEnforcePSLG(DefTol); + } + + NoDraw=FALSE; + + return TRUE; +} + +void ChdrawDoc::RotateMove(CComplex c, double t, int EditAction) +{ + int i; + CComplex x,z; + + z=exp(I*t*PI/180); + + if(EditAction==0) + { + for(i=0;i newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i; + CComplex p0,p1; + double d; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the nodes; + for(i=0;i newnodes; + + newnodes.RemoveAll(); + + n0=ClosestNode(p0.re,p0.im); + n1=ClosestNode(p1.re,p1.im); + + // 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;i 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;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;iextmaxx) extmaxx=nodelist[i].x; + if(nodelist[i].yextmaxy) extmaxy=nodelist[i].y; + } + + } + + for(i=0;iextmaxx) extmaxx=p.re; + if(p.imextmaxy) 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 newnodelist; + CArray< CSegment, CSegment&> newlinelist; + CArray< CArcSegment, CArcSegment&> newarclist; + CArray< CBlockLabel, CBlockLabel&> newblocklist; + int i,k; + CComplex p0,p1; + double d; + + bLinehook=ImportDXF; // kludge to stop the program from giving a crash if + // the user tries to exit during a dxf import. + + ChdrawView *pView; + POSITION pos; + pos=GetFirstViewPosition(); + pView=(ChdrawView *)GetNextView(pos); + + FirstDraw=TRUE; +// pView->lua_zoomnatural(); + dxf_line_hook(); + pView->EditAction=4; + + newnodelist.RemoveAll(); + newlinelist.RemoveAll(); + newarclist.RemoveAll(); + newblocklist.RemoveAll(); + + for(i=0;iInvalidateRect(NULL); + dxf_line_hook(); + + // find out what tolerance is so that there are not nodes right on + // top of each other; + if(tol==0){ + if (newnodelist.GetSize()<2) d=1.e-08; + else{ + p0=newnodelist[0].CC(); + p1=p0; + for(i=1;ip1.re) p1.re=newnodelist[i].x; + if(newnodelist[i].yp1.im) p1.im=newnodelist[i].y; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + } + else d=tol; + + // put in all of the lines; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + // put in all of the arcs; + for(i=0;iDrawPSLG(); + if(dxf_line_hook()){ + bLinehook=FALSE; + return; + } + } + } + + UnselectAll(); + + // do one last check to eliminate shallow arcs that + // link up the same two points as a line segment; + for(i=0;i +#include +#include "hd_nosebl.h" +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + InGroup=0; + BoundaryMarker=""; + InConductor=""; +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CComplex CNode::CC() +{ + return CComplex(x,y); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + MaxSideLength=-1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + Hidden=FALSE; + ArcLength=90.; + MaxSideLength=10.; + mySideLength=1; + BoundaryMarker=""; + InConductor=""; + InGroup=0; + NormalDirection=TRUE; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + BlockType=""; + InGroup=0; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + Kx=1.; + Ky=1; // volumetric heat capacity + qv=0.; // thermal conductivity + Kt=0.; // volume heat generation + npts=0; // number of points in the curve of + // conductivity versus temperature +} + +CMaterialProp::~CMaterialProp() +{ + +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + Tset=Tinf=qs=beta=h=0; + +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + T=0; // nodal voltage + qp=0; // point current density +} + +CCircuit::CCircuit() +{ + CircName="New Conductor"; + T=0; + q=0; + CircType=0; +}; + +CPeriodicBoundary::CPeriodicBoundary() +{ + BdryName=""; + BdryFormat=0; + nseg=0; + narc=0; + seg[0]=0; + seg[1]=0; +} + +CCommonPoint::CCommonPoint() +{ + x=y=t=0; +} + +void CCommonPoint::Order() +{ + int z; + + if(x>y){ + z=y; + y=x; + x=z; + } +} diff --git a/femm/hd_nosebl.h b/femm/hd_nosebl.h new file mode 100644 index 0000000..e99d185 --- /dev/null +++ b/femm/hd_nosebl.h @@ -0,0 +1,192 @@ +namespace hdrawdata +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL NormalDirection; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength,mySideLength; + CString BoundaryMarker; + CString InConductor; + int InGroup; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + BOOL IsSelected; + CString BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CMaterialProp(); + ~CMaterialProp(); + + CString BlockName; + double Kx,Ky; // thermal conductivity for linear (possibly anisotropic) regions + double Kt; // volumetric heat capacity + double qv; // and volume heat generation + + // properties for nonlinear conductivity + int npts; // number of points in the nonlinear conductivity curve + CComplex Kn[128]; // here, I'm being _very_ lazy by defining a fixed-length buffer for the + // thermal conductivity data points. + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + int BdryFormat; // type of boundary condition we are applying + // 0 = Fixed Voltage + // 1 = Mixed BC + // 2 = Surface Charge Density + // 3 = Periodic + // 4 = Antiperiodic + + double Tset; // Fixed value of temperature for BdryFormat=0; + double Tinf; // External temperature for convection or radiation + double qs; // Heat flux; + double beta; // radiosity coefficient + double h; // Heat transfer coefficient + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + double T; // prescribed nodal temperature + double qp; // point heat generation + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + double T; + double q; + int CircType; + + private: + +}; + +class CPeriodicBoundary +{ + public: + + CPeriodicBoundary(); + + CString BdryName; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + int nseg; // number of segs with this bc + int narc; // number of arcs with this bc + int seg[2]; // (arc)segments to which is applied + + private: +}; + +class CCommonPoint +{ + public: + + CCommonPoint(); + void Order(); + + int x,y,t; + + private: +}; + +} + +using namespace hdrawdata; diff --git a/femm/hd_probdlg.cpp b/femm/hd_probdlg.cpp new file mode 100644 index 0000000..cc4bc5d --- /dev/null +++ b/femm/hd_probdlg.cpp @@ -0,0 +1,128 @@ +// probdlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hd_probdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// probdlg dialog + + +hdCProbDlg::hdCProbDlg(CWnd* pParent /*=NULL*/) + : CDialog(hdCProbDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hdCProbDlg) + m_problem_note = _T(""); + m_precision = 1.e-8; + m_minangle=DEFAULT_MINIMUM_ANGLE; + m_depth = 1.0; + m_dt = 0.0; + m_prevsoln = _T(""); + //}}AFX_DATA_INIT +} + + +void hdCProbDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hdCProbDlg) + DDX_Control(pDX, IDC_HD_LENGTH_UNITS, m_length_units); + DDX_Control(pDX, IDC_BSMART, m_bsmart); + DDX_Control(pDX, IDC_HD_PROBTYPE, m_probtype); + DDX_Text(pDX, IDC_HD_PROBNOTE, m_problem_note); + DDX_Text(pDX, IDC_HD_PRC, m_precision); + DDV_MinMaxDouble(pDX, m_precision, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_HD_MINANG, m_minangle); + DDV_MinMaxDouble(pDX, m_minangle, 1., MINANGLE_MAX); + DDX_Text(pDX, IDC_HD_EDIT_DEPTH, m_depth); + DDX_Text(pDX, IDC_HD_DT, m_dt); + DDX_Text(pDX, IDC_HD_PREVSOLN, m_prevsoln); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HD_EDIT_DEPTH, m_IDC_depth); + DDX_Control(pDX, IDC_HD_PROBNOTE, m_IDC_problem_note); + DDX_Control(pDX, IDC_HD_PREVSOLN, m_IDC_prevsoln); + DDX_Control(pDX, IDC_HD_DT, m_IDC_dt); + DDX_Control(pDX, IDC_HD_PRC, m_IDC_precision); + DDX_Control(pDX, IDC_HD_MINANG, m_IDC_minangle); +} + + +BEGIN_MESSAGE_MAP(hdCProbDlg, CDialog) + //{{AFX_MSG_MAP(hdCProbDlg) + ON_CBN_SELCHANGE(IDC_HD_LENGTH_UNITS, OnSelchangeLengthUnits) + ON_CBN_SELCHANGE(IDC_HD_PROBTYPE, OnSelchangeProbtype) + ON_EN_CHANGE(IDC_HD_PREVSOLN, OnChangeHdPrevsoln) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// probdlg message handlers + +BOOL hdCProbDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_probtype.SetCurSel(probtype); + if(probtype) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); + + m_length_units.SetCurSel(lengthunits); + m_bsmart.SetCurSel(bsmart); + + if(m_prevsoln.GetLength()==0){ + m_IDC_dt.EnableWindow(FALSE); + m_dt=0; + } + else m_IDC_dt.EnableWindow(TRUE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hdCProbDlg::OnOK() +{ + if (UpdateData()==FALSE) return; + probtype=m_probtype.GetCurSel(); + if(probtype) m_depth=1; + if (m_prevsoln.GetLength()==0) m_dt=0; + UpdateData(FALSE); + lengthunits=m_length_units.GetCurSel(); + bsmart=m_bsmart.GetCurSel(); + CDialog::OnOK(); +} + +void hdCProbDlg::OnSelchangeLengthUnits() +{ + +} + +void hdCProbDlg::OnSelchangeProbtype() +{ + if(m_probtype.GetCurSel()) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); +} + +void hdCProbDlg::OnChangeHdPrevsoln() +{ + // TODO: If this is a RICHEDIT control, the control will not + // send this notification unless you override the CDialog::OnInitDialog() + // function and call CRichEditCtrl().SetEventMask() + // with the ENM_CHANGE flag ORed into the mask. + + UpdateData(); + if(m_prevsoln.GetLength()==0){ + m_IDC_dt.EnableWindow(FALSE); + m_dt=0; + UpdateData(FALSE); + } + else m_IDC_dt.EnableWindow(TRUE); + +} diff --git a/femm/hd_probdlg.h b/femm/hd_probdlg.h new file mode 100644 index 0000000..5552cec --- /dev/null +++ b/femm/hd_probdlg.h @@ -0,0 +1,54 @@ +// hd_CProbDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hdCProbDlg dialog + +class hdCProbDlg : public CDialog +{ +// Construction +public: + hdCProbDlg(CWnd* pParent = NULL); // standard constructor + + BOOL probtype; // variable denoting problem type + // so list entry can be correctly set + int lengthunits; // contains units of length; + int bsmart; + +// Dialog Data + //{{AFX_DATA(hdCProbDlg) + enum { IDD = IDD_HD_PROBDLG }; + CComboBox m_length_units; + CComboBox m_bsmart; + CComboBox m_probtype; + CString m_problem_note; + double m_precision; + double m_minangle; + double m_depth; + double m_dt; + CString m_prevsoln; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hdCProbDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hdCProbDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeLengthUnits(); + afx_msg void OnSelchangeProbtype(); + afx_msg void OnChangeHdPrevsoln(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_problem_note, m_IDC_precision, m_IDC_depth, m_IDC_minangle, m_IDC_dt, m_IDC_prevsoln ; +}; diff --git a/femm/hd_writepoly.cpp b/femm/hd_writepoly.cpp new file mode 100644 index 0000000..d365df6 --- /dev/null +++ b/femm/hd_writepoly.cpp @@ -0,0 +1,1545 @@ +// 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 +#include +#include "hdrawDoc.h" +#include "hdrawView.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "GRIDDLG.h" +#include "EnterPt.h" +#include "KbdZoom.h" +#include "ArcDlg.h" +#include "CopyDlg.h" +#include "scaledlg.h" +#include "MirrorDlg.h" +#include "GroupNumber.h" +#include "hd_libdlg.h" +#include "PromptBox.h" +#include "MakeABCDlg.h" + +#include + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +extern lua_State * lua; +extern BOOL bLinehook; +extern HANDLE hProc; + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView + +IMPLEMENT_DYNCREATE(ChdrawView, CView) + +BEGIN_MESSAGE_MAP(ChdrawView, CView) + //{{AFX_MSG_MAP(ChdrawView) + ON_COMMAND(ID_NODE_OP, OnNodeOp) + ON_COMMAND(ID_SEGMENT_OP, OnSegmentOp) + ON_COMMAND(ID_BLOCK_OP, OnBlockOp) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_WM_KEYDOWN() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWnd) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_MAKE_MESH, OnMakeMesh) + ON_COMMAND(ID_MENU_ANALYZE, OnMenuAnalyze) + ON_COMMAND(ID_MENU_VIEWRES, OnMenuViewres) + ON_COMMAND(ID_ARCSEG_OP, OnArcsegOp) + ON_COMMAND(ID_UNDO, OnUndo) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_COMMAND(ID_MOVE_OBJECTS, OnMoveObjects) + ON_COMMAND(ID_COPY_OBJECTS, OnCopyObjects) + ON_COMMAND(ID_DXFIN, OnDxfin) + ON_COMMAND(ID_PURGEMESH, OnPurgemesh) + ON_COMMAND(ID_DXFWRITE, OnDxfwrite) + ON_COMMAND(ID_SELECTWND, OnSelectwnd) + ON_COMMAND(ID_SELECTCIRC, OnBDSelectCirc) + ON_WM_ERASEBKGND() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_MENU_MATLIB, OnMenuMatlib) + ON_COMMAND(ID_GROUP_OP, OnGroupOp) + ON_COMMAND(ID_OPEN_SELECTED, OnOpenSelected) + ON_COMMAND(ID_EDIT_SCALE, OnEditScale) + ON_COMMAND(ID_EDIT_MIRROR, OnEditMirror) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames) + ON_COMMAND(ID_VIEW_SHOWORPHANS, OnViewShowOrphans) + ON_COMMAND(ID_CREATERADIUS, OnCreateRadius) + ON_UPDATE_COMMAND_UI(ID_EDIT_EXTERIOR, OnUpdateEditExterior) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_COMMAND(ID_EDIT_CREATEOPENBOUNDARY, &ChdrawView::OnMakeABC) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView construction/destruction + +ChdrawView::ChdrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // Default Colors + SelColor = RGB(255,0,0); + MeshColor = RGB(213,228,20); + BlockColor = RGB(0,125,0); + LineColor = RGB(0,0,255); + GridColor = RGB(0,0,255); + NodeColor = RGB(0,0,0); + BackColor = RGB(255,255,255); + NameColor = RGB(0,0,0); + + // assume some default behaviors if they can't be + // loaded from disk + d_action=0; + d_mag=100.; + d_gridsize=0.25; + d_showgrid=TRUE; + d_snapgrid=FALSE; + d_showorigin=FALSE; + d_shownames=TRUE; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // now, set default look for the preprocessor; + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + MaxSeg = 1.0; + ArcAngle = 90.0; +} + +void ChdrawView::OnNewDocument() +{ + EditAction=d_action; + ox=0.; oy=0.; + mag=d_mag; + GridSize=d_gridsize; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + MeshFlag=FALSE; + FirstPoint=-1; + ZoomWndFlag=FALSE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) return; + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + if (StatBar==NULL) return; + + // update check boxes in the main menu... + EditAction=d_action; + GridFlag=d_showgrid; + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(d_action==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(d_action==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(d_action==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(d_action==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(d_action==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(d_showgrid==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(d_snapgrid==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(d_shownames==TRUE) + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); +} + +ChdrawView::~ChdrawView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL ChdrawView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView drawing + +void ChdrawView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +void ChdrawView::DrawPSLG() +{ + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen,penMesh; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penBlack.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + + ChdrawDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + + // make sure all the right boxes are checked. + { + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r); + if(d_showorigin==TRUE) + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penBlack ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlack ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw node block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + + ReleaseDC(pDC); +} + +BOOL ChdrawView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void ChdrawView::OnDraw(CDC* pDC) +{ + ChdrawDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if(pDoc->NoDraw==TRUE) return; + + // TODO: add draw code for native data here + RECT r; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,side,R,dt; + CComplex c,p,s; + CString lbl; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + if (pDoc->FirstDraw==TRUE) OnZoomNatural(); + + CPen *pOldPen; + CPen penBlue,penRed,penNode,penGreen,penMesh,penGrey; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penGrey.CreatePen(PS_SOLID,1,RGB(220,220,220)); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=1.1; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + if(MeshFlag==TRUE) + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw origin marker if it is enabled + if(d_showorigin==TRUE) + { + // is the origin in the view area? + if (DwgToScreen(0.,0.,&xs,&ys,&r)==TRUE) + { + if ((xs>-10) && (ys>-10) && (xsSelectObject( &penNode ); + MyMoveTo(pDC,xs-9,ys); + MyLineTo(pDC,xs+9,ys); + MyMoveTo(pDC,xs,ys-9); + MyLineTo(pDC,xs,ys+9); + pDC->SelectObject( pOldPen ); + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->meshline[i].x].xs, + pDoc->meshnode[pDoc->meshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->meshline[i].y].xs, + pDoc->meshnode[pDoc->meshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + + pOldPen = pDC->SelectObject( &penGrey ); + for(i=0;igreymeshline.GetSize();i++) + { + MyMoveTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].x].xs, + pDoc->meshnode[pDoc->greymeshline[i].x].ys); + MyLineTo(pDC,pDoc->meshnode[pDoc->greymeshline[i].y].xs, + pDoc->meshnode[pDoc->greymeshline[i].y].ys); + } + pDC->SelectObject( pOldPen ); + } + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + { + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + { + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + // Draw block labels + for(i=0;iblocklist.GetSize();i++) + { + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + if(pDoc->blocklist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penGreen ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + // circle approximately showing area constraint... + if((pDoc->blocklist[i].MaxArea>0) && + (pDoc->blocklist[i].BlockType!="")){ + side=sqrt(pDoc->blocklist[i].MaxArea/PI); + j=(int) ceil(side*mag); + pDC->Arc(xs-j,ys-j,xs+j+1,ys+j+1,xs+j+1,ys,xs+j+1,ys); + } + + if(ShowNames){ + pDC->SetTextColor(NameColor); + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode (TRANSPARENT); + for(k=0,lbl="";kblockproplist.GetSize();k++) + if (pDoc->blockproplist[k].BlockName==pDoc->blocklist[i].BlockType) + lbl=pDoc->blocklist[i].BlockType; + if (pDoc->blocklist[i].BlockType=="") lbl=""; + pDC->TextOut(xs+5,ys,lbl); + pDC->SetTextColor(RGB(0,0,0)); + } + + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +void ChdrawView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + EditAction=d_action; + GridFlag=d_showgrid; + SnapFlag=d_snapgrid; + ShowNames=d_shownames; + CheckIt(); +} + +void ChdrawView::CheckIt() +{ + // once again, this is sort of a punt + // to make sure that the right buttons + // are checked. It can be relatively + // easy to change the internal flags + // associated with the buttons without + // taking the time to service the button + // state otherwise. + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame()"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + + // update check boxes in the main menu... + + CMenu* MMnu=MFrm->GetMenu(); + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + + if(EditAction==0){ + tc->PressButton(ID_NODE_OP,TRUE); + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + } + if(EditAction==1){ + tc->PressButton(ID_SEGMENT_OP,TRUE); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + } + if(EditAction==2){ + tc->PressButton(ID_BLOCK_OP,TRUE); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + } + if(EditAction==3){ + tc->PressButton(ID_ARCSEG_OP,TRUE); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + } + if(EditAction==4){ + tc->PressButton(ID_GROUP_OP,TRUE); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + } + + pToolBar=&MFrm->m_leftbar; + tc=&pToolBar->GetToolBarCtrl(); + if(GridFlag==TRUE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + + if(SnapFlag==TRUE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + + if(ShowNames==TRUE){ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_CHECKED); + } + else{ + MMnu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_UNCHECKED); + } +} + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView printing + +BOOL ChdrawView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void ChdrawView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void ChdrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView diagnostics + +#ifdef _DEBUG +void ChdrawView::AssertValid() const +{ + CView::AssertValid(); +} + +void ChdrawView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +ChdrawDoc* ChdrawView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(ChdrawDoc))); + return (ChdrawDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// ChdrawView message handlers + +void ChdrawView::OnNodeOp() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,TRUE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void ChdrawView::OnSegmentOp() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=1; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,TRUE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void ChdrawView::OnArcsegOp() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=3; + FirstPoint=-1; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,TRUE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} +void ChdrawView::OnBlockOp() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_CHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,TRUE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,FALSE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + + +void ChdrawView::OnGroupOp() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc; + pDoc=GetDocument(); + pDoc->UnselectAll(); + EditAction=4; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + MMnu->CheckMenuItem(ID_NODE_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_SEGMENT_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_BLOCK_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_ARCSEG_OP, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_GROUP_OP, MF_CHECKED); + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HD_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_NODE_OP,FALSE); + tc->PressButton(ID_SEGMENT_OP,FALSE); + tc->PressButton(ID_BLOCK_OP,FALSE); + tc->PressButton(ID_ARCSEG_OP,FALSE); + tc->PressButton(ID_GROUP_OP,TRUE); + +// InvalidateRect(NULL); + DrawPSLG(); +} + +void ChdrawView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + ChdrawDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ( (SnapFlag==TRUE) && ((EditAction==0) || (EditAction==2)) ) + { + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + if((ZoomWndFlag==2) || (SelectWndFlag==2)){ + + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + + } + + if(SelectCircFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + double R; + CComplex q; + + int xso,yso,xsi,ysi,xsn,ysn,i,k; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old circle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + R=abs((xso-xsn)+I*(yso-ysn)); + for(i=1;i<=(int)(2.*PI*R);i++){ + q=R*exp(I*((double) i)/R)+(xso+I*yso); + ocol=pDC->GetPixel((int) Re(q),(int) Im(q)); + p.c=ocol; p.x=(int) Re(q); p.y=(int) Im(q); + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel((int) Re(q),(int) Im(q),ocol); + } + + ReleaseDC(pDC); + + } + + // update mouse location; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void ChdrawView::OnZoomIn() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + InvalidateRect(NULL); +} + +void ChdrawView::OnZoomOut() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + InvalidateRect(NULL); +} + +BOOL ChdrawView::GetBoundingBox(double *x, double *y) +{ + // look at points, block labels, and arcs to get bounding box. + ChdrawDoc *pDoc=GetDocument(); + int i,j,k; + double R,dt; + CComplex p,s,c; + + if (pDoc->nodelist.GetSize()<2) return FALSE; + + x[0]=pDoc->nodelist[0].x; x[1]=pDoc->nodelist[0].x; + y[0]=pDoc->nodelist[0].y; y[1]=pDoc->nodelist[0].y; + for(i=1;inodelist.GetSize();i++) + { + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + { + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;iarclist.GetSize();i++) + { + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + return TRUE; +} + +void ChdrawView::OnZoomNatural() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + + if (GetBoundingBox(x,y)==FALSE) return; + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0]) > (y[1]-y[0])) w=(x[1]-x[0]); + else w=(y[1]-y[0]); + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-0.5)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) + pDoc->FirstDraw=FALSE; + else InvalidateRect(NULL); +} + +void ChdrawView::OnBDSelectCirc() +{ + SelectCircFlag=TRUE; + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,TRUE); +} + +void ChdrawView::OnZoomWnd() +{ + // TODO: Add your command handler code here + ZoomWndFlag=TRUE; + SelectWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=FALSE; +} + +void ChdrawView::OnSelectwnd() +{ + // TODO: Add your command handler code here + SelectWndFlag=TRUE; + SelectCircFlag=FALSE; + ZoomWndFlag=FALSE; + CreateRadiusFlag=FALSE; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,TRUE); +} + +void ChdrawView::OnShowGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + + InvalidateRect(NULL); +} + +void ChdrawView::OnSetGrid() +{ + // TODO: Add your command handler code here + GRIDDLG pDlg; + ChdrawDoc *pDoc=GetDocument(); + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + InvalidateRect(NULL); + } +} + +void ChdrawView::OnSnapGrid() +{ + // TODO: Add your command handler code here + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void ChdrawView::OnShowMesh() +{ + // TODO: Add your command handler code here + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + } + else if(MeshUpToDate==TRUE){ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + } + InvalidateRect(NULL); +} + +void ChdrawView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void ChdrawView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void ChdrawView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Add your message handler code here and/or call default + // VK_TAB, VK_DELETE -- ones that we want to catch + ChdrawDoc *pDoc=GetDocument(); + + if (((nChar=='z') || (nChar=='Z')) && (GetKeyState(VK_CONTROL))) OnUndo(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if (nChar==VK_TAB) + { + if ((EditAction==0) || (EditAction==2)) EnterPoint(); + if (EditAction==4) + { + CGroupNumber dlg; + dlg.m_groupnumber=0; + if(dlg.DoModal()==IDOK) + { + int i,j; + j=dlg.m_groupnumber; + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + } + + if (nChar==VK_DELETE) OnEditCut(); + + if (nChar==VK_SPACE) OnOpenSelected(); + + if (nChar==VK_ESCAPE){ + pDoc->UnselectAll(); + FirstPoint=-1; + ZoomWndFlag=0; + SelectWndFlag=0; + SelectCircFlag=0; + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + DrawPSLG(); + } + + if (nChar==VK_F3) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if (GetBoundingBox(x,y)!=FALSE) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + for (i=0;iblocklist.GetSize();i++) + { + if (pDoc->blocklist[i].MaxArea>0) pDoc->blocklist[i].MaxArea/=4.; + else if (pDoc->SmartMesh) pDoc->blocklist[i].MaxArea=DefaultMeshSize/4.; + } + InvalidateRect(NULL); + } + + if (nChar==VK_F4) + { + int i; + double x[2],y[2]; + double DefaultMeshSize; + + if ((GetBoundingBox(x,y)!=FALSE) && (pDoc->SmartMesh)) + DefaultMeshSize=pow(abs(x[1]-x[0]+I*(y[1]-y[0]))/BoundingBoxFraction,2.); + else DefaultMeshSize=0; + + for (i=0;iblocklist.GetSize();i++) + { + pDoc->blocklist[i].MaxArea*=4.; + if ((pDoc->blocklist[i].MaxArea>DefaultMeshSize) && (DefaultMeshSize>0)) + pDoc->blocklist[i].MaxArea=DefaultMeshSize; + } + InvalidateRect(NULL); + } + + // Call to base class... + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void ChdrawView::EnterPoint() +{ + // TODO: Add your command handler code here + CEnterPt pDlg; + double x,y,t,d; + int i; + ChdrawDoc* pDoc = GetDocument(); + BOOL flag; + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + pDoc->UpdateUndo(); + + if (pDoc->nodelist.GetSize()<2) d=1.e-08; + else{ + CComplex p0,p1,p2; + p0=pDoc->nodelist[0].CC(); + p1=p0; + for(i=1;inodelist.GetSize();i++) + { + p2=pDoc->nodelist[i].CC(); + if(p2.rep1.re) p1.re=p2.re; + if(p2.imp1.im) p1.im=p2.im; + } + d=abs(p1-p0)*CLOSE_ENOUGH; + } + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(x,y,d); + } + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(x,y,d); + } + + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } +} + +void ChdrawView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonDown(nFlags, point); + return; + } + + BOOL flag; + ChdrawDoc* pDoc = GetDocument(); + + if (CreateRadiusFlag==TRUE) + { + int k; + double r; + + CreateRadiusFlag=FALSE; + if ((k=pDoc->ClosestNode(mx,my))<0) return; // catch case where no nodes have been drawn yet; + if (pDoc->CanCreateRadius(k)==FALSE) + { + MsgBox("The specified point is not suitable for\nconversion into a radius"); + return; + } + + CPromptBox dlg; + dlg.mytitle = "Enter desired radius dimension:"; + if (dlg.DoModal()==IDOK) + { + r=dlg.ParseDouble(); + if (r>0){ + if (pDoc->CreateRadius(k,r)) + { + InvalidateRect(NULL); + MeshUpToDate=FALSE; + } + else MsgBox("Could not make a radius of the prescribed dimension"); + } + } + + return; + } + + if (SelectWndFlag==1) + { + ZoomPix.RemoveAll(); + SelectWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectWndFlag==2) return; + + if (SelectCircFlag==1) + { + ZoomPix.RemoveAll(); + SelectCircFlag++; + wzx=mx;wzy=my; + return; + } + + if (SelectCircFlag==2) return; + + if (ZoomWndFlag==1) + { + ZoomPix.RemoveAll(); + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0){ + pDoc->UpdateUndo(); + flag=pDoc->AddNode(mx,my,1./mag); + if (flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==1){ + if (FirstPoint<0){ + if(pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + pDoc->nodelist[FirstPoint].ToggleSelect(); + pDoc->UpdateUndo(); + flag=pDoc->AddSegment(FirstPoint,pDoc->ClosestNode(mx,my)); + FirstPoint=-1; + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + if (EditAction==2){ + pDoc->UpdateUndo(); + flag=pDoc->AddBlockLabel(mx,my,1./mag); + if(flag==TRUE) + { + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + } + + if (EditAction==3){ + if (FirstPoint<0){ + if (pDoc->nodelist.GetSize()==0) return; + FirstPoint=pDoc->ClosestNode(mx,my); + pDoc->nodelist[FirstPoint].ToggleSelect(); + DrawPSLG(); + } + else{ + CArcSegment asegm; + CArcDlg dlg; + asegm.n0=FirstPoint; + asegm.n1=pDoc->ClosestNode(mx,my); + pDoc->nodelist[asegm.n1].ToggleSelect(); + DrawPSLG(); + + for(int k=0;klineproplist.GetSize();k++) + dlg.namelist.Add(pDoc->lineproplist[k].BdryName); + + dlg.cursel=0; + dlg.m_MaxSeg=MaxSeg; + dlg.m_ArcAngle=ArcAngle; + if (dlg.DoModal()==IDCANCEL){ + FirstPoint=-1; + pDoc->UnselectAll(); + DrawPSLG(); + return; + } + MaxSeg = asegm.MaxSideLength = dlg.m_MaxSeg; + ArcAngle = asegm.ArcLength=dlg.m_ArcAngle; + if (dlg.cursel==0) asegm.BoundaryMarker=""; + else asegm.BoundaryMarker=pDoc->lineproplist[dlg.cursel-1].BdryName; + + pDoc->UpdateUndo(); + flag=pDoc->AddArcSegment(asegm); + flag=FALSE; + FirstPoint=-1; + pDoc->UnselectAll(); + if(flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else DrawPSLG(); + } + else DrawPSLG(); + } + } + + CView::OnLButtonDown(nFlags, point); +} + +void ChdrawView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag==2){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + RECT r; + double z,m[2]; + if (mxGetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTWND,FALSE); + + int i,k; + double x,y,z; + ChdrawDoc *pDoc=GetDocument(); + SelectWndFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + if (mxnodelist.GetSize();i++) + { + x=pDoc->nodelist[i].x; y=pDoc->nodelist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + x=pDoc->blocklist[i].x; y=pDoc->blocklist[i].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->linelist[i].n0].x; + y=pDoc->nodelist[pDoc->linelist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->linelist[i].n1].x; + y=pDoc->nodelist[pDoc->linelist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + x=pDoc->nodelist[pDoc->arclist[i].n0].x; + y=pDoc->nodelist[pDoc->arclist[i].n0].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + x=pDoc->nodelist[pDoc->arclist[i].n1].x; + y=pDoc->nodelist[pDoc->arclist[i].n1].y; + if((x<=mx) && (x>=wzx) && (y<=my) && (y>=wzy)) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + if (SelectCircFlag==2){ + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + tc->PressButton(ID_SELECTCIRC,FALSE); + + int i,k; + double R; + CComplex c,q; + ChdrawDoc *pDoc=GetDocument(); + SelectCircFlag=0; + if((mx==wzx) && (my==wzy)){ + InvalidateRect(NULL); + return; + } + + R=abs((mx-wzx)+I*(my-wzy)); + c=wzx+I*wzy; + + if((EditAction==0) || (EditAction==4)) + { + for(i=0;inodelist.GetSize();i++) + { + q=pDoc->nodelist[i].CC(); + if(abs(q-c)<=R) + pDoc->nodelist[i].IsSelected=TRUE; + } + } + + if((EditAction==2) || (EditAction==4)) + { + for(i=0;iblocklist.GetSize();i++) + { + q=pDoc->blocklist[i].x+I*pDoc->blocklist[i].y; + if(abs(q-c)<=R) + pDoc->blocklist[i].IsSelected=TRUE; + } + } + + if((EditAction==1) || (EditAction==4)) + { + for(i=0;ilinelist.GetSize();i++) + { + + k=0; + q=pDoc->nodelist[pDoc->linelist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->linelist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->linelist[i].IsSelected=TRUE; + } + } + + if((EditAction==3) || (EditAction==4)) + { + for(i=0;iarclist.GetSize();i++) + { + k=0; + q=pDoc->nodelist[pDoc->arclist[i].n0].CC(); + if(abs(q-c)<=R) k++; + q=pDoc->nodelist[pDoc->arclist[i].n1].CC(); + if(abs(q-c)<=R) k++; + + if(k==2) pDoc->arclist[i].IsSelected=TRUE; + } + } + InvalidateRect(NULL); + } + + CView::OnLButtonUp(nFlags, point); +} + +void ChdrawView::OnRButtonDown(UINT nFlags, CPoint point) +{ + if(bLinehook!=FALSE){ + CView::OnRButtonDown(nFlags, point); + return; + } + + ChdrawDoc* pDoc = GetDocument(); + int i,j; + + //toggle select of nearest point + if(EditAction==0){ + j=pDoc->ClosestNode(mx,my); + if(j>=0) pDoc->nodelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest segment + if(EditAction==1){ + j=pDoc->ClosestSegment(mx,my); + if(j>=0) pDoc->linelist[j].ToggleSelect(); + DrawPSLG(); + } + + //toggle select of nearest arc segment + if(EditAction==3){ + j=pDoc->ClosestArcSegment(mx,my); + if(j>=0) pDoc->arclist[j].ToggleSelect(); + DrawPSLG(); + } + //toggle select of nearest blocklabel + if(EditAction==2){ + j=pDoc->ClosestBlockLabel(mx,my); + if(j>=0) pDoc->blocklist[j].ToggleSelect(); + DrawPSLG(); + } + + if(EditAction==4){ + int clnode,clseg,claseg,cllbl; + double dnode,dseg,daseg,dlbl,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // find distance to closest block label; + cllbl=pDoc->ClosestBlockLabel(mx,my); + if(cllbl>=0) dlbl=pDoc->blocklist[cllbl].GetDistance(mx,my); + else dlbl=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InGroup; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InGroup; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InGroup; + } + if ((dlbl=0)){ + d=dlbl; + j=pDoc->blocklist[cllbl].InGroup; + } + + if (j<1) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InGroup==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InGroup==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InGroup==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].InGroup==j) pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void ChdrawView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CView::OnLButtonDblClk(nFlags, point); +} + +void ChdrawView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + + ChdrawDoc *pDoc=GetDocument(); + if (EditAction==0) + { + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + int j; + CString ss; + + sprintf(s,"Closest node: (%g,%g)\n",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + ss+=s; + + ss+="Nodal Property: "; + sprintf(s,"\n"); + for(j=0;jnodeproplist.GetSize();j++) + { + if(pDoc->nodeproplist[j].PointName== + pDoc->nodelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->nodelist[i].BoundaryMarker); + } + } + ss+=s; + + sprintf(s,"In Group: %i\n",pDoc->nodelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->nodelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->nodelist[i].InConductor); + } + } + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->nodelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==1) + { + int i=pDoc->ClosestSegment(mx,my); + int j; + CString ss; + + if(i>=0){ + char s[256]; + sprintf(s,"Length of closest segment: %g\n", + pDoc->LineLength(i)); + + ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->linelist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->linelist[i].BoundaryMarker); + } + } + ss+=s; + + ss+="Grid spacing: "; + if (pDoc->linelist[i].MaxSideLength<=0) + sprintf(s,"\n"); + else sprintf(s,"%g\n",pDoc->linelist[i].MaxSideLength); + ss+=s; + sprintf(s,"In Group: %i\n",pDoc->linelist[i].InGroup); + ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->linelist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->linelist[i].InConductor); + } + } + ss+=s; + + if(pDoc->linelist[i].Hidden==TRUE) + ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->linelist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==2) + { + int i=pDoc->ClosestBlockLabel(mx,my); + int j,k; + if(i>=0){ + char s[256]; + sprintf(s,"Closest block label: (%g,%g)\n",pDoc->blocklist[i].x, + pDoc->blocklist[i].y); + CString ss=s; + ss+="Block Material: "; + k=-1; + sprintf(s,"\n"); + if (pDoc->blocklist[i].BlockType=="") + { + sprintf(s,"\n"); + } + else for(j=0;jblockproplist.GetSize();j++) + { + if(pDoc->blockproplist[j].BlockName== + pDoc->blocklist[i].BlockType) + { + sprintf(s,"%s\n", (const char *) pDoc->blocklist[i].BlockType); + k=j; + } + } + ss+=s; + + ss+="Mesh size: "; + if (pDoc->blocklist[i].MaxArea==0) + sprintf(s,"\n"); + else sprintf(s,"%g\n", + floor(2.e07*sqrt(pDoc->blocklist[i].MaxArea/PI) + +0.5)/1.e07 ); + ss+=s; + + sprintf(s,"In Group: %i",pDoc->blocklist[i].InGroup); + ss+=s; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->blocklist[i].ToggleSelect(); + DrawPSLG(); + } + } + + if (EditAction==3) + { + int i=pDoc->ClosestArcSegment(mx,my); + if(i>=0){ + char s[256]; + CString ss; + int j; + double R; + CComplex c; + + sprintf(s,"Angle spanned by closest arc: %g deg\n", + pDoc->arclist[i].ArcLength); ss+=s; + pDoc->GetCircle(pDoc->arclist[i],c,R); + c=Chop(c); + sprintf(s,"Radius of associated circle: %g\n",R); ss+=s; + sprintf(s,"Center of associated circle: (%g,%g)\n",Re(c),Im(c)); ss+=s; + ss+="Boundary Property: "; + + sprintf(s,"\n"); + for(j=0;jlineproplist.GetSize();j++) + { + if(pDoc->lineproplist[j].BdryName== + pDoc->arclist[i].BoundaryMarker) + { + sprintf(s,"%s\n", (const char *) pDoc->arclist[i].BoundaryMarker); + } + } + ss+=s; + sprintf(s,"Grid spacing: %g deg\n",pDoc->arclist[i].MaxSideLength); ss+=s; + sprintf(s,"In Group: %i\n",pDoc->arclist[i].InGroup); ss+=s; + + ss+="In Conductor: "; + sprintf(s,"\n"); + for(j=0;jcircproplist.GetSize();j++) + { + if(pDoc->circproplist[j].CircName== + pDoc->arclist[i].InConductor) + { + sprintf(s,"%s", (const char *) pDoc->arclist[i].InConductor); + } + } + ss+=s; + + if(pDoc->arclist[i].Hidden==TRUE) ss+="\nHidden in postprocessor"; + + AfxMessageBox(ss,MB_ICONINFORMATION); + pDoc->arclist[i].ToggleSelect(); + DrawPSLG(); + } + } + CView::OnRButtonDblClk(nFlags, point); +} + +void ChdrawView::OnMakeMesh() +{ + ChdrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved.",MB_OK | MB_ICONEXCLAMATION,0); + return; + } + + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + BOOL LoadMesh=TheDoc->LoadMesh(); + if (bLinehook==FALSE) EndWaitCursor(); + + if(LoadMesh==TRUE){ + MeshUpToDate=TRUE; + if(MeshFlag==FALSE) OnShowMesh(); + else InvalidateRect(NULL); + CString s; + s.Format("Created mesh with %i nodes",TheDoc->meshnode.GetSize()); + if (TheDoc->greymeshline.GetSize()!=0) + s+="\nGrey mesh lines denote regions\nthat have no block label."; + if(bLinehook==FALSE) AfxMessageBox(s,MB_ICONINFORMATION); + else lua_pushnumber(lua,(int) TheDoc->meshnode.GetSize()); + } + +} + +void ChdrawView::OnMenuAnalyze() +{ + + int i,j,k; + ChdrawDoc *TheDoc = GetDocument(); + BOOL bFlag=FALSE; + BOOL bExteriorDefined=TRUE; + + ASSERT_VALID(TheDoc); + + // check to see if all blocklabels are kosher... + if (TheDoc->blocklist.GetSize()==0){ + MsgBox("No block information has been defined\nCannot analyze the problem"); + return; + } + + for(i=0,bFlag=FALSE;iblocklist.GetSize();i++) + { + for(k=0,j=0;kblockproplist.GetSize();k++) + if (TheDoc->blocklist[i].BlockType!=TheDoc->blockproplist[k].BlockName) j++; + if((j==TheDoc->blockproplist.GetSize()) && (TheDoc->blocklist[i].BlockType!="")) + { + if(bFlag==FALSE) OnBlockOp(); + bFlag=TRUE; + TheDoc->blocklist[i].IsSelected=TRUE; + } + } + + if(bFlag==TRUE){ + InvalidateRect(NULL); + CString ermsg="Material properties have not\n"; + ermsg+= "been defined for all block labels\n"; + ermsg+= "cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + + + + // check to see if all of the input points are on r>=0 for axisymmetric problems. + if(TheDoc->ProblemType==1) + { + for(k=0;knodelist.GetSize();k++) + if(TheDoc->nodelist[k].x<-(1.e-6)) + { + InvalidateRect(NULL); + CString ermsg="The problem domain must lie in\n"; + ermsg+= "r>=0 for axisymmetric problems.\n"; + ermsg+= "Cannot analyze the problem."; + MsgBox(ermsg); + return; + } + + + // check to see if all block defined to be in an axisymmetric external region are isotropic + for(k=0;kblocklist.GetSize();k++) + { + if(TheDoc->blocklist[k].IsExternal){ + if ((TheDoc->extRi==0) || (TheDoc->extRo==0)) bExteriorDefined=FALSE; + for(i=0;iblockproplist.GetSize();i++) + if(TheDoc->blocklist[k].BlockType==TheDoc->blockproplist[i].BlockName) + { + if(TheDoc->blockproplist[i].Kx!=TheDoc->blockproplist[i].Ky) bFlag=TRUE; + } + } + } + if(bFlag) + { + InvalidateRect(NULL); + CString ermsg="Only istropic materials are allowed\n"; + ermsg+= "in axisymmetric external regions.\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + + if(!bExteriorDefined) + { + InvalidateRect(NULL); + CString ermsg="Some block labels have been specific as placed in\n"; + ermsg+= "an axisymmetric exterior region, but no properties\n"; + ermsg+= "have been adequately defined for the exterior region\n"; + ermsg+= "Cannot analyze the problem"; + MsgBox(ermsg); + return; + } + } + + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("A data file must be loaded,\nor the current data must saved.",MB_OK | MB_ICONEXCLAMATION,0); + return; + } + if (TheDoc->OnSaveDocument(pn)==FALSE) return; + + if (bLinehook==FALSE) BeginWaitCursor(); + if (TheDoc->HasPeriodicBC()==TRUE){ + if (TheDoc->FunnyOnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + TheDoc->UnselectAll(); + return; + } + } + else{ + if (TheDoc->OnWritePoly()==FALSE){ + if (bLinehook==FALSE) EndWaitCursor(); + return; + } + } + if (bLinehook==FALSE) EndWaitCursor(); + + char CommandLine[512]; + CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\""; + + if(bLinehook==FALSE) + sprintf(CommandLine,"\"%shsolv.exe\" %s", (const char *) BinDir, (const char *) rootname); + else + sprintf(CommandLine,"\"%shsolv.exe\" %s bLinehook", (const char *) BinDir, (const char *) rootname); + + CString MyPath=pn.Left(pn.ReverseFind('\\')); + + STARTUPINFO StartupInfo2 = {0}; + PROCESS_INFORMATION ProcessInfo2; + StartupInfo2.cb = sizeof(STARTUPINFO); + StartupInfo2.dwFlags = STARTF_FORCEOFFFEEDBACK; + if(bLinehook==HiddenLua){ + StartupInfo2.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK; + // SHOWNOACTIVATE doesn't steal focus to others + StartupInfo2.wShowWindow = SW_SHOWMINNOACTIVE; + } + if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE, + 0, NULL, MyPath, &StartupInfo2, &ProcessInfo2)) + { + if(bLinehook!=FALSE) + { + DWORD ExitCode; + hProc=ProcessInfo2.hProcess; + do{ + GetExitCodeProcess(ProcessInfo2.hProcess,&ExitCode); + ((CFemmApp *)AfxGetApp())->line_hook(lua,NULL); + Sleep(1); + } while(ExitCode==STILL_ACTIVE); + hProc=NULL; + + if (ExitCode==1) + MsgBox("Material properties have not been defined for all regions"); + if (ExitCode==2) + MsgBox("problem loading mesh"); + if (ExitCode==3) + MsgBox("problem renumbering node points"); + if (ExitCode==4) + MsgBox("couldn't allocate enough space for matrices"); + if (ExitCode==5) + MsgBox("Couldn't solve the problem"); + if (ExitCode==6) + MsgBox("couldn't write results to disk"); + if (ExitCode==7) + MsgBox("problem loading input file"); + } + CloseHandle(ProcessInfo2.hProcess); + CloseHandle(ProcessInfo2.hThread); + } + else + { + MsgBox("Problem executing the solver"); + return; + } + +} + +void ChdrawView::OnMenuViewres() +{ + // TODO: Add your command handler code here + ChdrawDoc *TheDoc = GetDocument(); + + ASSERT_VALID(TheDoc); + CString pn = TheDoc->GetPathName(); + if (pn.GetLength()==0){ + MsgBox("No results to display",MB_OK | MB_ICONEXCLAMATION,0); + return; + } + + CString rootname= "\"" + pn.Left(pn.ReverseFind('.'))+".anh\""; + ((CFemmApp *) AfxGetApp())->HOCheckIfAlreadyOpen(rootname); + AfxGetApp( )->OpenDocumentFile(rootname); +} + +void ChdrawView::OnUndo() +{ + ChdrawDoc *TheDoc = GetDocument(); + TheDoc->Undo(); + TheDoc->UnselectAll(); + InvalidateRect(NULL); +} + +void ChdrawView::OnKbdZoom() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]UpdateUndo(); + pDoc->RotateMove(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateMove(dlg.m_deltax,dlg.m_deltay,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void ChdrawView::OnCopyObjects() +{ + // TODO: Add your command handler code here + CCopyDlg dlg; + ChdrawDoc *pDoc=GetDocument(); + + dlg.m_aboutx=0; + dlg.m_abouty=0; + dlg.m_shiftangle=0; + dlg.m_deltax=0; + dlg.m_deltay=0; + dlg.IsMove=FALSE; + dlg.m_ncopies=1; + + if(dlg.DoModal()==IDOK) + { + if(dlg.BtnState==0) // Rotate + { + pDoc->UpdateUndo(); + pDoc->RotateCopy(CComplex(dlg.m_aboutx,dlg.m_abouty), + dlg.m_shiftangle,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + if(dlg.BtnState==1) // Translate + { + pDoc->UpdateUndo(); + pDoc->TranslateCopy(dlg.m_deltax,dlg.m_deltay,dlg.m_ncopies,EditAction); + pDoc->meshnode.RemoveAll(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + MeshFlag=FALSE; + MeshUpToDate=FALSE; + InvalidateRect(NULL); + } + } +} + +void ChdrawView::OnDxfin() +{ + // TODO: Add your command handler code here + CString dxffile; + CFileDialog *fname_dia; + ChdrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + TRUE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if(pDoc->ReadDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't read specified DXF file\nMake sure the the specified file\nis in ASCII DXF r12 format"); + pDoc->NoDraw=FALSE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } +} + +void ChdrawView::OnPurgemesh() +{ + // TODO: Add your command handler code here + ChdrawDoc *pDoc=GetDocument(); + pDoc->meshnode.RemoveAll(); + pDoc->meshnode.FreeExtra(); + pDoc->meshline.RemoveAll(); + pDoc->greymeshline.RemoveAll(); + pDoc->meshline.FreeExtra(); + pDoc->greymeshline.FreeExtra(); + MeshUpToDate=FALSE; + if (MeshFlag==TRUE){ + MeshFlag=FALSE; + InvalidateRect(NULL); + } + +} + +void ChdrawView::OnDxfwrite() +{ + CString dxffile; + CFileDialog *fname_dia; + ChdrawDoc *pDoc=GetDocument(); + + fname_dia=new CFileDialog( + FALSE, + "dxf | * ", + dxffile, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "CAD Drawing (*.dxf) | *.dxf; *.DXF | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + return; + } + dxffile=fname_dia->GetPathName(); + delete[] fname_dia; + + if (bLinehook==FALSE) BeginWaitCursor(); + if(pDoc->WriteDXF(dxffile)==TRUE){ + if (bLinehook==FALSE) EndWaitCursor(); + pDoc->FirstDraw=TRUE; + MeshFlag=FALSE; + InvalidateRect(NULL); + } + else{ + MsgBox("Couldn't write specified DXF file"); + if (bLinehook==FALSE) EndWaitCursor(); + } +} + + +BOOL ChdrawView::OnEraseBkgnd(CDC* pDC) +{ + + // idea is to always make the background white. + // source code copied from: + // Frequently Asked Questions About Foundation Classes + + // Set brush to desired background color + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + return TRUE; + +} + +void ChdrawView::OnPanDown() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox=ox-0.25*x/mag; + oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void ChdrawView::OnPanLeft() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void ChdrawView::OnPanRight() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; +// oy-=0.25*y/mag; + + InvalidateRect(NULL); +} + +void ChdrawView::OnPanUp() +{ + // TODO: Add your command handler code here + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; +// ox+=0.25*x/mag; + oy+=0.25*y/mag; + + InvalidateRect(NULL); +} + +void ChdrawView::OnMenuMatlib() +{ + hdCLibDlg dlg; + + dlg.pDoc=GetDocument(); + dlg.BinDir=BinDir; + + dlg.DoModal(); +} + +void ChdrawView::OnOpenSelected() +{ + ChdrawDoc *pDoc=GetDocument(); + + if(EditAction==1) pDoc->OpSegDlg(); + if(EditAction==2){ + if (pDoc->OpBlkDlg()==TRUE) + InvalidateRect(NULL); + } + if(EditAction==3){ + pDoc->OpArcSegDlg(); + InvalidateRect(NULL); + } + if(EditAction==0) pDoc->OpNodeDlg(); + + if(EditAction==4) pDoc->OpGrpDlg(); + + pDoc->UnselectAll(); + DrawPSLG(); +} + +void ChdrawView::OnEditScale() +{ + // TODO: Add your command handler code here + CScaleDlg dlg; + ChdrawDoc *pDoc=GetDocument(); + double x[2],y[2],R,dt; + int i,j,k; + CComplex p,s,c; + BOOL bFlag=FALSE; + + // look at points, block labels, and arcs to get bounding box. + for(i=0;inodelist.GetSize();i++) + if(pDoc->nodelist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[i].x; x[1]=x[0]; + y[0]=pDoc->nodelist[i].y; y[1]=y[0]; + } + if(pDoc->nodelist[i].xnodelist[i].x; + if(pDoc->nodelist[i].x>x[1]) x[1]=pDoc->nodelist[i].x; + if(pDoc->nodelist[i].ynodelist[i].y; + if(pDoc->nodelist[i].y>y[1]) y[1]=pDoc->nodelist[i].y; + } + + for(i=0;iblocklist.GetSize();i++) + if(pDoc->blocklist[i].IsSelected==TRUE){ + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->blocklist[i].x; x[1]=x[0]; + y[0]=pDoc->blocklist[i].y; y[1]=y[0]; + } + if(pDoc->blocklist[i].xblocklist[i].x; + if(pDoc->blocklist[i].x>x[1]) x[1]=pDoc->blocklist[i].x; + if(pDoc->blocklist[i].yblocklist[i].y; + if(pDoc->blocklist[i].y>y[1]) y[1]=pDoc->blocklist[i].y; + } + + for(i=0;ilinelist.GetSize();i++) + if(pDoc->linelist[i].IsSelected==TRUE){ + for(j=0;j<2;j++){ + if(j==0) k=pDoc->linelist[i].n0; + else k=pDoc->linelist[i].n1; + if(bFlag==FALSE){ + bFlag=TRUE; + x[0]=pDoc->nodelist[k].x; x[1]=x[0]; + y[0]=pDoc->nodelist[k].y; y[1]=y[0]; + } + if(pDoc->nodelist[k].xnodelist[k].x; + if(pDoc->nodelist[k].x>x[1]) x[1]=pDoc->nodelist[k].x; + if(pDoc->nodelist[k].ynodelist[k].y; + if(pDoc->nodelist[k].y>y[1]) y[1]=pDoc->nodelist[k].y; + } + } + + + for(i=0;iarclist.GetSize();i++) + if(pDoc->arclist[i].IsSelected==TRUE){ + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].mySideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + s=exp(I*dt); + for(j=0;jx[1]) x[1]=p.re; + if(p.imy[1]) y[1]=p.im; + } + } + + if(bFlag==FALSE) return; + + dlg.m_scalefactor=1.; + dlg.m_basex=(x[1]+x[0])/2.; + dlg.m_basey=(y[1]+y[0])/2.; + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->ScaleMove(dlg.m_basex,dlg.m_basey,dlg.m_scalefactor,EditAction); + InvalidateRect(NULL); + } +} + +void ChdrawView::OnEditMirror() +{ + // TODO: Add your command handler code here + CMirrorDlg dlg; + ChdrawDoc *pDoc=GetDocument(); + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + pDoc->MirrorSelected(dlg.m_pax,dlg.m_pay, + dlg.m_pbx,dlg.m_pby,EditAction); + InvalidateRect(NULL); + } +} + +void ChdrawView::OnEditCut() +{ + ChdrawDoc *pDoc=GetDocument(); + BOOL flag; + + pDoc->UpdateUndo(); + if(EditAction==0) flag=pDoc->DeleteSelectedNodes(); + if(EditAction==1) flag=pDoc->DeleteSelectedSegments(); + if(EditAction==2) flag=pDoc->DeleteSelectedBlockLabels(); + if(EditAction==3) flag=pDoc->DeleteSelectedArcSegments(); + if(EditAction==4){ + flag=FALSE; + if (pDoc->DeleteSelectedSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedArcSegments()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedNodes()==TRUE) flag=TRUE; + if (pDoc->DeleteSelectedBlockLabels()==TRUE) flag=TRUE; + } + if (flag==TRUE){ + MeshUpToDate=FALSE; + if(MeshFlag==TRUE) OnShowMesh(); + else InvalidateRect(NULL); + } + +} + + +BOOL ChdrawView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"hdraw.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_action); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_mag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%lf",&d_gridsize); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_showorigin); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_snapgrid); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_shownames); + q[0]=NULL; + } + } + fclose(fp); + return TRUE; + } + + return FALSE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + + +BOOL ChdrawView::WritePreferences() +{ + FILE *fp; + CString fname; + ChdrawDoc *pDoc=GetDocument(); + + fname=BinDir+"hdraw.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("NameColor",NameColor,fp); + fprintf(fp," = %i\n",d_action); + fprintf(fp," = %g\n",d_mag); + fprintf(fp," = %g\n",d_gridsize); + fprintf(fp," = %i\n",d_showgrid); + fprintf(fp," = %i\n",d_snapgrid); + fprintf(fp," = %i\n",d_shownames); + fprintf(fp," = %i\n",d_showorigin); + fprintf(fp," = %i\n",pDoc->d_type); + fprintf(fp," = %i\n",pDoc->d_length); + fprintf(fp," = %g\n",pDoc->d_prec); + fprintf(fp," = %g\n",pDoc->d_minangle); + fprintf(fp," = %g\n",pDoc->d_depth); + fprintf(fp," = %i\n",pDoc->d_coord); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void ChdrawView::OnViewShownames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + InvalidateRect(NULL); +} + +void ChdrawView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void ChdrawView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +void ChdrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if (bActivate && pActivateView==this) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(5); + + MFrm->m_dlgBar.ShowWindow(SW_HIDE); + CheckIt(); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL ChdrawView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void ChdrawView::OnViewShowOrphans() +{ + ChdrawDoc *pDoc=GetDocument(); + + OnGroupOp(); + pDoc->SelectOrphans(); + InvalidateRect(NULL); +} + +void ChdrawView::OnUpdateEditExterior(CCmdUI* pCmdUI) +{ + if(GetDocument()->ProblemType) pCmdUI->Enable ( TRUE); + else pCmdUI->Enable ( FALSE ); +} + +void ChdrawView::OnCreateRadius() +{ + SelectWndFlag=FALSE; + ZoomWndFlag=FALSE; + SelectCircFlag=FALSE; + CreateRadiusFlag=TRUE; + + StatBar->SetPaneText(0,"SELECT POINT AT WHICH A RADIUS IS DESIRED",TRUE); +} + +void ChdrawView::OnMakeABC() +{ + CMakeABCDlg dlg; + ChdrawDoc *pDoc=GetDocument(); + + double xx[2],yy[2]; + if (GetBoundingBox(xx,yy)==0) return; + + if(pDoc->ProblemType == 0) // 2D planar case + { + dlg.abcr=0.75*abs((xx[0]+I*yy[0])-(xx[1]+I*yy[1])); + dlg.abcx=(xx[0]+xx[1])/2.0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.n=1; + } + else{ //Axi case + dlg.abcx=0; + dlg.abcy=(yy[0]+yy[1])/2.0; + dlg.abcr=1.5*abs(xx[1]+I*(yy[1]-yy[0])/2.0); + dlg.n=0; + } + + dlg.abcn=7; // suggested default number of layers + + if(dlg.DoModal()==IDOK){ + pDoc->UpdateUndo(); + CString LuaCmd; + LuaCmd.Format("hi_makeABC(%i,%g,%g,%g,%i)",dlg.abcn,dlg.abcr,dlg.abcx,dlg.abcy,dlg.n); + lua_dostring(lua,LuaCmd); + } +} diff --git a/femm/hdrawView.h b/femm/hdrawView.h new file mode 100644 index 0000000..ee38b98 --- /dev/null +++ b/femm/hdrawView.h @@ -0,0 +1,167 @@ +// hdrawView.h : interface of the ChdrawView class +// +///////////////////////////////////////////////////////////////////////////// + +class ChdrawView : public CView +{ +protected: // create from serialization only + ChdrawView(); + DECLARE_DYNCREATE(ChdrawView) + +// Attributes +public: + ChdrawDoc* GetDocument(); + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void DrawPSLG(); + void EnterPoint(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void OnNewDocument(); + void CheckIt(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL ShowNames; + BOOL MeshUpToDate; + int FirstPoint; + int ZoomWndFlag; + int SelectWndFlag; + int SelectCircFlag; + int CreateRadiusFlag; + double wzx,wzy; + double MaxSeg,ArcAngle; + + + // Colors used to render the view + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF NodeColor; + COLORREF NameColor; + + // default view properties + int d_action; //=0; + double d_mag; //=100.; + double d_gridsize; //=0.25; + BOOL d_showgrid; //=TRUE; + BOOL d_snapgrid; //=FALSE; + BOOL d_shownames; //=FALSE; + BOOL d_showorigin; + + CString BinDir; // pathname for other FEMM executables + CArray ZoomPix; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ChdrawView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual void OnInitialUpdate(); // called first time after construct + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + void lua_zoomin(); + void lua_zoomout(); + void lua_zoomnatural(); + void lnu_show_mesh(); + void lnu_purge_mesh(); + void lnuMakeMesh(); + void lnu_analyze(int bShow); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL GetBoundingBox(double *x, double *y); + + virtual ~ChdrawView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(ChdrawView) + afx_msg void OnNodeOp(); + afx_msg void OnSegmentOp(); + afx_msg void OnBlockOp(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnZoomIn(); + afx_msg void OnZoomOut(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnEditCopy(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomWnd(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMakeMesh(); + afx_msg void OnMenuAnalyze(); + afx_msg void OnMenuViewres(); + afx_msg void OnArcsegOp(); + afx_msg void OnUndo(); + afx_msg void OnKbdZoom(); + afx_msg void OnMoveObjects(); + afx_msg void OnCopyObjects(); + afx_msg void OnDxfin(); + afx_msg void OnPurgemesh(); + afx_msg void OnDxfwrite(); + afx_msg void OnSelectwnd(); + afx_msg void OnBDSelectCirc(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnMenuMatlib(); + afx_msg void OnGroupOp(); + afx_msg void OnOpenSelected(); + afx_msg void OnEditScale(); + afx_msg void OnEditMirror(); + afx_msg void OnEditCut(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnViewShownames(); + afx_msg void OnViewShowOrphans(); + afx_msg void OnCreateRadius(); + afx_msg void OnUpdateEditExterior(CCmdUI* pCmdUI); + afx_msg void OnMakeABC(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + +}; + +#ifndef _DEBUG // debug version in hdrawView.cpp +inline ChdrawDoc* ChdrawView::GetDocument() + { return (ChdrawDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/femm/hv_BlockInt.cpp b/femm/hv_BlockInt.cpp new file mode 100644 index 0000000..c6e2dd8 --- /dev/null +++ b/femm/hv_BlockInt.cpp @@ -0,0 +1,62 @@ +// BlockInt.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_BlockInt.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCBlockInt dialog + + +hvCBlockInt::hvCBlockInt(CWnd* pParent /*=NULL*/) + : CDialog(hvCBlockInt::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCBlockInt) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void hvCBlockInt::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCBlockInt) + DDX_Control(pDX, IDC_HV_BINTTYPE, m_binttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(hvCBlockInt, CDialog) + //{{AFX_MSG_MAP(hvCBlockInt) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCBlockInt message handlers + +BOOL hvCBlockInt::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + binttype=0; + m_binttype.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hvCBlockInt::OnOK() +{ + // TODO: Add extra validation here + binttype=m_binttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/hv_BlockInt.h b/femm/hv_BlockInt.h new file mode 100644 index 0000000..06f7a8d --- /dev/null +++ b/femm/hv_BlockInt.h @@ -0,0 +1,38 @@ +// BlockInt.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCBlockInt dialog + +class hvCBlockInt : public CDialog +{ +// Construction +public: + hvCBlockInt(CWnd* pParent = NULL); // standard constructor + + int binttype; + +// Dialog Data + //{{AFX_DATA(hvCBlockInt) + enum { IDD = IDD_HV_BLOCKINT }; + CComboBox m_binttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCBlockInt) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCBlockInt) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/hv_CircDlg.cpp b/femm/hv_CircDlg.cpp new file mode 100644 index 0000000..bfb6a11 --- /dev/null +++ b/femm/hv_CircDlg.cpp @@ -0,0 +1,79 @@ +// CircDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include "hv_problem.h" +#include "xyplot.h" +#include "hviewdoc.h" +#include "hv_CircDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCCircDlg dialog + + +hvCCircDlg::hvCCircDlg(CWnd* pParent /*=NULL*/) + : CDialog(hvCCircDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCCircDlg) + //}}AFX_DATA_INIT +} + + +void hvCCircDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCCircDlg) + DDX_Control(pDX, IDC_HV_CIRCNAME, m_circname); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(hvCCircDlg, CDialog) + //{{AFX_MSG_MAP(hvCCircDlg) + ON_CBN_SELCHANGE(IDC_HV_CIRCNAME, OnSelchangeCircname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCCircDlg message handlers +////////////////////////////////////////////////////// +void hvCCircDlg::OnSelchangeCircname() +{ + if(NumCircuits==0) return; + + int k; + CString crslt; + + k=m_circname.GetCurSel(); + crslt.Format("Temperature = %g K\r\nHeat Flux = %g W", + TheDoc->circproplist[k].V,TheDoc->circproplist[k].q); + SetDlgItemText(IDC_HV_CIRCRESULT,crslt); + +} + +BOOL hvCCircDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName); + + if(NumCircuits!=0){ + m_circname.SetCurSel(0); + OnSelchangeCircname(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/hv_CircDlg.h b/femm/hv_CircDlg.h new file mode 100644 index 0000000..0b376aa --- /dev/null +++ b/femm/hv_CircDlg.h @@ -0,0 +1,39 @@ +// CircDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCCircDlg dialog + +class hvCCircDlg : public CDialog +{ +// Construction +public: + hvCCircDlg(CWnd* pParent = NULL); // standard constructor + + ChviewDoc *TheDoc; + int NumCircuits; + +// Dialog Data + //{{AFX_DATA(hvCCircDlg) + enum { IDD = IDD_HV_CIRCPROPS }; + CComboBox m_circname; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCCircDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCCircDlg) + afx_msg void OnSelchangeCircname(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/hv_CplotDlg2.cpp b/femm/hv_CplotDlg2.cpp new file mode 100644 index 0000000..8f2aad3 --- /dev/null +++ b/femm/hv_CplotDlg2.cpp @@ -0,0 +1,65 @@ +// CplotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_CplotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCCPlotDlg2 dialog + + +hvCCPlotDlg2::hvCCPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(hvCCPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCCPlotDlg2) + m_numcontours = 0; + m_showa = FALSE; + m_ahigh = 0.0; + m_alow = 0.0; + m_showmask = FALSE; + //}}AFX_DATA_INIT +} + + +void hvCCPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCCPlotDlg2) + DDX_Text(pDX, IDC_HV_NUMCONTOURS, m_numcontours); + DDV_MinMaxInt(pDX, m_numcontours, 4, 999); + DDX_Check(pDX, IDC_HV_SHOW_A, m_showa); + DDX_Text(pDX, IDC_HV_AHIGH, m_ahigh); + DDX_Text(pDX, IDC_HV_ALOW, m_alow); + DDX_Check(pDX, IDC_HV_SHOW_MASK2, m_showmask); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HV_NUMCONTOURS, m_IDC_numcontours); + DDX_Control(pDX, IDC_HV_AHIGH, m_IDC_ahigh); + DDX_Control(pDX, IDC_HV_ALOW, m_IDC_alow); +} + + +BEGIN_MESSAGE_MAP(hvCCPlotDlg2, CDialog) + //{{AFX_MSG_MAP(hvCCPlotDlg2) + ON_BN_CLICKED(IDC_HV_DFLT1, OnDflt1) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCCPlotDlg2 message handlers + +void hvCCPlotDlg2::OnDflt1() +{ + // TODO: Add your control notification handler code here + UpdateData(TRUE); + m_alow=Alb; + m_ahigh=Aub; + m_numcontours=19; + UpdateData(FALSE); +} diff --git a/femm/hv_CplotDlg2.h b/femm/hv_CplotDlg2.h new file mode 100644 index 0000000..e001640 --- /dev/null +++ b/femm/hv_CplotDlg2.h @@ -0,0 +1,42 @@ +// hv_CplotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCCPlotDlg2 dialog + +class hvCCPlotDlg2 : public CDialog +{ +// Construction +public: + hvCCPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Alb,Aub; + +// Dialog Data + //{{AFX_DATA(hvCCPlotDlg2) + enum { IDD = IDD_HV_CPLOTDLG2 }; + int m_numcontours; + BOOL m_showa; + double m_ahigh; + double m_alow; + BOOL m_showmask; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCCPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCCPlotDlg2) + afx_msg void OnDflt1(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_numcontours, m_IDC_ahigh, m_IDC_alow; +}; diff --git a/femm/hv_DPlotDlg2.cpp b/femm/hv_DPlotDlg2.cpp new file mode 100644 index 0000000..cea8e5b --- /dev/null +++ b/femm/hv_DPlotDlg2.cpp @@ -0,0 +1,99 @@ +// DPlotDlg2.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_DPlotDlg2.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCDPlotDlg2 dialog + + +hvCDPlotDlg2::hvCDPlotDlg2(CWnd* pParent /*=NULL*/) + : CDialog(hvCDPlotDlg2::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCDPlotDlg2) + m_showit = FALSE; + m_showlegend = FALSE; + m_lb2 = 0.0; + m_ub2 = 0.0; + m_gscale = FALSE; + //}}AFX_DATA_INIT +} + + +void hvCDPlotDlg2::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCDPlotDlg2) + DDX_Control(pDX, IDC_HV_DPLOTTYPE, m_dplottype); + DDX_Check(pDX, IDC_HV_SHOWIT, m_showit); + DDX_Check(pDX, IDC_HV_SHOW_LEG2, m_showlegend); + DDX_Text(pDX, IDC_HV_LB2, m_lb2); + DDX_Text(pDX, IDC_HV_UB2, m_ub2); + DDX_Check(pDX, IDC_HV_GSCALE2, m_gscale); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HV_LB2, m_IDC_lb2); + DDX_Control(pDX, IDC_HV_UB2, m_IDC_ub2); +} + + +BEGIN_MESSAGE_MAP(hvCDPlotDlg2, CDialog) + //{{AFX_MSG_MAP(hvCDPlotDlg2) + ON_BN_CLICKED(IDC_HV_RESBTN2, OnResbtn2) + ON_CBN_SELCHANGE(IDC_HV_DPLOTTYPE, OnSelchangeDplottype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCDPlotDlg2 message handlers + +void hvCDPlotDlg2::OnResbtn2() +{ + // TODO: Add your control notification handler code here + UpdateData(); + m_ub2=d_PlotBounds[DensityPlot][1]; + m_lb2=d_PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} + +BOOL hvCDPlotDlg2::OnInitDialog() +{ + CDialog::OnInitDialog(); + + DensityPlot--; + if(DensityPlot<0) DensityPlot=0; + m_dplottype.SetCurSel(DensityPlot); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hvCDPlotDlg2::OnOK() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot++; + CDialog::OnOK(); +} + +void hvCDPlotDlg2::OnSelchangeDplottype() +{ + UpdateData(); + PlotBounds[DensityPlot][1]=m_ub2; + PlotBounds[DensityPlot][0]=m_lb2; + DensityPlot=m_dplottype.GetCurSel(); + m_ub2=PlotBounds[DensityPlot][1]; + m_lb2=PlotBounds[DensityPlot][0]; + UpdateData(FALSE); +} diff --git a/femm/hv_DPlotDlg2.h b/femm/hv_DPlotDlg2.h new file mode 100644 index 0000000..08d4963 --- /dev/null +++ b/femm/hv_DPlotDlg2.h @@ -0,0 +1,49 @@ +// DPlotDlg2.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCDPlotDlg2 dialog + +class hvCDPlotDlg2 : public CDialog +{ +// Construction +public: + hvCDPlotDlg2(CWnd* pParent = NULL); // standard constructor + double Bm_l, Bm_h; + double d_PlotBounds[4][2]; + double PlotBounds[4][2]; + int DensityPlot; + +// Dialog Data + //{{AFX_DATA(hvCDPlotDlg2) + enum { IDD = IDD_HV_DPLOTDLG2 }; + CComboBox m_dplottype; + BOOL m_showit; + BOOL m_showlegend; + double m_lb2; + double m_ub2; + BOOL m_gscale; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCDPlotDlg2) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCDPlotDlg2) + afx_msg void OnResbtn2(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeDplottype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_lb2, m_IDC_ub2; +}; diff --git a/femm/hv_LIntDlg.cpp b/femm/hv_LIntDlg.cpp new file mode 100644 index 0000000..88612e4 --- /dev/null +++ b/femm/hv_LIntDlg.cpp @@ -0,0 +1,59 @@ +// LIntDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_LIntDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCLIntDlg dialog + + +hvCLIntDlg::hvCLIntDlg(CWnd* pParent /*=NULL*/) + : CDialog(hvCLIntDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCLIntDlg) + //}}AFX_DATA_INIT +} + + +void hvCLIntDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCLIntDlg) + DDX_Control(pDX, IDC_HV_LINTTYPE, m_inttype); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(hvCLIntDlg, CDialog) + //{{AFX_MSG_MAP(hvCLIntDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCLIntDlg message handlers + +BOOL hvCLIntDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_inttype.SetCurSel(0); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hvCLIntDlg::OnOK() +{ + // TODO: Add extra validation here + linttype=m_inttype.GetCurSel(); + + CDialog::OnOK(); +} diff --git a/femm/hv_LIntDlg.h b/femm/hv_LIntDlg.h new file mode 100644 index 0000000..c59f70d --- /dev/null +++ b/femm/hv_LIntDlg.h @@ -0,0 +1,38 @@ +// LIntDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCLIntDlg dialog + +class hvCLIntDlg : public CDialog +{ +// Construction +public: + hvCLIntDlg(CWnd* pParent = NULL); // standard constructor + + int linttype; + +// Dialog Data + //{{AFX_DATA(hvCLIntDlg) + enum { IDD = IDD_HV_LINEINT }; + CComboBox m_inttype; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCLIntDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCLIntDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/femm/hv_VPlotDlg.cpp b/femm/hv_VPlotDlg.cpp new file mode 100644 index 0000000..45159ac --- /dev/null +++ b/femm/hv_VPlotDlg.cpp @@ -0,0 +1,61 @@ +// VPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "hv_VPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCVPlotDlg dialog + + +hvCVPlotDlg::hvCVPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(hvCVPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCVPlotDlg) + m_vectorscalefactor = 0.0; + //}}AFX_DATA_INIT +} + + +void hvCVPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCVPlotDlg) + DDX_Control(pDX, IDC_HV_VPLOTTYPE, m_vplottype); + DDX_Text(pDX, IDC_HV_SCALEFACTOR, m_vectorscalefactor); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HV_SCALEFACTOR, m_IDC_vectorscalefactor); +} + + +BEGIN_MESSAGE_MAP(hvCVPlotDlg, CDialog) + //{{AFX_MSG_MAP(hvCVPlotDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCVPlotDlg message handlers + +void hvCVPlotDlg::OnOK() +{ + m_plottype=m_vplottype.GetCurSel(); + + CDialog::OnOK(); +} + +BOOL hvCVPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_vplottype.SetCurSel(m_plottype); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/femm/hv_VPlotDlg.h b/femm/hv_VPlotDlg.h new file mode 100644 index 0000000..5912986 --- /dev/null +++ b/femm/hv_VPlotDlg.h @@ -0,0 +1,51 @@ +#if !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) +#define AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// VPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCVPlotDlg dialog + +class hvCVPlotDlg : public CDialog +{ +// Construction +public: + hvCVPlotDlg(CWnd* pParent = NULL); // standard constructor + + int m_plottype; + CLuaEdit m_IDC_vectorscalefactor; + +// Dialog Data + //{{AFX_DATA(hvCVPlotDlg) + enum { IDD = IDD_HV_VPLOTDLG }; + CComboBox m_vplottype; + double m_vectorscalefactor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCVPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCVPlotDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VPLOTDLG_H__2CA08017_4A4D_457C_B3B3_A2F29FB62CAE__INCLUDED_) diff --git a/femm/hv_XYPlotDlg.cpp b/femm/hv_XYPlotDlg.cpp new file mode 100644 index 0000000..ae8c996 --- /dev/null +++ b/femm/hv_XYPlotDlg.cpp @@ -0,0 +1,95 @@ +// XYPlotDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include +#include +#include "hv_problem.h" +#include "xyplot.h" +#include "hviewDoc.h" +#include "hviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#include "hv_XYPlotDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// hvCXYPlotDlg dialog + + +hvCXYPlotDlg::hvCXYPlotDlg(CWnd* pParent /*=NULL*/) + : CDialog(hvCXYPlotDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(hvCXYPlotDlg) + m_ToFile = FALSE; + m_npoints = 150; + //}}AFX_DATA_INIT + ListType=0; + XYPlotType=0; + FileFormat=0; +} + + +void hvCXYPlotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(hvCXYPlotDlg) + DDX_Control(pDX, IDC_HV_FILEFORMAT, m_fileformat); + DDX_Control(pDX, IDC_HV_XYPLOTTYPE, m_XYPlotType); + DDX_Check(pDX, IDC_HV_TOFILE, m_ToFile); + DDX_Text(pDX, IDC_HV_NPOINTS, m_npoints); + DDV_MinMaxInt(pDX, m_npoints, 10, 100000); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_HV_NPOINTS, m_IDC_npoints); +} + + +BEGIN_MESSAGE_MAP(hvCXYPlotDlg, CDialog) + //{{AFX_MSG_MAP(hvCXYPlotDlg) + ON_BN_CLICKED(IDC_HV_TOFILE, OnToFileClicked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// hvCXYPlotDlg message handlers + +BOOL hvCXYPlotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_XYPlotType.AddString("T (Temperature)"); + m_XYPlotType.AddString("|F| (Magnitude of heat flux density)"); + m_XYPlotType.AddString("F . n (Normal heat flux density)"); + m_XYPlotType.AddString("F . t (Tangential heat flux density)"); + m_XYPlotType.AddString("|G| (Magnitude of field gradient)"); + m_XYPlotType.AddString("G . n (Normal temperature gradient)"); + m_XYPlotType.AddString("G . t (Tangential temperature gradient)"); + m_XYPlotType.SetCurSel(0); + + m_fileformat.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void hvCXYPlotDlg::OnOK() +{ + // TODO: Add extra validation here + XYPlotType=m_XYPlotType.GetCurSel(); + FileFormat=m_fileformat.GetCurSel(); + CDialog::OnOK(); +} + +void hvCXYPlotDlg::OnToFileClicked() +{ + UpdateData(); +} + diff --git a/femm/hv_XYPlotDlg.h b/femm/hv_XYPlotDlg.h new file mode 100644 index 0000000..44015f0 --- /dev/null +++ b/femm/hv_XYPlotDlg.h @@ -0,0 +1,46 @@ +// XYPlotDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// hvCXYPlotDlg dialog + +class hvCXYPlotDlg : public CDialog +{ +// Construction +public: + hvCXYPlotDlg(CWnd* pParent = NULL); // standard constructor + int ListType; + int XYPlotType; + int FileFormat; + ChviewDoc *pDoc; + +// Dialog Data + //{{AFX_DATA(hvCXYPlotDlg) + enum { IDD = IDD_HV_XYPLOTDLG }; + CComboBox m_fileformat; + CComboBox m_XYPlotType; + BOOL m_ToFile; + int m_npoints; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(hvCXYPlotDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(hvCXYPlotDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnToFileClicked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_npoints; +}; diff --git a/femm/hv_problem.cpp b/femm/hv_problem.cpp new file mode 100644 index 0000000..4e7f750 --- /dev/null +++ b/femm/hv_problem.cpp @@ -0,0 +1,170 @@ +#include "stdafx.h" +#include "hv_problem.h" + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CNode::CNode() +{ + x=0.; + y=0.; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +CComplex CNode::CC() +{ + return (x+I*y); +} + +double CNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +void CNode::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMeshNode construction + +CMeshNode::CMeshNode() +{ + x=y=T=0; + Q=FALSE; + msk=0; + IsSelected=FALSE; +} + +CComplex CMeshNode::CC() +{ + return (x+I*y); +} + +double CMeshNode::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +///////////////////////////////////////////////////////////////////////////// +// CSegment construction + +CSegment::CSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} +///////////////////////////////////////////////////////////////////////////// +// CArcSegment construction + +CArcSegment::CArcSegment() +{ + n0=0; + n1=0; + IsSelected=FALSE; + MaxSideLength=-1; + ArcLength=90.; + BoundaryMarker=-1; + InConductor=-1; + InGroup=0; +} + +void CArcSegment::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CNode construction + +CBlockLabel::CBlockLabel() +{ + x=0.; + y=0.; + MaxArea=0.; + IsSelected=FALSE; + InGroup=0; + BlockType=-1; + IsExternal=FALSE; + IsDefault=FALSE; +} + +void CBlockLabel::ToggleSelect() +{ + if (IsSelected==TRUE) IsSelected=FALSE; + else IsSelected=TRUE; +} + +double CBlockLabel::GetDistance(double xo, double yo) +{ + return sqrt((x-xo)*(x-xo) + (y-yo)*(y-yo)); +} + +CMaterialProp::CMaterialProp() +{ + BlockName="New Material"; + Kx=Ky=1; + Kt=0; + qv=0; +} + +CBoundaryProp::CBoundaryProp() +{ + BdryName="New Boundary"; + BdryFormat=0; + Tset=Tinf=h=beta=qs=0; + InConductor=""; +} + +CComplex CMaterialProp::GetK(double t) +{ + int i,j; + + // Kx returned as real part; + // Ky returned as imag part + + if (npts==0) return (Kx+I*Ky); + if (npts==1) return (Im(Kn[0])*(1+I)); + if (t<=Re(Kn[0])) return (Im(Kn[0])*(1+I)); + if (t>=Re(Kn[npts-1])) return (Im(Kn[npts-1])*(1+I)); + + for(i=0,j=1;j=Re(Kn[i])) && (t<=Re(Kn[j]))) + { + return (1+I)*(Im(Kn[i])+Im(Kn[j]-Kn[i])*Re(t-Kn[i])/Re(Kn[j]-Kn[i])); + } + } + + return (Kx+I*Ky); +} + +CPointProp::CPointProp() +{ + PointName="New Point Property"; + InConductor=""; + V=qp=0; +} + +CCircuit::CCircuit() +{ + CircName="New Circuit"; + V=q=0; + CircType=0; +} diff --git a/femm/hv_problem.h b/femm/hv_problem.h new file mode 100644 index 0000000..1b537a4 --- /dev/null +++ b/femm/hv_problem.h @@ -0,0 +1,203 @@ +namespace hviewtype +{ + +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each control point. + +class CNode +{ + public: + CNode(); + + double x,y; + int xs,ys; + BOOL IsSelected; + int BoundaryMarker; + int InGroup,InConductor; + + double GetDistance(double xo, double yo); + CComplex CC(); + void ToggleSelect(); + + private: + +}; + +class CMeshNode +{ + public: + CMeshNode(); + + double x,y,T; + double msk; + int xs,ys; + BOOL Q,IsSelected; + + double GetDistance(double xo, double yo); + CComplex CC(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CSegment -- structure that holds information about lines joining control pts + +class CSegment +{ + public: + CSegment(); + + int n0,n1; + double MaxSideLength; + BOOL IsSelected; + BOOL Hidden; + int BoundaryMarker; + int InGroup,InConductor; + + void ToggleSelect(); + + private: + +}; + +class CArcSegment +{ + public: + CArcSegment(); + + int n0,n1; + BOOL IsSelected; + BOOL Hidden; + double MaxSideLength,ArcLength; + int BoundaryMarker; + int InGroup, InConductor; + + void ToggleSelect(); + + private: + +}; +///////////////////////////////////////////////////////////////////////////// +// CBlockLabel -- structure that holds block label information + +class CBlockLabel +{ + public: + CBlockLabel(); + + double x,y; + double MaxArea; + double MagDir; + BOOL IsSelected; + int BlockType; + int InGroup; + BOOL IsExternal; + BOOL IsDefault; + + void ToggleSelect(); + double GetDistance(double xo, double yo); + + private: + +}; + +class CMaterialProp +{ + public: + + CString BlockName; + double Kx,Ky; // thermal conductivity for linear (possibly anisotropic) regions + double Kt; // volumetric heat capacity + double qv; // volume heat generation + + // properties for nonlinear conductivity + int npts; // number of points in the nonlinear conductivity curve + CComplex Kn[128]; // here, I'm being _very_ lazy by defining a fixed-length buffer for the + // thermal conductivity data points. + CComplex GetK(double t); + + CMaterialProp(); + + private: +}; + +class CBoundaryProp +{ + public: + + CBoundaryProp(); + + CString BdryName; + CString InConductor; + int BdryFormat; + + double Tset; // Fixed value of temperature for BdryFormat=0; + double Tinf; // External temperature for convection or radiation + double qs; // Heat flux; + double beta; // radiosity coefficient + double h; // Heat transfer coefficient + + private: +}; + +class CPointProp +{ + public: + + CPointProp(); + + CString PointName; + CString InConductor; + double V,qp; + + private: +}; + +class CCircuit +{ + public: + + CCircuit(); + + CString CircName; + double V,q; + int CircType; + + private: + +}; + +class CElement +{ + public: + + int p[3]; + int blk,lbl; + CComplex D; // elemental flux density + CComplex d[3]; // smoothed flux density at corners + CComplex ctr; + double rsqr; + int n[3]; // Add 3 ints to store elem's neigh. + + CComplex E(); + + private: +}; + +class CPointVals +{ + public: + + double T; // temperature + CComplex F; // heat flux density + CComplex K; // thermal conductivity + CComplex G; // temperature gradient + + CPointVals(); + + private: +}; + +} + +using namespace hviewtype; \ No newline at end of file diff --git a/femm/hviewDoc.cpp b/femm/hviewDoc.cpp new file mode 100644 index 0000000..71d8356 --- /dev/null +++ b/femm/hviewDoc.cpp @@ -0,0 +1,2002 @@ +// hviewDoc.cpp : implementation of the ChviewDoc class +// + + +#include "stdafx.h" +#include +#include +#include "hv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "hviewDoc.h" +#include "hviewView.h" +#include "MainFrm.h" + +#include "lua.h" + +#define AXISYMMETRIC 1 + +extern lua_State * lua; +extern void *phviewDoc; +extern BOOL bLinehook; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// ChviewDoc + +IMPLEMENT_DYNCREATE(ChviewDoc, CDocument) + +BEGIN_MESSAGE_MAP(ChviewDoc, CDocument) + //{{AFX_MSG_MAP(ChviewDoc) + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// ChviewDoc construction/destruction + +double sqr(double x); + +ChviewDoc::ChviewDoc() +{ + // set some default values for problem definition + d_LineIntegralPoints=400; + Depth=1/0.0254; + LengthUnits=0; + ProblemType=FALSE; + ProblemNote="Add comments here."; + FirstDraw=-1; + A_High=0.; + A_Low=0.; + A_lb=0.; + A_ub=0.; + extRo=extRi=extZo=0; + Smooth=TRUE; + NumList=NULL; + ConList=NULL; + bHasMask=FALSE; + LengthConv=(double *)calloc(6,sizeof(double)); + LengthConv[0]=0.0254; //inches + LengthConv[1]=0.001; //millimeters + LengthConv[2]=0.01; //centimeters + LengthConv[3]=1.; //meters + LengthConv[4]=2.54e-05; //mils + LengthConv[5]=1.e-06; //micrometers + Coords=FALSE; + + for(int i=0;i<4;i++) + d_PlotBounds[i][0]=d_PlotBounds[i][1]= + PlotBounds[i][0]=PlotBounds[i][1]=0; + + // determine path to bin directory + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // lua initialization stuff + initalise_lua(); +} + +ChviewDoc::~ChviewDoc() +{ + int i; + free(LengthConv); + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + ProblemNote=v; + 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.V=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.V); + 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 = BProp.Tinf = BProp.qs = 0; + BProp.beta = 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=0; + 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 Circuit"; + CProp.V=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.V); + 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) asegm.MaxSideLength=b; + asegm.InConductor--; + arclist.Add(asegm); + } + q[0]=NULL; + } + + + // read in list of holes; + if(_strnicmp(q,"[numholes]",13)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) + { + blk.BlockType=-1; + blk.MaxArea=0; + for(i=0;imeshelem[i].rsqr) meshelem[i].rsqr=b; + } + } + + // Find flux density in each element; + for(i=0;iA_High) A_High=meshnode[i].T; + if (meshnode[i].Targ(u1)) + { + swa=ConList[i][k]; + ConList[i][k]=ConList[i][k+1]; + ConList[i][k+1]=swa; + flg=TRUE; + } + } + if(!flg) j=NumList[i]; + } + } + + // Find extreme values of potential + d_PlotBounds[0][0]=A_Low; + d_PlotBounds[0][1]=A_High; + PlotBounds[0][0]=d_PlotBounds[0][0]; + PlotBounds[0][1]=d_PlotBounds[0][1]; + + for(i=0;id_PlotBounds[1][1]) d_PlotBounds[1][1]=b; + if(bd_PlotBounds[2][1]) d_PlotBounds[2][1]=b; + if(b=0) + { + if(meshelem[i].lbl!=k) + { + blocklist[meshelem[i].lbl].IsSelected=TRUE; + if (!bMultiplyDefinedLabels) + { + CString msg; + msg ="Some regions in the problem have been defined\n"; + msg+="by more than one block label. These potentially\n"; + msg+="problematic regions will appear as selected in\n"; + msg+="the initial view."; + MsgBox(msg); + bMultiplyDefinedLabels=TRUE; + } + } + } + } + + + FirstDraw=TRUE; + + return TRUE; +} + +int ChviewDoc::InTriangle(double x, double y) +{ + static int k; + int j,hi,lo,sz; + double z; + + sz=(int) meshelem.GetSize(); + if((k<0) || (k>=sz)) k=0; + + // In most applications, the triangle we're looking + // for is nearby the last one we found. Since the elements + // are ordered in a banded structure, we want to check the + // elements nearby the last one selected first. + if (InTriangleTest(x,y,k)) return k; + + hi=k;lo=k; + + for(j=0;j=sz) hi=0; + lo--; if(lo<0) lo=sz-1; + + z=(meshelem[hi].ctr.re-x)*(meshelem[hi].ctr.re-x) + + (meshelem[hi].ctr.im-y)*(meshelem[hi].ctr.im-y); + if(z<=meshelem[hi].rsqr) + { + if(InTriangleTest(x,y,hi)) + { + k=hi; + return k; + } + } + + z=(meshelem[lo].ctr.re-x)*(meshelem[lo].ctr.re-x) + + (meshelem[lo].ctr.im-y)*(meshelem[lo].ctr.im-y); + if(z<=meshelem[lo].rsqr) + { + if(InTriangleTest(x,y,lo)) + { + k=lo; + return k; + } + } + + } + + return (-1); +} + +BOOL ChviewDoc::GetPointValues(double x, double y, CPointVals &u) +{ + int k; + k=InTriangle(x,y); + if (k<0) return FALSE; + GetPointValues(x,y,k,u); + return TRUE; +} + +BOOL ChviewDoc::GetPointValues(double x, double y, int k, CPointVals &u) +{ + int i,n[3]; + double a[3],b[3],c[3],da,ravg; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + ravg=LengthConv[LengthUnits]* + (meshnode[n[0]].x + meshnode[n[1]].x + meshnode[n[2]].x)/3.; + + GetPointD(x,y,u.F,meshelem[k]); + + u.T=0; + for(i=0;i<3;i++) u.T+=meshnode[n[i]].T*(a[i]+b[i]*x+c[i]*y)/(da); + + u.K=blockproplist[meshelem[k].blk].GetK(u.T); + u.K/=AECF(k,x+I*y); + + u.G.re = u.F.re/(u.K.re); + u.G.im = u.F.im/(u.K.im); + + return TRUE; +} + +void ChviewDoc::GetPointD(double x, double y, CComplex &D, CElement &elm) +{ + // elm is a reference to the element that contains the point of interest. + int i,n[3]; + double da,a[3],b[3],c[3]; + + if(Smooth==FALSE){ + D=elm.D; + return; + } + + for(i=0;i<3;i++) n[i]=elm.p[i]; + a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; + a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; + a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,D=0;i<3;i++) D+=(elm.d[i]*(a[i]+b[i]*x+c[i]*y)/da); +} + +BOOL ChviewDoc::IsSameMaterial(int e1, int e2) +{ + int b1,b2; + + b1=meshelem[e1].blk; + b2=meshelem[e2].blk; + + // Are the same material trivially if they are the same block type + if (b1==b2) return TRUE; + + // If the materials are linear and have the same Kx and Ky, we + // can say that they are the same material; + if ((blockproplist[b1].Kx==blockproplist[b2].Kx) && + (blockproplist[b1].Ky==blockproplist[b2].Ky) && + (blockproplist[b1].npts==0) && + (blockproplist[b2].npts==0)) return TRUE; + + // If the materials are nonlinear and have all of the same T-k points, + // they are the same material; + if (blockproplist[b1].npts>0){ + if (blockproplist[b1].npts==blockproplist[b2].npts) + { + for(int k=0;k2) nos=0; + p=meshelem[n].p[nos]; + + // add this node to the list. We can have a max of 20 nodes, + // which should never actually occur (usually about 6 to 8) + if (qn<20) q[qn++]=p; + + // if this node has a fixed definition, get out of the loop; + if((meshnode[j].Q!=-2) &&(meshnode[p].Q!=-2)){ + lf=p; + break; + } + + m--; if(m<0) m=NumList[j]-1; + } + + // catch some annoying special cases; + if ((lf==rt) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is at the end of a conductor; not much to + // do but punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + else if ((rt!=-1) && (meshnode[j].Q!=-2) && (lf==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + d[i]=meshelem[N].D; + flag=TRUE; + } + else if ((lf!=-1) && (meshnode[j].Q!=-2) && (rt==-1)) + { + // Another instance of a node at the + // end of a conductor; punt! + d[i]=meshelem[N].D; + flag=TRUE; + } + else if((lf==-1) && (rt==-1) && (meshnode[j].Q!=-2)) + { + // The node of interest is an isolated charge. Again, not much to + // do but punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + else if((lf!=-1) && (rt!=-1) && (meshnode[j].Q!=-2)) + { + + // The node of interest is on some boundary where the charge is fixed. + // if the angle is shallow enough, we can just do the regular thing; + // Otherwise, we punt. + CComplex x,y; + x=meshnode[lf].CC()-meshnode[j].CC(); x/=abs(x); + y=meshnode[j].CC()-meshnode[rt].CC(); y/=abs(y); + if(fabs(arg(x/y))>10.0001*PI/180.) + { + // if the angle is greater than 10 degrees, punt; + d[i]=meshelem[N].D; + flag=TRUE; + } + } + + if(flag==FALSE) + { + // The nominal case. + // Fit a plane through the nodes in the list to solve for E. + // Then, multiply by permittivity to get D. + xi=yi=ii=xx=xy=yy=iv=xv=yv=0; + + q[qn++]=j; + + for(k=0;k0) + { + OnNewDocument(); + SetPathName(pname,FALSE); + OnOpenDocument(pname); + } +} + +int ChviewDoc::ClosestNode(double x, double y) +{ + int i,j; + double d0,d1; + + if(nodelist.GetSize()==0) return -1; + + j=0; + d0=nodelist[0].GetDistance(x,y); + for(i=0;iq[k]) && (k<(contour.GetSize()-1))) k++; + u=(z-q[k-1])/(q[k]-q[k-1]); + pt=contour[k-1]+u*(contour[k]-contour[k-1]); + t=contour[k]-contour[k-1]; + t/=abs(t); + n = I*t; + pt+=(n*1.e-06); + + if (elm<0) elm=InTriangle(pt.re,pt.im); + else if (InTriangleTest(pt.re,pt.im,elm)==FALSE) + { + flag=FALSE; + for(j=0;j<3;j++) + for(m=0;m=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + p.M[i][0]=z; + if(flag!=FALSE) + { + switch (PlotType) + { + case 0: + p.M[i][1]=v.T; + break; + case 1: + p.M[i][1]=abs(v.F); + break; + case 2: + p.M[i][1]=Re(v.F/n); + break; + case 3: + p.M[i][1]=Re(v.F/t); + break; + case 4: + p.M[i][1]=abs(v.G); + break; + case 5: + p.M[i][1]=Re(v.G/n); + break; + case 6: + p.M[i][1]=Re(v.G/t); + break; + default: + p.M[i][1]=0; + break; + } + } + } + + free(q); +} + +BOOL ChviewDoc::InTriangleTest(double x, double y, int i) +{ + if ((i<0) || (i>=meshelem.GetSize())) return FALSE; + + int j,k; + double z; + + for(j=0;j<3;j++) + { + k=j+1; if(k==3) k=0; + // Case 1: p[k]>p[j] + if (meshelem[i].p[k] > meshelem[i].p[j]) + { + z=(meshnode[meshelem[i].p[k]].x-meshnode[meshelem[i].p[j]].x)* + (y-meshnode[meshelem[i].p[j]].y) - + (meshnode[meshelem[i].p[k]].y-meshnode[meshelem[i].p[j]].y)* + (x-meshnode[meshelem[i].p[j]].x); + if(z<0) return FALSE; + } + //Case 2: p[k]0) return FALSE; + } + } + + return TRUE; +} + +CPointVals::CPointVals() +{ + T=0; // vector potential + F=0; // flux density + K=0; // permittivity + G=0; // field intensity +} + +CComplex ChviewDoc::Ctr(int i) +{ + CComplex p,c; + int j; + + for(j=0,c=0;j<3;j++){ + p.Set(meshnode[meshelem[i].p[j]].x/3.,meshnode[meshelem[i].p[j]].y/3.); + c+=p; + } + + return c; +} + +double ChviewDoc::ElmArea(int i) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=meshelem[i].p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +double ChviewDoc::ElmArea(CElement *elm) +{ + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=elm->p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return (b0*c1-b1*c0)/2.; + +} + +CComplex ChviewDoc::HenrotteVector(int k) +{ + int i,n[3]; + double b[3],c[3],da; + CComplex v; + + for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + for(i=0,v=0;i<3;i++) + v-=meshnode[n[i]].msk*(b[i]+I*c[i])/(da*LengthConv[LengthUnits]); // grad + + return v; +} + +CComplex ChviewDoc::BlockIntegral(int inttype) +{ + int i,k; + CComplex c,z; + double T; + double a,R; + double r[3]; + + for(i=0,z=0;i G.t + if(inttype==0){ + CPointVals u; + int k; + + k=(int) contour.GetSize(); + GetPointValues(contour[0].re,contour[0].im, u); + z[0] = u.T; + GetPointValues(contour[k-1].re,contour[k-1].im,u); + z[0]-= u.T; + } + + // inttype==1 => F.n + if(inttype==1){ + CComplex n,t,pt; + CPointVals v; + double dz,u,d,Fn; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + z[1]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + Fn = Re(v.F/n); + + if (ProblemType==AXISYMMETRIC) + d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); + else + d=Depth*LengthConv[LengthUnits]; + + z[0]+=(Fn*dz*d); + z[1]+=dz*d; + } + } + } + z[1]=z[0]/z[1]; // Average F.n over the surface; + } + + // inttype==2 => Contour Length + if(inttype==2){ + int i,k; + k=(int) contour.GetSize(); + for(i=0,z[0]=0;i Average Temperature + if(inttype==3){ + CComplex pt; + CPointVals v; + double dz,u,d; + int i,j,k,m,elm; + int NumPlotPoints=d_LineIntegralPoints; + BOOL flag; + + z[0]=0; + z[1]=0; + for(k=1;k=0) + flag=GetPointValues(pt.re,pt.im,elm,v); + else flag=FALSE; + + if(flag==TRUE){ + if (ProblemType==AXISYMMETRIC) + d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); + else + d=Depth*LengthConv[LengthUnits]; + + z[0]+=(v.T*dz*d); + z[1]+=dz*d; + } + } + } + z[0]=z[0]/z[1]; // Average F.n over the surface; + } + + return; +} + + +int ChviewDoc::ClosestArcSegment(double x, double y) +{ + double d0,d1; + int i,j; + + if(arclist.GetSize()==0) return -1; + + j=0; + d0=ShortestDistanceFromArc(CComplex(x,y),arclist[0]); + 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])); +} + +BOOL ChviewDoc::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"hview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LineIntegralPoints); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + + +void ChviewDoc::BendContour(double angle, double anglestep) +{ + if (angle==0) return; + if (anglestep==0) anglestep=1; + + int k,n; + double d,tta,dtta,R; + CComplex c,a0,a1; + + // check to see if there are at least enough + // points to have made one line; + k=(int) contour.GetSize()-1; + if (k<1) return; + + // restrict the angle of the contour to 180 degrees; + if ((angle<-180.) || (angle>180.)) return; + n=(int) ceil(fabs(angle/anglestep)); + tta=angle*PI/180.; + dtta=tta/((double) n); + + // pop last point off of the contour; + a1=contour[k]; + contour.RemoveAt(k); + a0=contour[k-1]; + + // compute location of arc center; + // and radius of the circle that the + // arc lives on. + d=abs(a1-a0); + R=d/(2.*sin(fabs(tta/2.))); + if(tta>0) c=a0 + (R/d)*(a1-a0)*exp(I*(PI-tta)/2.); + else c=a0+(R/d)*(a1-a0)*exp(-I*(PI+tta)/2.); + + // add the points on the contour + for(k=1;k<=n;k++) contour.Add(c+(a0-c)*exp(k*I*dtta)); +} + +CComplex ChviewDoc::E(int k) +{ + // return average electric field intensity for the kth element + CComplex kn; + int i; + + for(i=0,kn=0;i<3;i++) + kn+=blockproplist[meshelem[k].blk].GetK(meshnode[meshelem[k].p[i]].T)/3.; + + return (meshelem[k].D.re/Re(kn) + I*meshelem[k].D.im/Im(kn)) * AECF(k); + + // AECF(k) part corrects permittivity for axisymmetric external region; +} + +CComplex ChviewDoc::D(int k) +{ + // return average electric flux density for the kth element + return meshelem[k].D; +} + +CComplex ChviewDoc::e(int k, int i) +{ + // return nodal temperature gradient for the ith node of the kth element + double aecf=1; + CComplex kn; + + if((ProblemType) && (blocklist[meshelem[k].lbl].IsExternal)) + { + // correct for axisymmetric external region + double x=meshnode[meshelem[k].p[i]].x; + double y=meshnode[meshelem[k].p[i]].y-extZo; + aecf=(x*x+y*y)/(extRi*extRo); + } + + kn=blockproplist[meshelem[k].blk].GetK(meshnode[meshelem[k].p[i]].T); + + return (meshelem[k].d[i].re/Re(kn) + + I*meshelem[k].d[i].im/Im(kn)) * aecf; +} + +CComplex ChviewDoc::d(int k, int i) +{ + // return nodal flux density for the ith node of the kth element; + return meshelem[k].d[i]; +} + +double ChviewDoc::ShortestDistance(double p, double q, int segm) +{ + double t,x[3],y[3]; + + x[0]=nodelist[linelist[segm].n0].x; + y[0]=nodelist[linelist[segm].n0].y; + x[1]=nodelist[linelist[segm].n1].x; + y[1]=nodelist[linelist[segm].n1].y; + + t=((p-x[0])*(x[1]-x[0]) + (q-y[0])*(y[1]-y[0]))/ + ((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])); + + if (t>1.) 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 ChviewDoc::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 + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +class ChviewDoc : public CDocument +{ +protected: // create from serialization only + ChviewDoc(); + DECLARE_DYNCREATE(ChviewDoc) + +// Attributes +public: + + // General problem attributes + double Depth; + int LengthUnits; + double *LengthConv; + BOOL ProblemType; + BOOL Coords; + CString ProblemNote; + BOOL FirstDraw; + BOOL Smooth; + BOOL bMultiplyDefinedLabels; + double extRo, extRi, extZo; + + double A_High, A_Low; + double A_lb, A_ub; + + double d_PlotBounds[4][2]; + double PlotBounds[4][2]; + + + // Some default behaviors + CString BinDir; + int d_LineIntegralPoints; + BOOL bHasMask; + + // lists of nodes, segments, and block labels + CArray< hviewtype::CNode, hviewtype::CNode&> nodelist; + CArray< hviewtype::CSegment, hviewtype::CSegment&> linelist; + CArray< hviewtype::CBlockLabel, hviewtype::CBlockLabel&> blocklist; + CArray< hviewtype::CArcSegment, hviewtype::CArcSegment&> arclist; + + // CArrays containing the mesh information + CArray< hviewtype::CMeshNode, hviewtype::CMeshNode&> meshnode; + CArray< hviewtype::CElement, hviewtype::CElement&> meshelem; + + // List of elements connected to each node; + int *NumList; + int **ConList; + + // lists of properties + CArray< hviewtype::CMaterialProp, hviewtype::CMaterialProp& > blockproplist; + CArray< hviewtype::CBoundaryProp, hviewtype::CBoundaryProp& > lineproplist; + CArray< hviewtype::CPointProp, hviewtype::CPointProp& > nodeproplist; + CArray< hviewtype::CCircuit, hviewtype::CCircuit& > circproplist; + + // list of points in a user-defined contour; + CArray< CComplex, CComplex& > contour; + + // member functions + int InTriangle(double x, double y); + BOOL InTriangleTest(double x, double y, int i); + BOOL GetPointValues(double x, double y, hviewtype::CPointVals &u); + BOOL GetPointValues(double x, double y, int k, hviewtype::CPointVals &u); + void GetLineValues(CXYPlot &p, int PlotType, int npoints); + void GetElementD(int k); + void OnReload(); + int ClosestNode(double x, double y); + CComplex Ctr(int i); + double ElmArea(int i); + double ElmArea(hviewtype::CElement *elm); + void GetPointD(double x, double y, CComplex &D, hviewtype::CElement &elm); + void GetNodalD(CComplex *d, int i); + CComplex BlockIntegral(int inttype); + void LineIntegral(int inttype, double *z); + int ClosestArcSegment(double x, double y); + void GetCircle(hviewtype::CArcSegment &asegm,CComplex &c, double &R); + double ShortestDistanceFromArc(CComplex p, hviewtype::CArcSegment &arc); + double ShortestDistanceFromSegment(double p, double q, int segm); + double ShortestDistance(double p, double q, int segm); + int ClosestSegment(double x, double y); + BOOL IsSameMaterial(int e1, int e2); + double AECF(int k); + double AECF(int k, CComplex p); + + BOOL ScanPreferences(); + void BendContour(double angle, double anglestep); + CComplex HenrotteVector(int k); + BOOL IsKosher(int k); + void FindBoundaryEdges(); + CComplex E(int k); + CComplex D(int k); + CComplex e(int k, int i); + CComplex d(int k, int i); + +/* // Tests for whether or not one is inside a user-defined + // contour; this was really mostly used pre- v3.0, when + // the areas over which block integrals were taken were + // defined by a closed, user-generated contour. + BOOL ContourClosed(); + BOOL SlowInContour(double x, double y); + BOOL InContour(double x, double y); + BOOL InContour(CElement &elm); + BOOL InContour(CComplex p); + BOOL OnContour(CElement &elm); + void AvgMaxwell(double &fx, double &fy); + void AvgMaxwell(double &fx, double &fy, + CComplex &f2x, CComplex &f2y); +*/ + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ChviewDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + // lua extensions + bool luafired; + void initalise_lua(); + static int lua_dumpheader(lua_State * L); + static int lua_getpointvals(lua_State * L); + static int lua_exitpost(lua_State * L); + static int lua_addcontour(lua_State * L); + static int lua_clearcontour(lua_State * L); + static int lua_lineintegral(lua_State * L); + static int lua_selectblock(lua_State * L); + static int lua_groupselectblock(lua_State * L); + static int lua_blockintegral(lua_State * L); + static int lua_clearblock(lua_State * L); + static int lua_zoomout(lua_State * L); + static int lua_zoomin(lua_State * L); + static int lua_zoomnatural(lua_State * L); + static int lua_hidemesh(lua_State * L); + static int lua_showmesh(lua_State * L); + static int lua_showgrid(lua_State * L); + static int lua_hidegrid(lua_State * L); + static int lua_showdensity(lua_State * L); + static int lua_hidedensity(lua_State * L); + static int lua_hidecountour(lua_State * L); + static int lua_showcountour(lua_State * L); + static int lua_zoom(lua_State * L); + static int lua_smoothing(lua_State * L); + static int lua_hidepoints(lua_State * L); + static int lua_showpoints(lua_State * L); + static int lua_gridsnap(lua_State * L); + static int lua_setgrid(lua_State * L); + static int lua_getprobleminfo(lua_State * L); + static int lua_savebitmap(lua_State * L); + PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp); + void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,HBITMAP hBMP, HDC hDC) ; + static int lua_getcircuitprops(lua_State *L); + static int lua_saveWMF(lua_State *L); + static int lua_refreshview(lua_State *L); + static int lua_selectline(lua_State *L); + static int lua_seteditmode(lua_State *L); + static int lua_bendcontour(lua_State *L); + static int lua_makeplot(lua_State *L); + static int lua_unselectall(lua_State *L); + static int lua_selectconductor(lua_State *L); + static int lua_shownames(lua_State * L); + static int lua_vectorplot(lua_State * L); + static int lua_reload(lua_State *L); + static int lua_switchfocus(lua_State *L); + static int luaResize(lua_State *L); + static int luaMinimize(lua_State *L); + static int luaMaximize(lua_State *L); + static int luaRestore(lua_State *L); + static int lua_gettitle(lua_State *L); + + // commands to access low-level information through Lua + static int lua_numnodes(lua_State *L); + static int lua_numelements(lua_State *L); + static int lua_getnode(lua_State *L); + static int lua_getelement(lua_State *L); + + virtual ~ChviewDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(ChviewDoc) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: + +}; + +///////////////////////////////////////////////////////////////////////////// +char* StripKey(char *c); diff --git a/femm/hviewLua.cpp b/femm/hviewLua.cpp new file mode 100644 index 0000000..44ed733 --- /dev/null +++ b/femm/hviewLua.cpp @@ -0,0 +1,1876 @@ +#include "stdafx.h" +#include +#include +#include "hv_problem.h" +#include "femm.h" +#include "xyplot.h" +#include "hviewDoc.h" +#include "hviewview.h" +#include "MainFrm.h" +#include "windows.h" //necessary for bitmap saving +#include "lua.h" +#include "mycommandlineinfo.h" +#include "promptbox.h" +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern lua_State * lua; +extern BOOL bLinehook; +extern void *phviewDoc; +extern BOOL lua_byebye; +extern int m_luaWindowStatus; +extern CLuaConsoleDlg *LuaConsole; + +#define CatchNullDocument(); if (phviewDoc==NULL)\ + { CString msg="No current heat flow output in focus"; \ + lua_error(L,msg.GetBuffer(1)); \ + return 0;} + +//-------------------Lua Extensions------------------------- + +void ChviewDoc::initalise_lua() +{ + // use a messagebox to display errors + lua_register(lua,"ho_setfocus",lua_switchfocus); + lua_register(lua,"ho_getpointvalues",lua_getpointvals); + lua_register(lua,"ho_close",lua_exitpost); + lua_register(lua,"ho_addcontour",lua_addcontour); + lua_register(lua,"ho_clearcontour",lua_clearcontour); + lua_register(lua,"ho_lineintegral",lua_lineintegral); + lua_register(lua,"ho_selectblock",lua_selectblock); + lua_register(lua,"ho_groupselectblock",lua_groupselectblock); + lua_register(lua,"ho_clearblock",lua_clearblock); + lua_register(lua,"ho_blockintegral",lua_blockintegral); + lua_register(lua,"ho_zoomnatural",lua_zoomnatural); + lua_register(lua,"ho_zoomin",lua_zoomin); + lua_register(lua,"ho_zoomout",lua_zoomout); + lua_register(lua,"ho_zoom",lua_zoom); + lua_register(lua,"ho_showgrid",lua_showgrid); + lua_register(lua,"ho_hidegrid",lua_hidegrid); + lua_register(lua,"ho_gridsnap",lua_gridsnap); + lua_register(lua,"ho_setgrid",lua_setgrid); + lua_register(lua,"ho_showmesh",lua_showmesh); + lua_register(lua,"ho_hidemesh",lua_hidemesh); + lua_register(lua,"ho_hidedensityplot",lua_hidedensity); + lua_register(lua,"ho_showdensityplot",lua_showdensity); + lua_register(lua,"ho_hidecontourplot",lua_hidecountour); + lua_register(lua,"ho_showcontourplot",lua_showcountour); + lua_register(lua,"ho_showvectorplot" ,lua_vectorplot); + lua_register(lua,"ho_smooth",lua_smoothing); + lua_register(lua,"ho_showpoints",lua_showpoints); + lua_register(lua,"ho_hidepoints",lua_hidepoints); + lua_register(lua,"ho_shownames",lua_shownames); + lua_register(lua,"ho_getprobleminfo",lua_getprobleminfo); + lua_register(lua,"ho_savebitmap",lua_savebitmap); + lua_register(lua,"ho_getconductorproperties",lua_getcircuitprops); + lua_register(lua,"ho_savemetafile",lua_saveWMF); + lua_register(lua,"ho_refreshview",lua_refreshview); + lua_register(lua,"ho_selectpoint",lua_selectline); + lua_register(lua,"ho_seteditmode",lua_seteditmode); + lua_register(lua,"ho_bendcontour",lua_bendcontour); + lua_register(lua,"ho_makeplot",lua_makeplot); + lua_register(lua,"ho_selectconductor",lua_selectconductor); + lua_register(lua,"ho_reload",lua_reload); + + lua_register(lua,"ho_resize",luaResize); + lua_register(lua,"ho_minimize",luaMinimize); + lua_register(lua,"ho_maximize",luaMaximize); + lua_register(lua,"ho_restore", luaRestore); + lua_register(lua,"ho_gettitle",lua_gettitle); + lua_register(lua,"ho_get_title",lua_gettitle); + + // compatibility with alternate lua function naming convention + lua_register(lua,"ho_set_focus",lua_switchfocus); + lua_register(lua,"ho_get_point_values",lua_getpointvals); + lua_register(lua,"ho_add_contour",lua_addcontour); + lua_register(lua,"ho_clear_contour",lua_clearcontour); + lua_register(lua,"ho_line_integral",lua_lineintegral); + lua_register(lua,"ho_select_block",lua_selectblock); + lua_register(lua,"ho_group_select_block",lua_groupselectblock); + lua_register(lua,"ho_clear_block",lua_clearblock); + lua_register(lua,"ho_block_integral",lua_blockintegral); + lua_register(lua,"ho_zoom_natural",lua_zoomnatural); + lua_register(lua,"ho_zoom_in",lua_zoomin); + lua_register(lua,"ho_zoom_out",lua_zoomout); + lua_register(lua,"ho_show_grid",lua_showgrid); + lua_register(lua,"ho_hide_grid",lua_hidegrid); + lua_register(lua,"ho_show_mesh",lua_showmesh); + lua_register(lua,"ho_hide_mesh",lua_hidemesh); + lua_register(lua,"ho_hide_density_plot",lua_hidedensity); + lua_register(lua,"ho_show_density_plot",lua_showdensity); + lua_register(lua,"ho_hide_contour_plot",lua_hidecountour); + lua_register(lua,"ho_show_contour_plot",lua_showcountour); + lua_register(lua,"ho_show_points",lua_showpoints); + lua_register(lua,"ho_hide_points",lua_hidepoints); + lua_register(lua,"ho_grid_snap",lua_gridsnap); + lua_register(lua,"ho_set_grid",lua_setgrid); + lua_register(lua,"ho_get_problem_info",lua_getprobleminfo); + lua_register(lua,"ho_save_bitmap",lua_savebitmap); + lua_register(lua,"ho_get_conductor_properties",lua_getcircuitprops); + lua_register(lua,"ho_save_metafile",lua_saveWMF); + lua_register(lua,"ho_refresh_view",lua_refreshview); + lua_register(lua,"ho_select_point",lua_selectline); + lua_register(lua,"ho_set_edit_mode",lua_seteditmode); + lua_register(lua,"ho_bend_contour",lua_bendcontour); + lua_register(lua,"ho_make_plot",lua_makeplot); + lua_register(lua,"ho_select_conductor",lua_selectconductor); + lua_register(lua,"ho_show_names",lua_shownames); + lua_register(lua,"ho_show_vector_plot",lua_vectorplot); + + + // functions to access low-level mesh info + lua_register(lua,"ho_numnodes",lua_numnodes); + lua_register(lua,"ho_numelements",lua_numelements); + lua_register(lua,"ho_getnode",lua_getnode); + lua_register(lua,"ho_getelement",lua_getelement); + + lua_register(lua,"ho_num_nodes",lua_numnodes); + lua_register(lua,"ho_num_elements",lua_numelements); + lua_register(lua,"ho_get_node",lua_getnode); + lua_register(lua,"ho_get_element",lua_getelement); + + phviewDoc=this; + +} + +int ChviewDoc::lua_dumpheader(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + return 0; +} + +int ChviewDoc::lua_switchfocus(lua_State *L) +{ + POSITION tpos,dpos; + CDocTemplate* pTemp; + ChviewDoc* pDoc; + CString DocTitle,ThisTitle; + int n; + + // get title of desired document from Lua + n=lua_gettop(L); if (n==0) return NULL; + DocTitle.Format("%s",lua_tostring(L,n)); + DocTitle.MakeLower(); + if(DocTitle.Right(4)==".anh") + DocTitle=DocTitle.Left(DocTitle.GetLength()-4); + + // get pointer to document template for FemmeDoc + tpos=AfxGetApp()->GetFirstDocTemplatePosition( ); + for(int i=0;i<7;i++) pTemp=AfxGetApp()->GetNextDocTemplate(tpos); + + // leaf through documents to get a pointer to the + // document with the right title + dpos=pTemp->GetFirstDocPosition(); + while(dpos!=NULL) + { + pDoc=(ChviewDoc *)pTemp->GetNextDoc(dpos); + ThisTitle=pDoc->GetTitle(); + ThisTitle.MakeLower(); + if(ThisTitle.Right(4)==".anh") + ThisTitle=ThisTitle.Left(ThisTitle.GetLength()-4); + if(ThisTitle==DocTitle) + { + phviewDoc=pDoc; + return NULL; + } + } + + // if we can't find it, throw an error message + CString msg; + msg.Format("No document that matches %s",DocTitle); + lua_error(L,msg.GetBuffer(1)); + return NULL; +} + +int ChviewDoc::lua_getpointvals(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + ChviewDoc * thisDoc; + ChviewView * theView; + + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CPointVals u; + CComplex Jtot; + + if(thisDoc->GetPointValues(px, py, u)==TRUE) + { + lua_pushnumber(L,u.T); + lua_pushnumber(L,u.F.re); + lua_pushnumber(L,u.F.im); + lua_pushnumber(L,u.G.re); + lua_pushnumber(L,u.G.im); + lua_pushnumber(L,u.K.re); + lua_pushnumber(L,u.K.im); + + return 7; + } + + return 0; +} + +int ChviewDoc::lua_exitpost(lua_State * L) +{ + CatchNullDocument(); + ((ChviewDoc *)phviewDoc)->OnCloseDocument( ); + + return 0; +} + +int ChviewDoc::lua_reload(lua_State * L) +{ + CatchNullDocument(); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + // theView->BeginWaitCursor(); + thisDoc->OnReload(); + // theView->EndWaitCursor(); + if (theView->d_ResetOnReload==FALSE) thisDoc->FirstDraw=FALSE; + theView->RedrawView(); + theView->LuaViewInfo(); + return 0; +} + +void ChviewView::LuaViewInfo() +{ + OnViewInfo(); +} + +int ChviewDoc::lua_addcontour(lua_State * L) +{ + CatchNullDocument(); + CComplex z; + int i; + z.Set(lua_todouble(L,1),lua_todouble(L,2)); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + i=(int) thisDoc->contour.GetSize(); + + if(i>0){ + if (z!=thisDoc->contour[i-1]) + thisDoc->contour.Add(z); + } + else thisDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + + return 0; +} + +int ChviewDoc::lua_clearcontour(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + + return 0; +} + +int ChviewDoc::lua_lineintegral(lua_State * L) +{ + CatchNullDocument(); + int type; + double z[4]; + + type=(int) lua_todouble(L,1); + // 0 - G.t + // 1 - F.n + // 2 - Contour length + // 3 - Average temperature + + if (type<0 || type >3) + { + CString msg; + msg.Format("Invalid line integral selected %d",type); + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + z[0]=z[1]=0; + thisDoc->LineIntegral(type,z); + + lua_pushnumber(lua,z[0]); + lua_pushnumber(lua,z[1]); + + return 2; +} + +int ChviewDoc::lua_selectblock(lua_State * L) +{ + CatchNullDocument(); + double px,py; + + px=lua_todouble(L,1); + py=lua_todouble(L,2); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int k; + + if (thisDoc->meshelem.GetSize()>0){ + k=thisDoc->InTriangle(px,py); + if(k>=0){ + thisDoc->bHasMask=FALSE; + thisDoc->blocklist[thisDoc->meshelem[k].lbl].ToggleSelect(); + // RedrawView(); + theView->DrawSelected=thisDoc->meshelem[k].lbl; + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + } + + return 0; +} + +int ChviewDoc::lua_groupselectblock(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + theView->EditAction=2; + int j,k,n; + + if (thisDoc->meshelem.GetSize()>0) + { + n=lua_gettop(L); + k=0; if (n>0) k=(int)lua_todouble(L,1); + + for(j=0;jblocklist.GetSize();j++) + { + if ((thisDoc->blocklist[j].InGroup==k) || (n==0)) + thisDoc->blocklist[j].ToggleSelect(); + thisDoc->bHasMask=FALSE; + } + + HDC myDCH=GetDC(theView->m_hWnd); + CDC tempDC; + CDC *pDC; + pDC=tempDC.FromHandle(myDCH); + + //CDC *pDC=GetDC(theView->m_hWnd); + theView->OnDraw(pDC); + theView->DrawSelected=-1; + theView->ReleaseDC(pDC); + thisDoc->UpdateAllViews(theView); + } + + return 0; +} + +int ChviewDoc::lua_clearblock(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + theView->UnselectAll(); + theView->EditAction=0; + theView->RedrawView(); + + return 0; +} + + +int ChviewDoc::lua_blockintegral(lua_State * L) +{ + // 0 - Stored anergy + // 1 - Area + // 2 - Volume + // 3 - Average D + // 4 - Average E + // 5 - Weighted Stress Tensor Force + // 6 - Weighted Stress Tensor Torque + + CatchNullDocument(); + int type; + type=(int) lua_todouble(L,1); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CComplex z; + + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (thisDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE) + { + CString msg="Cannot integrate\nNo area has been selected"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + z=thisDoc->BlockIntegral(type); + + lua_pushnumber(L,z.re); + lua_pushnumber(L,z.im); + + return 2; +} + +int ChviewDoc::lua_zoomin(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + + theView->ox=theView->ox+0.25*x/theView->mag; + theView->oy=theView->oy+0.25*y/theView->mag; + theView->mag*=2.; + + theView->RedrawView(); + + + + + return 0; +} + +int ChviewDoc::lua_zoom(lua_State * L) +{ + CatchNullDocument(); + double x[2],y[2],m[2]; + + x[0]=lua_todouble(L,1); + y[0]=lua_todouble(L,2); + x[1]=lua_todouble(L,3); + y[1]=lua_todouble(L,4); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CRect r; + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + theView->Invalidate(TRUE); + return 0; +} + + +int ChviewDoc::lua_zoomnatural(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + + ChviewDoc *pDoc=theView->GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return 0; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + theView->GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + theView->ox=x[0]; theView->oy=y[0]; + theView->GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]mag=m[0]; + else theView->mag=m[1]; + + if(pDoc->FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else theView->RedrawView(); + + + + return 0; +} + +int ChviewDoc::lua_zoomout(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + RECT r; + double x,y; + + theView->GetClientRect(&r); + x=r.right; y=r.bottom; + theView->ox=theView->ox-0.5*x/theView->mag; + theView->oy=theView->oy-0.5*y/theView->mag; + theView->mag/=2.; + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_showmesh(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_hidemesh(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_hidegrid(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + theView->RedrawView(); + + return 0; +} + + +int ChviewDoc::lua_showgrid(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + theView->GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_showdensity(lua_State * L) +{ + CatchNullDocument(); + BOOL showlegend; + BOOL gscale; + int PlotType,n; + double m_ub1,m_lb1; + CString type; + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + n=lua_gettop(L); if(n<3) return 0; + + showlegend=(int) lua_todouble(L,1); + gscale=(int) lua_todouble(L,2); + PlotType=(int) lua_todouble(L,3); + + if(n>=5) + { + m_ub1=lua_todouble(L,4); + m_lb1=lua_todouble(L,5); + } + + if(m_lb1>m_ub1) + { + double temp=m_lb1; + m_lb1=m_ub1; + m_ub1=temp; + } + + if ((PlotType>2)|| (PlotType<0)) PlotType=0; + + if (showlegend==-1) + { + // load back the default plot range + m_lb1=thisDoc->d_PlotBounds[PlotType][0]; + m_ub1=thisDoc->d_PlotBounds[PlotType][1]; + showlegend=1; + gscale=0; + n=5; + } + + theView->DensityPlot=PlotType+1; + theView->LegendFlag=showlegend; + theView->GreyContours=gscale; + if(n>=5) + { + thisDoc->PlotBounds[PlotType][1]=m_ub1; + thisDoc->PlotBounds[PlotType][0]=m_lb1; + } + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_hidedensity(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + theView->DensityPlot=0; + + theView->RedrawView(); + + return 0; +} + + +int ChviewDoc::lua_showcountour(lua_State * L) +{ + CatchNullDocument(); + int m_numcontours; + double m_alow,m_ahigh; + CString type; + m_numcontours=(int) lua_todouble(L,1); + m_alow=lua_todouble(L,2); + m_ahigh=lua_todouble(L,3); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + + theView->ShowAr=true; + thisDoc->A_Low=m_alow; + thisDoc->A_High=m_ahigh; + theView->NumContours=m_numcontours; + theView->RedrawView(); + + if(m_numcontours==-1) + { + thisDoc->A_Low=thisDoc->A_lb; + thisDoc->A_High=thisDoc->A_ub; + theView->NumContours=19; + } + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_hidecountour(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + theView->ShowAr=FALSE; + + theView->RedrawView(); + return 0; +} + +int ChviewDoc::lua_smoothing(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + + if (temp=="off") + { + thisDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + + } + if (temp=="on") + { + thisDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for smoothing"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + + theView->RedrawView(); + + return 0; +} + + +int ChviewDoc::lua_showpoints(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_hidepoints(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CFrameWnd *MFrm; + MFrm=theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + theView->PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_gridsnap(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CString temp; + temp.Format("%s",lua_tostring(L,1)); + temp.MakeLower(); + + CMainFrame *MFrm; + MFrm=(CMainFrame *)theView->GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(temp=="off"){ + theView->SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + theView->SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } + + + if (temp !="on" && temp !="off") + { + CString msg="Unknown option for grid snap"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + return 0; +} + + +int ChviewDoc::lua_setgrid(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CString temp; + int coords=0; + double gridsize; + + gridsize=lua_todouble(L,1); + temp.Format("%s",lua_tostring(L,2)); + temp.MakeLower(); + + if (temp=="cart") coords=0; + if (temp=="polar") coords=1; + + if (temp !="cart" && temp !="polar") + { + CString msg="Unknown option for set grid"; + lua_error(L,msg.GetBuffer(1)); + return 0; + + } + + + theView->GridSize=gridsize; + thisDoc->Coords=coords; + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_getprobleminfo(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + lua_pushnumber(L,thisDoc->ProblemType); + lua_pushnumber(L,thisDoc->Depth); + lua_pushnumber(L,thisDoc->LengthConv[thisDoc->LengthUnits]); + + return 3; +} + +int ChviewDoc::lua_savebitmap(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=theView->GetDC(); + + theView->GetClientRect(&r); + + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + tempDC.Rectangle(0,0,r.right,r.bottom); + + theView->OnDraw(&tempDC); + // tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + + PBITMAPINFO pbmi; + + pbmi=thisDoc->CreateBitmapInfoStruct(theView->m_hWnd,HBITMAP(bitmap)); + thisDoc->CreateBMPFile(theView->m_hWnd,filename.GetBuffer(1),pbmi,HBITMAP(bitmap),tempDC.m_hDC); + + // to save a bitmap file we need + // a bitmapheader lets use the v5 + + // OpenClipboard(); + // EmptyClipboard(); + // SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + // CloseClipboard(); +return 0; +} + + +PBITMAPINFO ChviewDoc::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) +{ + BITMAP bmp; + PBITMAPINFO pbmi; + WORD cClrBits; + + // Retrieve the bitmap's color format, width, and height. + if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) + {//errhandler("GetObject", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy9"); + } + // Convert the color format to a count of bits. + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; + + // Allocate memory for the BITMAPINFO structure. (This structure + // contains a BITMAPINFOHEADER structure and an array of RGBQUAD + // data structures.) + + if (cClrBits >= 24) + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ((int)(1<< cClrBits))); + + // There is no RGBQUAD array for the 24-bit-per-pixel format. + + else + pbmi = (PBITMAPINFO) LocalAlloc(LPTR, + sizeof(BITMAPINFOHEADER)); + + // Initialize the fields in the BITMAPINFO structure. + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = bmp.bmWidth; + pbmi->bmiHeader.biHeight = bmp.bmHeight; + pbmi->bmiHeader.biPlanes = bmp.bmPlanes; + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; + if (cClrBits < 24) + pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; + + // Compute the number of bytes in the array of color + // indices and store the result in biSizeImage. + // For Windows NT/2000, the width must be DWORD aligned unless + // the bitmap is RLE compressed. This example shows this. + // For Windows 95/98, the width must be WORD aligned unless the + // bitmap is RLE compressed. + pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 + * pbmi->bmiHeader.biHeight; + // Set biClrImportant to 0, indicating that all of the + // device colors are important. + pbmi->bmiHeader.biClrImportant = 0; + return pbmi; + } + + +void ChviewDoc::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, + HBITMAP hBMP, HDC hDC) + { + HANDLE hf; // file handle + BITMAPFILEHEADER hdr; // bitmap file-header + PBITMAPINFOHEADER pbih; // bitmap info-header + LPBYTE lpBits; // memory pointer + DWORD dwTotal; // total count of bytes + DWORD cb; // incremental count of bytes + BYTE *hp; // byte pointer + DWORD dwTmp; + + pbih = (PBITMAPINFOHEADER) pbi; + lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); + + if (!lpBits) + MsgBox("Critical error on getting bmp info, possible page fault ahoy10"); +// errhandler("GlobalAlloc", hwnd); + + // Retrieve the color table (RGBQUAD array) and the bits + // (array of palette indices) from the DIB. + if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, + DIB_RGB_COLORS)) + { + // errhandler("GetDIBits", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy11"); + + } + + // Create the .BMP file. + hf = CreateFile(pszFile, + GENERIC_READ | GENERIC_WRITE, + (DWORD) 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + (HANDLE) NULL); + if (hf == INVALID_HANDLE_VALUE) + {// errhandler("CreateFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy12"); + + } + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof(RGBQUAD) + pbih->biSizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + + pbih->biSize + pbih->biClrUsed + * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), + (LPDWORD) &dwTmp, NULL)) + { + MsgBox("Critical error on getting bmp info, possible page fault ahoy13"); + + // errhandler("WriteFile", hwnd); + } + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + + pbih->biClrUsed * sizeof (RGBQUAD), + (LPDWORD) &dwTmp, ( NULL))) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy14"); + + // Copy the array of color indices into the .BMP file. + dwTotal = cb = pbih->biSizeImage; + hp = lpBits; + if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) +// errhandler("WriteFile", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy15"); + + // Close the .BMP file. + if (!CloseHandle(hf)) +// errhandler("CloseHandle", hwnd); + MsgBox("Critical error on getting bmp info, possible page fault ahoy16"); + + // Free memory. + GlobalFree((HGLOBAL)lpBits); +} + +int ChviewDoc::lua_getcircuitprops(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * TheDoc; // note normally thisdoc + ChviewView * theView; + TheDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=TheDoc->GetFirstViewPosition(); + theView=(ChviewView *)TheDoc->GetNextView(pos); + + int NumCircuits,i,k; + CString circuitname; + circuitname=lua_tostring(L,1); + k=-1; + + // ok we need to find the correct entry for the circuit name + NumCircuits=(int) TheDoc->circproplist.GetSize(); + for(i=0;icircproplist[i].CircName==circuitname) + { + k=i; + i=NumCircuits; // that will break it + } + } + +// trap errors + + if(k==-1) + { + CString msg="Unknown conductor"; + lua_error(L,msg.GetBuffer(1)); + return 0; + } + + lua_pushnumber(L,TheDoc->circproplist[k].V); + lua_pushnumber(L,TheDoc->circproplist[k].q); + return 2; +} + +int ChviewDoc::lua_saveWMF(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + CString filename; + + filename.Format("%s",lua_tostring(L,1)); + + RECT r; + CDC tempDC; + CDC *pDC=theView->GetDC(); + + CMetaFileDC Meta; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + theView->GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + theView->OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,filename)); + DeleteEnhMetaFile(hMeta); + + return 0; +} + +int ChviewDoc::lua_refreshview(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + CDC *pDC=theView->GetDC(); + + // erase background + CBrush backBrush(theView->BackColor); + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + CRect rect; + pDC->GetClipBox(&rect); + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + // redraw the view + theView->OnDraw(pDC); + + return 0; +} + +int ChviewDoc::lua_selectline(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * pDoc; // note normally thisdoc + ChviewView * theView; + pDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + theView=(ChviewView *)pDoc->GetNextView(pos); + + theView->EditAction=1; // make sure things update OK + + double mx,my; + int i,j,k,m; + + mx=lua_todouble(L,1); + my=lua_todouble(L,2); + + +//*************** + { + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return 0; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + theView->DrawUserContour(FALSE); + return 0; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(z); + theView->DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + //CView::OnLButtonDown(nFlags, point); + return 0; + } + } + pDoc->contour.Add(y); + theView->DrawUserContour(FALSE); + } + } + } + } + + +//************* + return 0; +} + +int ChviewDoc::lua_seteditmode(lua_State *L) +{ + CatchNullDocument(); + CString EditAction; + + EditAction.Format("%s",lua_tostring(L,1)); + EditAction.MakeLower(); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + if (EditAction=="point") + { + if (theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + if (theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) + { + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=0; + } + if (EditAction=="contour") + { + if(theView->EditAction==2){ + int i; + BOOL flg=FALSE; + thisDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++){ + if (thisDoc->blocklist[i].IsSelected==TRUE) + { + thisDoc->blocklist[i].IsSelected=FALSE; + flg=TRUE; + } + } + + if(flg==TRUE) theView->RedrawView(); + } + theView->EditAction=1; + } + if (EditAction=="area") + { + if(theView->EditAction==1){ + theView->EraseUserContour(TRUE); + thisDoc->contour.RemoveAll(); + } + theView->EditAction=2; + } + + return 0; +} + +int ChviewDoc::lua_bendcontour(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + thisDoc->BendContour(lua_todouble(L,1),lua_todouble(L,2)); + theView->InvalidateRect(NULL); + + return 0; +} + +int ChviewDoc::lua_makeplot(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc *pDoc; + ChviewView *pView; + pDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=pDoc->GetFirstViewPosition(); + pView=(ChviewView *)pDoc->GetNextView(pos); + + int PlotType,npoints,FileFormat,n; + CString ToFile; + +// if ((pView->EditAction!=1) || (pDoc->contour.GetSize()==0)){ + if (pDoc->contour.GetSize()==0){ + CString outmsg; + outmsg.Format("*** Cannot create a plot;\r\n*** No contour has been defined\r\n"); + LuaConsole->ToOutput(outmsg); + return TRUE; + } + + n=lua_gettop(L); + + if(n>0) PlotType=(int) lua_todouble(L,1); + else return FALSE; + + if(n>1) npoints=(int) lua_todouble(L,2); + else npoints=pView->d_PlotPoints; + + CXYPlot xyplot; + pDoc->GetLineValues(xyplot,PlotType,npoints); + + if(n<3) + { + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (pView->OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else{ + ToFile.Format("%s",lua_tostring(L,3)); + + if(n>3){ + FileFormat=(int) lua_todouble(L,4); + if (xyplot.ToDisk(FileFormat,ToFile)==FALSE) + LuaConsole->ToOutput("*** Couldn't write data to disk\r\n"); + } + else{ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + DeleteEnhMetaFile(CopyEnhMetaFile(hMeta,ToFile)); + DeleteEnhMetaFile(hMeta); + } + } + + return TRUE; +} + +int ChviewDoc::lua_selectconductor(lua_State *L) +{ + CatchNullDocument(); + int n=lua_gettop(L); + if (n==0) return 0; + + int j,i; + CString name; + name=lua_tostring(L,1); + + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + for(i=0,j=-1;icircproplist.GetSize();i++) + { + + if (name==thisDoc->circproplist[i].CircName) + { + j=i; + break; + } + } + + if (j<0) return 0; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (thisDoc->nodelist[i].InConductor==j) thisDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (thisDoc->linelist[i].InConductor==j) thisDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (thisDoc->arclist[i].InConductor==j) thisDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (thisDoc->meshnode[i].Q==j) + { + thisDoc->meshnode[i].IsSelected=1-thisDoc->meshnode[i].IsSelected; + } + } + theView->RedrawView(); + + return 0; +} + +int ChviewDoc::lua_shownames(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + int flg=(int)lua_todouble(L,1); + if (flg!=0) flg=1; + theView->ShowNames=flg; + theView->InvalidateRect(NULL); + + return 0; +} + +int ChviewDoc::lua_vectorplot(lua_State * L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + + int n=lua_gettop(L); + if (n>0) theView->VectorPlot=(int)lua_todouble(L,1); + if (n>1) theView->VectorScaleFactor=lua_todouble(L,2); + + theView->InvalidateRect(NULL); + + return 0; +} + +int ChviewDoc::luaResize(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + int n=lua_gettop(L); + if (n!=2) return 0; + + int nWidth = (int)lua_todouble(L,1); + int nHeight = (int)lua_todouble(L,2); + pChildFrm->ResizeClient(nWidth,nHeight,TRUE); + + return 0; +} + +int ChviewDoc::luaMinimize(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MINIMIZE); + + return 0; +} + +int ChviewDoc::luaMaximize(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_MAXIMIZE); + + return 0; +} + +int ChviewDoc::luaRestore(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + ChviewView * theView; + thisDoc=(ChviewDoc *)phviewDoc; + POSITION pos; + pos=thisDoc->GetFirstViewPosition(); + theView=(ChviewView *)thisDoc->GetNextView(pos); + CChildFrame *pChildFrm = (CChildFrame *)theView->GetParentFrame(); + + pChildFrm->ShowWindow(SW_RESTORE); + + return 0; +} + +int ChviewDoc::lua_gettitle(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + thisDoc=(ChviewDoc *)phviewDoc; + + lua_pushstring(L,thisDoc->GetTitle()); + + return 1; +} + + +/////////////////////////////////////////////////////// +// Functions that provide low-level access to the mesh +/////////////////////////////////////////////////////// + +int ChviewDoc::lua_numnodes(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + thisDoc=(ChviewDoc *)phviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshnode.GetSize()); + + return 1; +} + +int ChviewDoc::lua_numelements(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + thisDoc=(ChviewDoc *)phviewDoc; + + lua_pushnumber(L,(int) thisDoc->meshelem.GetSize()); + + return 1; +} + +int ChviewDoc::lua_getnode(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + thisDoc=(ChviewDoc *)phviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshnode.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshnode[k].x); + lua_pushnumber(L,thisDoc->meshnode[k].y); + + return 2; +} + +int ChviewDoc::lua_getelement(lua_State *L) +{ + CatchNullDocument(); + ChviewDoc * thisDoc; + thisDoc=(ChviewDoc *)phviewDoc; + + int k=(int) lua_todouble(L,1); + k--; + if ((k<0) || (k>=thisDoc->meshelem.GetSize())) return 0; + + lua_pushnumber(L,thisDoc->meshelem[k].p[0]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[1]+1); + lua_pushnumber(L,thisDoc->meshelem[k].p[2]+1); + lua_pushnumber(L,Re(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,Im(thisDoc->meshelem[k].ctr)); + lua_pushnumber(L,thisDoc->ElmArea(k)); + lua_pushnumber(L,thisDoc->blocklist[thisDoc->meshelem[k].lbl].InGroup); + + return 7; +} diff --git a/femm/hviewView.cpp b/femm/hviewView.cpp new file mode 100644 index 0000000..a0b8d6d --- /dev/null +++ b/femm/hviewView.cpp @@ -0,0 +1,3655 @@ +// hviewView.cpp : implementation of the ChviewView class +// + +#include "stdafx.h" +#include +#include +#include "femm.h" +#include "hv_problem.h" +#include "xyplot.h" +#include "hviewDoc.h" +#include "hviewView.h" +#include "GridMod.h" +#include "EnterPt.h" +#include "MainFrm.h" +#include "ChildFrm.h" +#include "KbdZoom.h" +#include "hv_CPlotDlg2.h" +#include "hv_DPlotDlg2.h" +#include "hv_VPlotDlg.h" +#include "MyMsgBox.h" +#include "hv_XYPlotDlg.h" +#include "hv_LIntDlg.h" +#include "hv_BlockInt.h" +#include "hv_CircDlg.h" +#include "BendContourDlg.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern int Xm,Ym; + +#define MSKHI (1. + 1.e-08) +#define MSKLO (0. - 1.e-08) + +extern lua_State * lua; +extern BOOL bLinehook; + +///////////////////////////////////////////////////////////////////////////// +// ChviewView + +IMPLEMENT_DYNCREATE(ChviewView, CView) + +BEGIN_MESSAGE_MAP(ChviewView, CView) + //{{AFX_MSG_MAP(ChviewView) + ON_COMMAND(ID_SMOOTH, OnSmooth) + ON_COMMAND(ID_ZOOM_IN, OnZoomIn) + ON_COMMAND(ID_SNAP_GRID, OnSnapGrid) + ON_COMMAND(ID_SHOW_MESH, OnShowMesh) + ON_COMMAND(ID_SHOW_GRID, OnShowGrid) + ON_COMMAND(ID_SET_GRID, OnSetGrid) + ON_COMMAND(ID_CPLOT, OnCplot) + ON_COMMAND(ID_DPLOT, OnDplot) + ON_COMMAND(ID_ZOOM_NATURAL, OnZoomNatural) + ON_COMMAND(ID_ZOOM_OUT, OnZoomOut) + ON_COMMAND(ID_ZOOM_WINDOW, OnZoomWindow) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_RELOAD, OnReload) + ON_COMMAND(ID_MENU_AREA, OnMenuArea) + ON_COMMAND(ID_MENU_CONTOUR, OnMenuContour) + ON_COMMAND(ID_MENU_POINT, OnMenuPoint) + ON_WM_KEYDOWN() + ON_COMMAND(ID_MENU_PLOT, OnMenuPlot) + ON_COMMAND(ID_MENU_INTEGRATE, OnMenuIntegrate) + ON_COMMAND(ID_MENUSHOWPTS, OnMenushowpts) + ON_COMMAND(ID_KBDZOOM, OnKbdZoom) + ON_WM_ERASEBKGND() + ON_WM_RBUTTONDBLCLK() + ON_WM_SIZE() + ON_COMMAND(ID_PAN_DOWN, OnPanDown) + ON_COMMAND(ID_PAN_LEFT, OnPanLeft) + ON_COMMAND(ID_PAN_RIGHT, OnPanRight) + ON_COMMAND(ID_PAN_UP, OnPanUp) + ON_COMMAND(ID_VIEW_CIRCPROPS, OnViewCircprops) + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + ON_COMMAND(ID_VIEW_INFO, OnViewInfo) + ON_COMMAND(ID_VIEW_SHOWBLOCKNAMES, OnViewShowblocknames) + ON_COMMAND(ID_VPLOT, OnVplot) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_LBUTTONDBLCLK() +END_MESSAGE_MAP() + +void MyMessageBox(CString s); + +///////////////////////////////////////////////////////////////////////////// +// ChviewView construction/destruction + +ChviewView::ChviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews++; + + // TODO: add construction code here + d_EditAction=0; + d_GridFlag=FALSE; + d_SnapFlag=FALSE; + d_MeshFlag=FALSE; + d_LegendFlag=TRUE; + d_GreyContours=FALSE; + d_NumContours=19; + d_ShowAr=FALSE; + d_ShowMask=FALSE; + d_DensityPlot=1; + d_VectorPlot=0; + d_PtsFlag=TRUE; + d_ResetOnReload=FALSE; + d_Smooth=TRUE; + d_PlotPoints=1500; + d_ShowNames=FALSE; + + ox=0.; oy=0.; mag=100.; // lower left corner is origin; 100 dpi + GridSize=0.25; // 1/4" grid + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + + ////////////////////////////// + // Default Colors // + ////////////////////////////// + + // Greyscale Colormap + Grey00=dGrey00; + Grey01=dGrey01; + Grey02=dGrey02; + Grey03=dGrey03; + Grey04=dGrey04; + Grey05=dGrey05; + Grey06=dGrey06; + Grey07=dGrey07; + Grey08=dGrey08; + Grey09=dGrey09; + Grey10=dGrey10; + Grey11=dGrey11; + Grey12=dGrey12; + Grey13=dGrey13; + Grey14=dGrey14; + Grey15=dGrey15; + Grey16=dGrey16; + Grey17=dGrey17; + Grey18=dGrey18; + Grey19=dGrey19; + + // BELA Colormap + Color19=dColor19; + Color18=dColor18; + Color17=dColor17; + Color16=dColor16; + Color15=dColor15; + Color14=dColor14; + Color13=dColor13; + Color12=dColor12; + Color11=dColor11; + Color10=dColor10; + Color09=dColor09; + Color08=dColor08; + Color07=dColor07; + Color06=dColor06; + Color05=dColor05; + Color04=dColor04; + Color03=dColor03; + Color02=dColor02; + Color01=dColor01; + Color00=dColor00; + + // Other colors + SelColor = dSelColor; + MeshColor = dMeshColor; + BlockColor = dBlockColor; + LineColor = dLineColor; + RegionColor = dRegionColor; + GridColor = dGridColor; + BackColor = dBackColor; + NodeColor = dNodeColor; + TextColor = dTextColor; + RealFluxLineColor = dRealFluxLineColor; + MaskLineColor = dMaskLineColor; + NameColor = dNameColor; + VectorColor = dRealVectorColor; + + BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); + + ScanPreferences(); + + // Apply default behaviors + EditAction=d_EditAction; + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; +} + +ChviewView::~ChviewView() +{ + ((CFemmApp *)AfxGetApp())->NumViews--; + if (!((CFemmApp *)AfxGetApp())->NumViews) + ((CMainFrame *)AfxGetApp()->GetMainWnd())->SetBar(0); +} + +BOOL ChviewView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// ChviewView drawing +void ChviewView::ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r) +{ + double x,y; + x=(double) xs; + y=(double) ys; + + *xd=x/mag+ox; + *yd=(((double) r->bottom) - y- 1.)/mag + oy; +} + +BOOL ChviewView::DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r) +{ + double x,y; + x=mag*(xd-ox); + y=((double) r->bottom)- 1. - mag*(yd-oy); +// if((fabs(x)>32768.) || (fabs(y)>32768.)) return FALSE; + if((fabs(x)>2.147483648e9) || (fabs(y)>2.147483648e9)) return FALSE; + *xs = (int) (mag*(xd-ox)); + *ys = ((int) r->bottom) - 1 - ((int) (mag*(yd-oy)) ); + return TRUE; +} + +void ChviewView::DoContours(CDC *pDC,int *p,int side,int Aflag) +{ + int i,j,k; + static double q[4][4]; + static double *m[4]; + static int u[4]; + double *swap; + double hi,lo,a,b,z,offset; + + ChviewDoc *pDoc=GetDocument(); + + switch(side) + { + case 0 : u[0]=p[0]; u[1]=p[1]; u[2]=p[1]; u[3]=p[2]; break; + case 1 : u[0]=p[1]; u[1]=p[2]; u[2]=p[2]; u[3]=p[0]; break; + default: u[0]=p[2]; u[1]=p[0]; u[2]=p[0]; u[3]=p[1]; break; + } + + for(i=0;i<4;i++){ + m[i]=q[i]; + m[i][0]=(double) pDoc->meshnode[u[i]].xs; + m[i][1]=(double) pDoc->meshnode[u[i]].ys; + m[i][3]=pDoc->meshnode[u[i]].x; + if (Aflag==0) m[i][2]=pDoc->meshnode[u[i]].T; + if (Aflag==1) m[i][2]=pDoc->meshnode[u[i]].T; + if (Aflag==2) m[i][2]=pDoc->meshnode[u[i]].msk; + } + + // scale A for easier analysis. Not necessary if mask is being displayed, + // since mask always varies between zero and one. + + if (Aflag<2) + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-pDoc->A_Low)/ + (pDoc->A_High-pDoc->A_Low); + offset=-NumContours*pDoc->A_Low/(pDoc->A_High-pDoc->A_Low); + } + else + { + for(i=0;i<4;i++) m[i][2]=NumContours*(m[i][2]-MSKLO)/(MSKHI-MSKLO); + offset=-NumContours*MSKLO/(MSKHI-MSKLO); + } + + // swap around so that lowest magnitude is first point in + // each line... + if (m[0][2]>m[1][2]){ + swap=m[1]; + m[1]=m[0]; + m[0]=swap; + } + if (m[2][2]>m[3][2]){ + swap=m[3]; + m[3]=m[2]; + m[2]=swap; + } + + // figure out which contours lie in this section + lo=m[0][2]; if(m[2][2]>lo) lo=m[2][2]; + hi=m[1][2]; if(m[3][2]=0) && (iSetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), RealFluxLineColor ); + +// if(Aflag==1) +// pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), +// (int) ((m[3][1]-m[2][1])*b+m[2][1]), ImagFluxLineColor ); + + if(Aflag==2) + pDC->SetPixel((int) ((m[3][0]-m[2][0])*b+m[2][0]), + (int) ((m[3][1]-m[2][1])*b+m[2][1]), MaskLineColor ); + } +} +//////////////// +void ChviewView::PlotFluxDensity(CDC *pDC,int elmnum,int flag) +{ + int i,j,k,n,lav; + double b,bn[3],bh,bl,y,z; + CComplex b1[3],b2[3]; + POINT ps[3]; + static double c[64][3],p[3][2]; + CElement elm; + ChviewDoc *pDoc=GetDocument(); + + elm=pDoc->meshelem[elmnum]; + + if (((pDoc->meshnode[elm.p[0]].xs == pDoc->meshnode[elm.p[1]].xs) && + (pDoc->meshnode[elm.p[1]].xs == pDoc->meshnode[elm.p[2]].xs)) || + ((pDoc->meshnode[elm.p[0]].ys == pDoc->meshnode[elm.p[1]].ys) && + (pDoc->meshnode[elm.p[1]].ys == pDoc->meshnode[elm.p[2]].ys) )) return; + + if(pDoc->blocklist[elm.lbl].IsSelected==TRUE) return; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + for(i=0;i<3;i++) + { + switch(DensityPlot) + { + case 2: + if (pDoc->Smooth==TRUE) bn[i]=abs(elm.d[i]); + else bn[i]=abs(elm.D); + break; + + case 3: + if (pDoc->Smooth==TRUE) bn[i]=abs(pDoc->e(elmnum,i)); + else bn[i]=abs(pDoc->E(elmnum)); + break; + + default: + bn[i]=pDoc->meshnode[elm.p[i]].T; + break; + } + } + + flag=1; + + bl=pDoc->PlotBounds[DensityPlot-1][0]; + bh=pDoc->PlotBounds[DensityPlot-1][1]; + + if(bh==bl) return; + else for(i=0;i<3;i++) bn[i]=20.*(bn[i]-bl)/(bh-bl); + + // find subtriangle edges; + for(i=0,n=0;i<3;i++) + { + c[n][0]=(double) pDoc->meshnode[elm.p[i]].xs; + c[n][1]=(double) pDoc->meshnode[elm.p[i]].ys; + c[n][2]=bn[i]; + n++; if(n>=64) return; + j=i+1; if(j==3) j=0; + p[0][0]=(double) pDoc->meshnode[elm.p[i]].xs; + p[0][1]=(double) pDoc->meshnode[elm.p[i]].ys; + p[1][0]=(double) pDoc->meshnode[elm.p[j]].xs; + p[1][1]=(double) pDoc->meshnode[elm.p[j]].ys; + p[2][0]=bn[i]; + p[2][1]=bn[j]; + if(p[2][0]=0) && (z<20)) n++; + if(n>=64) return; + } + else + for(z=floor(p[2][0]);z>p[2][1];z--) + { + y=(z-p[2][0])/(p[2][1]-p[2][0]); + c[n][0]=(1.-y)*p[0][0] + y*p[1][0]; + c[n][1]=(1.-y)*p[0][1] + y*p[1][1]; + c[n][2]=(1.-y)*p[2][0] + y*p[2][1]; + if ((z>=0) && (z<20)) n++; + if(n>=64) return; + } + + } + + // subtriangle vertices are now listed in the c[][] array. + // there are n vertices. Now, plot out these subtriangles; + + do{ + // find lowest vertex & neighbors; + for(i=1,j=0;i=n) k=0; + + // plot triangle; + b=(c[i][2]+c[j][2]+c[k][2])/3.; + lav=19-((int) b); + if(lav>19) lav=19; + if(lav<0) lav=0; + + { + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + BOOL DrawIt=TRUE; + + if (GreyContours==FALSE){ + if(mymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(mymap[lav]); + FillPen.CreatePen(PS_SOLID,1,mymap[lav]); + } + } + else{ + if(greymap[lav]==BackColor) DrawIt=FALSE; + else{ + FillBrush.CreateSolidBrush(greymap[lav]); + FillPen.CreatePen(PS_SOLID,1,greymap[lav]); + } + } + if(DrawIt==TRUE) + { + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + ps[0].x=(long) c[i][0]; ps[0].y=(long) c[i][1]; + ps[1].x=(long) c[j][0]; ps[1].y=(long) c[j][1]; + ps[2].x=(long) c[k][0]; ps[2].y=(long) c[k][1]; + pDC->Polygon(ps,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); + } + } + + // remove middle point from the list; + for(i=j;i2); +} + +/////////////// + +void ChviewView::PlotSelectedElm(CDC *pDC,CElement &elm) +{ + int i; + POINT p[3]; + ChviewDoc *pDoc=GetDocument(); + + if (elm.lbl!=DrawSelected) + if (pDoc->blocklist[elm.lbl].IsSelected==FALSE) return; + + for(i=0;i<3;i++){ + p[i].x=pDoc->meshnode[elm.p[i]].xs; + p[i].y=pDoc->meshnode[elm.p[i]].ys; + } + + CPen FillPen,*pOldPen; + CBrush FillBrush,*pOldBrush; + if (pDoc->blocklist[elm.lbl].IsSelected==TRUE) + { + FillBrush.CreateSolidBrush(RegionColor); + FillPen.CreatePen(PS_SOLID,1,RegionColor); + } + else{ + FillBrush.CreateSolidBrush(0x00ffffff); + FillPen.CreatePen(PS_SOLID,1,0x00ffffff); + } + pOldBrush = pDC->SelectObject( &FillBrush ); + pOldPen = pDC->SelectObject( &FillPen ); + pDC->Polygon(p,3); + pDC->SelectObject(pOldPen); + pDC->SelectObject(pOldBrush); +} + +void ChviewView::DrawUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + ChviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,FALSE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,FALSE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,FALSE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void ChviewView::EraseUserContour(BOOL flag) +{ + // FALSE == just draw last line in contour; + // TRUE == draw all lines in contour; + int i,xs,ys,xso,yso; + + ChviewDoc *pDoc=GetDocument(); + CDC *pDC=GetDC(); + RECT r; + GetClientRect(&r); + + for(i=0;icontour.GetSize();i++){ + DwgToScreen(pDoc->contour[i].re,pDoc->contour[i].im,&xs,&ys,&r); + if((flag==TRUE) || (i==(int) pDoc->contour.GetSize()-1)) + { + if(i==0){ + SpecialLine(pDC,xs-2,ys,xs+2,ys,TRUE); + SpecialLine(pDC,xs,ys-2,xs,ys+2,TRUE); + xso=xs;yso=ys; + } + else{ + SpecialLine(pDC,xso,yso,xs,ys,TRUE); + xso=xs; yso=ys; + } + } + else{ xso=xs; yso=ys; } + } + ReleaseDC(pDC); +} + +void ChviewView::OnDraw(CDC* pDC) +{ + ChviewDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + RECT r; + static RECT oldr; + GetClientRect(&r); + int i,j,k; // usual iterators... + int xs,ys,nx,ny; + double xd,yd,dt,R; + double xss,yss,rss,rt; + CComplex p,c,s; + + const COLORREF mymap[]={ + Color00,Color01,Color02,Color03,Color04, + Color05,Color06,Color07,Color08,Color09, + Color10,Color11,Color12,Color13,Color14, + Color15,Color16,Color17,Color18,Color19 + }; + + const COLORREF greymap[]={ + Grey00,Grey01,Grey02,Grey03,Grey04, + Grey05,Grey06,Grey07,Grey08,Grey09, + Grey10,Grey11,Grey12,Grey13,Grey14, + Grey15,Grey16,Grey17,Grey18,Grey19 + }; + + CFont fntArial,*pOldFont; + fntArial.CreateFont(16,6,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); + pOldFont=pDC->SelectObject(&fntArial); + + if(pDoc->FirstDraw<0) + { + pDoc->Smooth=d_Smooth; + pDoc->FirstDraw=FALSE; + } + + if(pDoc->FirstDraw==TRUE){ + // Apply default behaviors + ox=0.; oy=0.; mag=100.; + GridSize=0.25; + Coords=FALSE; + ZoomWndFlag=FALSE; + DrawSelected=-1; + if(pDoc->bMultiplyDefinedLabels){ + EditAction=2; + ShowNames=TRUE; + } + else{ + EditAction=d_EditAction; + ShowNames=d_ShowNames; + } + GridFlag=d_GridFlag; + SnapFlag=d_SnapFlag; + MeshFlag=d_MeshFlag; + + LegendFlag=d_LegendFlag; + GreyContours=d_GreyContours; + NumContours=d_NumContours; + ShowAr=d_ShowAr; + ShowMask=d_ShowMask; + DensityPlot=d_DensityPlot; + VectorPlot=d_VectorPlot; + VectorScaleFactor=1; + PtsFlag=d_PtsFlag; + pDoc->Smooth=d_Smooth; + + OnZoomNatural(); + LinePix.RemoveAll(); + oldr=r; + OnViewInfo(); + } + + if((oldr.right!=r.right) || (oldr.bottom!=r.bottom)) + { + LinePix.RemoveAll(); + oldr=r; + } + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + // just give up and make sure that the right + // buttons are checked every time through OnDraw; + // otherwise, it's just too easy to get the buttons + // so that they don't match the actual mode. + else{ + CMainFrame *pFrame=(CMainFrame *)GetTopLevelFrame(); + CChildFrame *pChild = (CChildFrame *)pFrame->MDIGetActive(); + CView *pView = pChild->GetActiveView(); + if (pView==this) CheckIt(); + } + + CPen *pOldPen; + CPen penBlue,penRed,penBlack,penGreen, + penMesh,penReal,penImag,penMask, + penNode,penText,penArrow; + penBlue.CreatePen(PS_SOLID,1,LineColor); + penRed.CreatePen(PS_SOLID,1,SelColor); + penReal.CreatePen(PS_SOLID,1,RealFluxLineColor); + penMask.CreatePen(PS_SOLID,1,MaskLineColor); + penGreen.CreatePen(PS_SOLID,1,BlockColor); + penMesh.CreatePen(PS_SOLID,1,MeshColor); + penNode.CreatePen(PS_SOLID,1,NodeColor); + penText.CreatePen(PS_SOLID,1,TextColor); + penArrow.CreatePen(PS_SOLID,1,VectorColor); + + // Convert node coordinates to screen coordinates + for(i=0;inodelist.GetSize();i++) + if(DwgToScreen(pDoc->nodelist[i].x,pDoc->nodelist[i].y, + &(pDoc->nodelist[i].xs),&(pDoc->nodelist[i].ys),&r)==FALSE) + { + mag/=2.; + i=-1; + } + + // Convert meshnode coordinates to screen coordinates + for(i=0;imeshnode.GetSize();i++) + DwgToScreen(pDoc->meshnode[i].x,pDoc->meshnode[i].y, + &(pDoc->meshnode[i].xs),&(pDoc->meshnode[i].ys),&r); + + // get center and radius of the screen in drawing coords. + // can then use to find out whether elements are off the screen. + xs=(r.right+r.left)/2; + ys=(r.top+r.bottom)/2; + ScreenToDwg(xs,ys, &xss, &yss, &r); + rss=sqrt(pow((double)r.bottom,2.) + pow((double)r.right,2.))/(2.*mag); + + // Draw selected area... + if (EditAction==2) + { + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + PlotSelectedElm(pDC,pDoc->meshelem[i]); + } + } + } + + // Draw flux densities if they are enabled... + if(DensityPlot!=0){ + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=abs(CComplex(xss,yss)-pDoc->meshelem[i].ctr); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + { + PlotFluxDensity(pDC,i,DensityPlot); + } + } + } + } + + // Draw grid if it is enabled... + if (GridFlag==TRUE) + { + int skip; + BOOL drawgrid=TRUE; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Grid too dense to display.",TRUE); + } + else{ + skip=__min((nx/20)+1,(ny/20)+1); + skip=(int) pow(2.,floor(log((double) skip)/log(2.))); + for(i=0,xd=GridSize*ceil(ox/GridSize);i<=nx;i++,xd+=GridSize) + for(j=0,yd=GridSize*ceil(oy/GridSize);j<=ny;j++,yd+=GridSize) + { + if((i==skip*(i/skip)) || (j==skip*(j/skip))) + { + DwgToScreen(xd,yd,&xs,&ys,&r); + pDC->SetPixel((int) xs, (int) ys, GridColor ); + } + } + } + } + + // Draw mesh if it is enabled... + if (MeshFlag==TRUE) + { + int pi,po,OnBoundary; + + pOldPen = pDC->SelectObject( &penMesh ); + for(i=0;imeshelem.GetSize();i++) + { + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + + OnBoundary=FALSE; + for(j=0;j<3;j++) + if (pDoc->meshelem[i].n[j] == 1) + OnBoundary=TRUE; + + for(j=0;j<3;j++) + { + k=j+1; if (k==3) k=0; + pi=pDoc->meshelem[i].p[j]; + po=pDoc->meshelem[i].p[k]; + + if((po>pi) || (OnBoundary==TRUE)) + { + MyMoveTo(pDC,pDoc->meshnode[pi].xs, + pDoc->meshnode[pi].ys); + MyLineTo(pDC,pDoc->meshnode[po].xs, + pDoc->meshnode[po].ys); + } + } + } + } + pDC->SelectObject( pOldPen ); + } + + // Draw contour lines, if they are enabled. + pOldPen = pDC->SelectObject( &penReal ); + if (ShowAr==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,0); + } + } + + pDC->SelectObject(&penMask); + if (ShowMask==TRUE) + for(i=0;imeshelem.GetSize();i++){ + if((pDoc->meshelem[i].lbl==DrawSelected) || (DrawSelected==-1)){ + rt=sqrt( pow(xss-pDoc->meshelem[i].ctr.re,2.) + + pow(yss-pDoc->meshelem[i].ctr.im,2.) ); + if( rt < ( sqrt(pDoc->meshelem[i].rsqr) + rss) ) + for(j=0;j<3;j++) + DoContours(pDC,pDoc->meshelem[i].p,j,2); + } + } + + pDC->SelectObject( pOldPen ); + + // Draw lines linking nodes + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].Hidden==FALSE){ + if(pDoc->linelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,pDoc->nodelist[pDoc->linelist[i].n0].xs, + pDoc->nodelist[pDoc->linelist[i].n0].ys); + MyLineTo(pDC,pDoc->nodelist[pDoc->linelist[i].n1].xs, + pDoc->nodelist[pDoc->linelist[i].n1].ys); + + pDC->SelectObject( pOldPen ); + } + + // Draw Arc Segments; + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].Hidden==FALSE){ + if(pDoc->arclist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penBlue ); + else pOldPen = pDC->SelectObject( &penRed ); + k=(int) ceil(pDoc->arclist[i].ArcLength/pDoc->arclist[i].MaxSideLength); + dt=pDoc->arclist[i].ArcLength*PI/(((double) k)*180.); + + pDoc->GetCircle(pDoc->arclist[i],c,R); + p.Set(pDoc->nodelist[pDoc->arclist[i].n0].x, + pDoc->nodelist[pDoc->arclist[i].n0].y); + DwgToScreen(p.re,p.im,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + s=exp(I*dt); + for(j=0;jSelectObject( pOldPen ); + } + + // Draw node points + if(PtsFlag==TRUE) for(i=0;inodelist.GetSize();i++) + { + xs=pDoc->nodelist[i].xs; + ys=pDoc->nodelist[i].ys; + + if(pDoc->nodelist[i].IsSelected==FALSE) + pOldPen = pDC->SelectObject( &penNode ); + else pOldPen = pDC->SelectObject( &penRed ); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SelectObject( pOldPen ); + } + + + // Draw vectors + if ((VectorPlot>0) && (pDoc->nodelist.GetSize()>0)) + { + CPointVals u; + BOOL drawgrid=TRUE; + double MaxVal; + int xp,yp; + CComplex vr,va,c0,c1; + int ilo,ihi,jlo,jhi; + + MaxVal=pDoc->d_PlotBounds[VectorPlot][1]; + + ScreenToDwg((int) r.right, (int) r.top, &xd, &yd, &r); + nx=(int) (floor(xd/GridSize) - ceil(ox/GridSize)); + ny=(int) (floor(yd/GridSize) - ceil(oy/GridSize)); + + if (nx>0){ + if((r.right/nx)<2) drawgrid=FALSE; + } + + if (drawgrid==FALSE){ + StatBar->SetPaneText(0,"Vectors too dense to display.",TRUE); + } + else{ + pOldPen = pDC->SelectObject( &penArrow ); + for(k=0;kmeshelem.GetSize();k++) + { + rt=abs(CComplex(xss,yss)-pDoc->meshelem[k].ctr); + if( rt < ( sqrt(pDoc->meshelem[k].rsqr) + rss) ) + { + c0=pDoc->meshelem[k].ctr-sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c1=pDoc->meshelem[k].ctr+sqrt(pDoc->meshelem[k].rsqr)*(1.+I); + c0/=GridSize; + c1/=GridSize; + ilo=(int) floor(Re(c0)); + ihi=(int) ceil (Re(c1)); + jlo=(int) floor(Im(c0)); + jhi=(int) ceil (Im(c1)); + for(i=ilo;i<=ihi;i++) + { + for(j=jlo;j<=jhi;j++) + { + xd=GridSize*((double) i); + yd=GridSize*((double) j); + if(pDoc->InTriangleTest(xd,yd,k)) + { + pDoc->GetPointValues(xd,yd,k,u); + + if (VectorPlot==1) vr=(u.F)*GridSize*VectorScaleFactor/MaxVal; + else vr=(u.G)*GridSize*VectorScaleFactor/MaxVal; + DwgToScreen(xd,yd,&xs,&ys,&r); + MyMoveTo(pDC,xs,ys); + xp=xs;yp=ys; + DwgToScreen(xd+Re(vr),yd+Im(vr),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + if ((xs==xp) && (ys==yp)) pDC->SetPixel((int) xs, (int) ys, VectorColor ); + else if (abs(vr)!=0) + { + xp=xs;yp=ys; + va=exp(I*3.*PI/4.)*vr/3.; + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + MyMoveTo(pDC,xp,yp); + va*=exp(I*PI/2.); + DwgToScreen(xd+Re(vr+va),yd+Im(vr+va),&xs,&ys,&r); + MyLineTo(pDC,xs,ys); + } + } + } + } + } // end of if(rt<... + } + pDC->SelectObject( pOldPen ); + } + } + + if(EditAction==1) DrawUserContour(TRUE); + + // draw block names/labels + if(ShowNames){ + pDC->SetTextColor(NameColor); + pOldPen = pDC->SelectObject( &penGreen ); + CString lbl; + for(i=0;iblocklist.GetSize();i++) + { + + DwgToScreen(pDoc->blocklist[i].x,pDoc->blocklist[i].y,&xs,&ys,&r); + + MyMoveTo(pDC,xs-2,ys-2); + MyLineTo(pDC,xs-2,ys+2); + MyLineTo(pDC,xs+2,ys+2); + MyLineTo(pDC,xs+2,ys-2); + MyLineTo(pDC,xs-2,ys-2); + + pDC->SetTextAlign(TA_BASELINE); + pDC->SetBkMode(TRANSPARENT); + lbl=pDoc->blockproplist[pDoc->blocklist[i].BlockType].BlockName; + pDC->TextOut(xs+5,ys,lbl); + } + pDC->SelectObject( pOldPen ); + } + + // Draw Legend if it is enabled; + if((LegendFlag==TRUE) && (DensityPlot!=0)) + { + CBrush *pOldBrush; + char cc[80]; + double dta; + CBrush BackBrush; + + pOldPen = pDC->SelectObject( &penText ); + pDC->SetTextColor(TextColor); + pDC->SetBkMode(TRANSPARENT); + pDC->SetTextAlign(TA_TOP); + pDC->SetTextAlign(TA_LEFT); + BackBrush.CreateSolidBrush(BackColor); + pOldBrush = pDC->SelectObject( &BackBrush ); + pDC->Rectangle(r.right-212-6,r.top+6,r.right-6,r.top+24+21*16 ); + pDC->SelectObject(pOldBrush); + + if (DensityPlot==1) sprintf(cc,"Density Plot: Temperature (K)"); + if (DensityPlot==2) sprintf(cc,"Density Plot: |F|, W/m^2"); + if (DensityPlot==3) sprintf(cc,"Density Plot: |G|, K/m"); + pDC->TextOut(r.right-212,r.top+16*20+16,cc,(int) strlen(cc)); + + dta=(pDoc->PlotBounds[DensityPlot-1][1]- + pDoc->PlotBounds[DensityPlot-1][0])/20.; + + for(i=0;i<20;i++){ + + { + CBrush FillBrush; + + if (GreyContours==FALSE) FillBrush.CreateSolidBrush(mymap[i]); + else FillBrush.CreateSolidBrush(greymap[i]); + pOldBrush = pDC->SelectObject( &FillBrush ); + pDC->Rectangle(r.right-212,r.top+16*i+12,r.right-187,r.top+12+16*(i+1) ); + pDC->SelectObject(pOldBrush); + } + + double Blb=pDoc->PlotBounds[DensityPlot-1][0]; + double Bub=pDoc->PlotBounds[DensityPlot-1][1]; + if(i==0) + sprintf(cc,"%.3e : >%.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else if(i==19) + sprintf(cc,"<%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + else + sprintf(cc,"%.3e : %.3e",((double) (19-i))*dta + Blb, + ((double) (20-i))*dta + Blb); + pDC->TextOut(r.right-182,r.top+16*i+12,cc,(int) strlen(cc)); + } + pDC->SelectObject( pOldPen ); + } + + pDC->SelectObject(pOldFont); + fntArial.DeleteObject(); + +} + +///////////////////////////////////////////////////////////////////////////// +// ChviewView printing + +BOOL ChviewView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void ChviewView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void ChviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// ChviewView diagnostics + +#ifdef _DEBUG +void ChviewView::AssertValid() const +{ + CView::AssertValid(); +} + +void ChviewView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +ChviewDoc* ChviewView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(ChviewDoc))); + return (ChviewDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// ChviewView message handlers + +void ChviewView::OnMouseMove(UINT nFlags, CPoint point) +{ + if ((bLinehook==NormalLua) || (bLinehook==HiddenLua)) + { + StatBar->SetPaneText(0,"EXECUTING LUASCRIPT -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==ImportDXF) + { + StatBar->SetPaneText(0,"IMPORTING DXF -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + if (bLinehook==BuildMask) + { + StatBar->SetPaneText(0,"BUILDING STRESS TENSOR MASK -- HIT TO ABORT",TRUE); + CView::OnMouseMove(nFlags, point); + return; + } + + static char statmsg[256]; + double x,y,q; + RECT r; + ChviewDoc *pDoc=GetDocument(); + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + q=pow(10.,floor(log(mag)/log(10.)+0.5)); + x=(double) point.x; y=(double) (r.bottom-point.y-1); + x=x/mag+ox; y=y/mag+oy; + x=floor(x*q+0.5)/q; y=floor(y*q+0.5)/q; + + // process Snap to Grid command + if ((SnapFlag==TRUE) && (EditAction!=2) && (ZoomWndFlag==0)){ + x=GridSize*floor(0.5+x/GridSize); + y=GridSize*floor(0.5+y/GridSize); + } + + // draw box for window zoom; + if(ZoomWndFlag==2){ + CDC *pDC=GetDC(); + COLORREF ocol; + CZPix p; + + int xso,yso,xsi,ysi,xsn,ysn,i,k,lo,hi; + DwgToScreen(wzx,wzy,&xso,&yso,&r); + DwgToScreen(mx,my,&xsi,&ysi,&r); + DwgToScreen(x,y,&xsn,&ysn,&r); + + // Draw old rectangle off the screen; + if(ZoomPix.GetSize()>0){ + for(k=(int) ZoomPix.GetSize()-1;k>=0;k--) + pDC->SetPixel(ZoomPix[k].x,ZoomPix[k].y,ZoomPix[k].c); + ZoomPix.RemoveAll(); + } + + // XOR new rectangle onto screen + if(xsoGetPixel(i,ysn); + p.c=ocol; p.x=i; p.y=ysn; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,ysn,ocol); + ocol=pDC->GetPixel(i,yso); + p.c=ocol; p.x=i; p.y=yso; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(i,yso,ocol); + } + if(ysoGetPixel(xso,i); + p.c=ocol; p.x=xso; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xso,i,ocol); + ocol=pDC->GetPixel(xsn,i); + p.c=ocol; p.x=xsn; p.y=i; + ZoomPix.Add(p); + ocol=ocol ^ RGB(255,255,255); + pDC->SetPixel(xsn,i,ocol); + } + + ReleaseDC(pDC); + } + + + // update mouse position; + mx=x; my=y; + + if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==0)) + sprintf(statmsg,"(x=%.4f,y=%.4f)",x,y); + else if ((pDoc->Coords==FALSE) && (pDoc->ProblemType==1)) + sprintf(statmsg,"(r=%.4f,z=%.4f)",x,y); + else sprintf(statmsg,"(%.4f at %.4f deg)",sqrt(x*x+y*y),atan2(y,x)*180/PI); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} + +void ChviewView::OnZoomIn() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + + ox=ox+0.25*x/mag; + oy=oy+0.25*y/mag; + mag*=2.; + + RedrawView(); +} + +void ChviewView::OnZoomOut() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox=ox-0.5*x/mag; + oy=oy-0.5*y/mag; + mag/=2.; + + RedrawView(); +} + +void ChviewView::OnZoomNatural() +{ + ChviewDoc *pDoc=GetDocument(); + double x[2],y[2],m[2],w; + RECT r; + int i; + + if (pDoc->meshnode.GetSize()<2) return; + x[0]=pDoc->meshnode[0].x; x[1]=pDoc->meshnode[0].x; + y[0]=pDoc->meshnode[0].y; y[1]=pDoc->meshnode[0].y; + for(i=1;imeshnode.GetSize();i++) + { + if(pDoc->meshnode[i].xmeshnode[i].x; + if(pDoc->meshnode[i].x>x[1]) x[1]=pDoc->meshnode[i].x; + if(pDoc->meshnode[i].ymeshnode[i].y; + if(pDoc->meshnode[i].y>y[1]) y[1]=pDoc->meshnode[i].y; + } + + if(pDoc->FirstDraw==TRUE){ + if((x[1]-x[0])>(y[1]-y[0])) w=x[1]-x[0]; + else w=y[1]-y[0]; + if(w!=0) + GridSize=pow(10.,floor(log(w)/log(10.)-1.)); + } + + ox=x[0]; oy=y[0]; + GetClientRect(&r); + m[0]=((double) (r.right-1))/(x[1]-x[0]); + m[1]=((double) (r.bottom-1))/(y[1]-y[0]); + + if(m[0]FirstDraw==TRUE) pDoc->FirstDraw=FALSE; + else RedrawView(); +} + + +void ChviewView::OnKbdZoom() +{ + ChviewDoc *pDoc=GetDocument(); + CKbdZoom dlg; + RECT r; + double m[2],x[4],z; + + GetClientRect(&r); + ScreenToDwg(r.right,r.top, &dlg.m_scr_right, &dlg.m_scr_top, &r); + dlg.m_scr_top=floor(1000.*dlg.m_scr_top)/1000.; + dlg.m_scr_right=floor(1000.*dlg.m_scr_right)/1000.; + dlg.m_scr_bottom=oy; + dlg.m_scr_left=ox; + + if(dlg.DoModal()==IDOK) + { + x[0]=dlg.m_scr_left; + x[1]=dlg.m_scr_bottom; + x[2]=dlg.m_scr_right; + x[3]=dlg.m_scr_top; + + if(x[0]>x[2]){ z=x[2]; x[2]=x[0]; x[0]=z; } + if(x[1]>x[3]){ z=x[3]; x[3]=x[1]; x[1]=z; } + + ox=x[0]; oy=x[1]; + m[0]=((double) (r.right-1))/(x[2]-x[0]); + m[1]=((double) (r.bottom-1))/(x[3]-x[1]); + if(m[0]GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(GridFlag==TRUE){ + GridFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + GridFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc->PressButton(ID_SHOW_GRID,TRUE); + } + RedrawView(); +} + +void ChviewView::OnSetGrid() +{ + CGridMod pDlg; + ChviewDoc *pDoc=GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + pDlg.m_gridsize = GridSize; + pDlg.coords = pDoc->Coords; + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + GridSize=pDlg.m_gridsize; + pDoc->Coords=pDlg.coords; + RedrawView(); + } +} + +void ChviewView::OnSnapGrid() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_leftbar; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(SnapFlag==TRUE){ + SnapFlag=FALSE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + SnapFlag=TRUE; + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc->PressButton(ID_SNAP_GRID,TRUE); + } +} + +void ChviewView::OnShowMesh() +{ + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + if(MeshFlag==TRUE){ + MeshFlag=FALSE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MeshFlag=TRUE; + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc->PressButton(ID_SHOW_MESH,TRUE); + } + + RedrawView(); +} + + +void ChviewView::OnCplot() +{ + ChviewDoc *pDoc=GetDocument(); + + hvCCPlotDlg2 dlg; + dlg.m_showa=ShowAr; + dlg.m_showmask=ShowMask; + dlg.m_numcontours=NumContours; + dlg.m_alow=pDoc->A_Low; + dlg.m_ahigh=pDoc->A_High; + dlg.Alb=pDoc->A_lb; + dlg.Aub=pDoc->A_ub; + if(dlg.DoModal()==IDOK){ + ShowAr=dlg.m_showa; + ShowMask=dlg.m_showmask; + pDoc->A_Low=dlg.m_alow; + pDoc->A_High=dlg.m_ahigh; + NumContours=dlg.m_numcontours; + RedrawView(); + } + +} + +void ChviewView::OnDplot() +{ + ChviewDoc *pDoc=GetDocument(); + int i,k; + + hvCDPlotDlg2 dlg; + + if(!DensityPlot) dlg.m_showit=FALSE; + else dlg.m_showit=TRUE; + dlg.m_showlegend=LegendFlag; + dlg.m_gscale=GreyContours; + dlg.DensityPlot=DensityPlot; + + for(i=0;i<4;i++) + for(k=0;k<2;k++) + { + dlg.PlotBounds[i][k]=pDoc->PlotBounds[i][k]; + dlg.d_PlotBounds[i][k]=pDoc->d_PlotBounds[i][k]; + } + + if(dlg.DoModal()==IDOK){ + if(dlg.m_showit) DensityPlot=dlg.DensityPlot; + else DensityPlot=0; + LegendFlag=dlg.m_showlegend; + GreyContours=dlg.m_gscale; + for(i=0;i<4;i++) + for(k=0;k<2;k++) + pDoc->PlotBounds[i][k]=dlg.PlotBounds[i][k]; + RedrawView(); + } +} + +void ChviewView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (MFrm==NULL) MsgBox("Null GetTopLevelFrame"); + else{ + StatBar=(CStatusBar *)MFrm->GetMessageBar(); + Dspl=&MFrm->m_dlgBar; + } + + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); +} + +void ChviewView::DisplayPointProperties(double px, double py) +{ + ChviewDoc* pDoc = GetDocument(); + CPointVals u; + CComplex Jtot; + if (pDoc->nodelist.GetSize()==0) return; + if(pDoc->GetPointValues(px, py, u)==TRUE) + { + CString outbox,s; + if (pDoc->ProblemType>=0) + { + if (pDoc->ProblemType==0) + { + s.Format("Point: x=%g, y=%g",px,py); + outbox=s; + s.Format("T = %g K",u.T); + outbox+="\r\n"+s; + s.Format("|F| = %g W/m^2",abs(u.F)); + outbox+="\r\n"+s; + s.Format("Fx = %g W/m^2",u.F.re); + outbox+="\r\n"+s; + s.Format("Fy = %g W/m^2",u.F.im); + outbox+="\r\n"+s; + s.Format("|G| = %g K/m",abs(u.G)); + outbox+="\r\n"+s; + s.Format("Gx = %g K/m",u.G.re); + outbox+="\r\n"+s; + s.Format("Gy = %g K/m",u.G.im); + outbox+="\r\n"+s; + s.Format("Kx = %g W/(m*K)",u.K.re); + outbox+="\r\n"+s; + s.Format("Ky = %g W/(m*K)",u.K.im); + outbox+="\r\n"+s; + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + else{ + s.Format("Point: r=%g, z=%g",px,py); + outbox=s; + s.Format("T = %g K",u.T); + outbox+="\r\n"+s; + s.Format("|F| = %g W/m^2",abs(u.F)); + outbox+="\r\n"+s; + s.Format("Fr = %g W/m^2",u.F.re); + outbox+="\r\n"+s; + s.Format("Fz = %g W/m^2",u.F.im); + outbox+="\r\n"+s; + s.Format("|G| = %g K/m",abs(u.G)); + outbox+="\r\n"+s; + s.Format("Gr = %g K/m",u.G.re); + outbox+="\r\n"+s; + s.Format("Gz = %g K/m",u.G.im); + outbox+="\r\n"+s; + s.Format("Kr = %g W/(m*K)",u.K.re); + outbox+="\r\n"+s; + s.Format("Kz = %g W/(m*K)",u.K.im); + outbox+="\r\n"+s; + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; + } + } +} +} + +void ChviewView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonDown(nFlags, point); + return; + } + + int i,j,k,m; + + if (ZoomWndFlag==1) + { + ZoomWndFlag++; + wzx=mx;wzy=my; + return; + } + + if (ZoomWndFlag==2) return; + + if (EditAction==0) DisplayPointProperties(mx,my); + + if (EditAction==1){ + ChviewDoc *pDoc=GetDocument(); + if (pDoc->nodelist.GetSize()>0){ + i=pDoc->ClosestNode(mx,my); + CComplex x,y,z; + double R,d1,d2; + int lineno,arcno,flag=0; + z.Set(pDoc->nodelist[i].x,pDoc->nodelist[i].y); + + if (pDoc->contour.GetSize()>0){ + + //check to see if point is the same as last point in the contour; + y=pDoc->contour[pDoc->contour.GetSize()-1]; + if ((y.re==z.re) && (y.im==z.im)) return; + + j=pDoc->ClosestNode(y.re,y.im); + x.Set(pDoc->nodelist[j].x,pDoc->nodelist[j].y); + + //check to see if this point and the last point are ends of an + //input segment; + lineno=-1; + d1=1.e08; + + if (abs(x-y)<1.e-08){ + for(k=0;klinelist.GetSize();k++){ + if((pDoc->linelist[k].n0==j) && (pDoc->linelist[k].n1==i)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2linelist[k].n0==i) && (pDoc->linelist[k].n1==j)) + { + d2=fabs(pDoc->ShortestDistanceFromSegment(mx,my,k)); + if(d2arclist.GetSize();k++){ + if((pDoc->arclist[k].n0==j) && (pDoc->arclist[k].n1==i)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2arclist[k].n0==i) && (pDoc->arclist[k].n1==j)) + { + d2=pDoc->ShortestDistanceFromArc(CComplex(mx,my), + pDoc->arclist[k]); + if(d2contour.Add(z); + DrawUserContour(FALSE); + return; + } + + if((lineno<0) && (arcno<0)){ + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(lineno>=0){ + j=(int) pDoc->contour.GetSize(); + if(j>1){ + if(abs(pDoc->contour[j-2]-z)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + if(arcno>=0){ + k=arcno; + pDoc->GetCircle(pDoc->arclist[k],x,R); + j=(int) ceil(pDoc->arclist[k].ArcLength/pDoc->arclist[k].MaxSideLength); + if(flag==TRUE) + z=exp(I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + else + z=exp(-I*pDoc->arclist[k].ArcLength*PI/(180.*((double) j)) ); + for(i=0;icontour.GetSize(); + if(m>1){ + if(abs(pDoc->contour[m-2]-y)<1.e-08){ + CView::OnLButtonDown(nFlags, point); + return; + } + } + pDoc->contour.Add(y); + DrawUserContour(FALSE); + } + } + } + } + + if (EditAction==2){ + ChviewDoc *pDoc=GetDocument(); + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + pDoc->blocklist[pDoc->meshelem[k].lbl].ToggleSelect(); + DrawSelected=pDoc->meshelem[k].lbl; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + + } + + CView::OnLButtonDown(nFlags, point); +} + +void ChviewView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (bLinehook!=FALSE) + { + CView::OnLButtonUp(nFlags, point); + return; + } + + if (ZoomWndFlag>0){ + ZoomPix.RemoveAll(); + ZoomWndFlag=0; + if((mx==wzx) && (my==wzy)){ + RedrawView(); + return; + } + RECT r; + double z,cmag,m[2]; + if (mxcontour.GetSize(); + if(i>0){ + if (z!=pDoc->contour[i-1]) + pDoc->contour.Add(z); + } + else pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + + if(EditAction==2){ + ChviewDoc *pDoc=GetDocument(); + int clnode,clseg,claseg,i,j; + double dnode,dseg,daseg,d; + + // find distance to closest node; + clnode=pDoc->ClosestNode(mx,my); + if(clnode>=0) dnode=pDoc->nodelist[clnode].GetDistance(mx,my); + else dnode=-1.; + + // find distance to closest segment; + clseg=pDoc->ClosestSegment(mx,my); + if (clseg>=0) dseg=pDoc->ShortestDistance(mx,my,clseg); + else dseg=-1.; + + // find distance to closest arc segment; + claseg=pDoc->ClosestArcSegment(mx,my); + if (claseg>=0) + daseg=pDoc->ShortestDistanceFromArc(CComplex(mx,my),pDoc->arclist[claseg]); + else daseg=-1.; + + // now, compare to find the closest entity; + j=-1; + if (clnode>=0){ + d=dnode; + j=pDoc->nodelist[clnode].InConductor; + } + if ((dseg=0)){ + d=dseg; + j=pDoc->linelist[clseg].InConductor; + } + if ((daseg=0)){ + d=daseg; + j=pDoc->arclist[claseg].InConductor; + } + + if (j<0) return; // return if the closest object is associated with + // the default group, or if there are no objects. + + pDoc->bHasMask=FALSE; + + // now, the group associated with the nearest entity is in j; + // toggle the select of all objects in this group; + for(i=0;inodelist.GetSize();i++) + if (pDoc->nodelist[i].InConductor==j) pDoc->nodelist[i].ToggleSelect(); + for(i=0;ilinelist.GetSize();i++) + if (pDoc->linelist[i].InConductor==j) pDoc->linelist[i].ToggleSelect(); + for(i=0;iarclist.GetSize();i++) + if (pDoc->arclist[i].InConductor==j) pDoc->arclist[i].ToggleSelect(); + for(i=0;imeshnode.GetSize();i++) + { + if (pDoc->meshnode[i].Q==j) + { + pDoc->meshnode[i].IsSelected=1-pDoc->meshnode[i].IsSelected; + } + } + // DrawPSLG(); + RedrawView(); + } + + CView::OnRButtonDown(nFlags, point); +} + +void ChviewView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void ChviewView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} + +void ChviewView::OnReload() +{ + ChviewDoc *pDoc=GetDocument(); + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->OnReload(); + if (bLinehook==FALSE) EndWaitCursor(); + if (d_ResetOnReload==FALSE) pDoc->FirstDraw=FALSE; + RedrawView(); + OnViewInfo(); +} + +void ChviewView::OnMenuArea() +{ + ChviewDoc *pDoc=GetDocument(); + if(EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + EditAction=2; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, TRUE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void ChviewView::OnMenushowpts() +{ + CFrameWnd *MFrm; + MFrm=GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if(PtsFlag==FALSE){ + PtsFlag=TRUE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + } + else{ + PtsFlag=FALSE; + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + } + RedrawView(); +} + +void ChviewView::OnMenuContour() +{ + ChviewDoc *pDoc=GetDocument(); + + if(EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + + RedrawView(); + } + + EditAction=1; + + + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, TRUE); + tc->PressButton(ID_MENU_POINT, FALSE); +} + +void ChviewView::OnMenuPoint() +{ + ChviewDoc *pDoc=GetDocument(); + + if (EditAction==1){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + if (EditAction==2){ + BOOL flg=FALSE; + pDoc->bHasMask=FALSE; + UnselectAll(); + RedrawView(); + } + + EditAction=0; + + // update check boxes in the main menu... + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar; + pToolBar=&MFrm->m_HV_toolBar1; + CToolBarCtrl *tc=&pToolBar->GetToolBarCtrl(); + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc->PressButton(ID_MENU_AREA, FALSE); + tc->PressButton(ID_MENU_CONTOUR, FALSE); + tc->PressButton(ID_MENU_POINT, TRUE); + +} + +void ChviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + ChviewDoc *pDoc=GetDocument(); + + if (nChar==VK_LEFT) OnPanLeft(); + if (nChar==VK_RIGHT) OnPanRight(); + if (nChar==VK_UP) OnPanUp(); + if (nChar==VK_DOWN) OnPanDown(); + if (nChar==VK_PRIOR) OnZoomIn(); // page up + if (nChar==VK_NEXT) OnZoomOut(); // page down + if (nChar==VK_HOME) OnZoomNatural(); + + if ((nChar==VK_TAB) && (EditAction!=2)) EnterPoint(); + + if ((nChar==VK_DELETE) && (EditAction==1)){ + int k; + k=(int) pDoc->contour.GetSize(); + + if(k>1){ + EraseUserContour(FALSE); + pDoc->contour.RemoveAt(k-1); + DrawUserContour(TRUE); + } + else if(k!=0){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAt(0); + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==1)){ + EraseUserContour(TRUE); + pDoc->contour.RemoveAll(); + } + + if ((nChar==VK_SHIFT) && (EditAction==1)){ + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if ((nChar==VK_ESCAPE) && (EditAction==2)){ + UnselectAll(); + RedrawView(); + } + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void ChviewView::UnselectAll() +{ + ChviewDoc *pDoc=GetDocument(); + int i; + + pDoc->bHasMask=FALSE; + for(i=0;iblocklist.GetSize();i++) pDoc->blocklist[i].IsSelected=FALSE; + for(i=0;imeshnode.GetSize();i++) pDoc->meshnode[i].IsSelected=FALSE; + for(i=0;inodelist.GetSize();i++) pDoc->nodelist[i].IsSelected=FALSE; + for(i=0;ilinelist.GetSize();i++) pDoc->linelist[i].IsSelected=FALSE; + for(i=0;iarclist.GetSize();i++) pDoc->arclist[i].IsSelected=FALSE; +} + +void ChviewView::EnterPoint() +{ + CEnterPt pDlg; + double x,y,t; + ChviewDoc* pDoc = GetDocument(); + + // Send present parameter values to the dialog + // pDlg.m_rji=TheDoc->vi[0]; + + if(pDoc->Coords==FALSE){ + pDlg.m_coord1 = mx; + pDlg.m_coord2 = my; + if(pDoc->ProblemType==0){ + pDlg.m_label1 = "x-coord"; + pDlg.m_label2 = "y-coord"; + } + else{ + pDlg.m_label1 = "r-coord"; + pDlg.m_label2 = "z-coord"; + } + } + else{ + pDlg.m_coord1=sqrt(mx*mx+my*my); + pDlg.m_coord2=atan2(my,mx)*180/PI; + pDlg.m_label1="radius"; + pDlg.m_label2="degrees"; + } + + // Display dialog and collect data + if(pDlg.DoModal()==IDOK) + { + if(pDoc->Coords==FALSE){ + x=pDlg.m_coord1; + y=pDlg.m_coord2; + } + else{ + t=pDlg.m_coord2*PI/180; + x=pDlg.m_coord1*cos(t); + y=pDlg.m_coord1*sin(t); + } + if (EditAction==0) DisplayPointProperties(x,y); + if (EditAction==1){ + CComplex z; + z.Set(x,y); + pDoc->contour.Add(z); + DrawUserContour(FALSE); + } + } +} + +void ChviewView::SpecialLine(CDC *pDC, int X0, int Y0, int X1, int Y1, int flag) +{ + double l; + int i,j,k,p,x,y,z; + int hi,lo,zj; + BOOL InLine,DrawIt; + COLORREF c; + COLORREF Red; + RECT r; + + GetClientRect(&r); + Red=SelColor; + + int x0,y0,x1,y1,xb,yb; + + x0=X0; y0=Y0; + x1=X1; y1=Y1; + xb=r.right; + yb=r.bottom; + DrawIt=TRUE; + + // test to see if any of the endpoints are offscreen. + // if they are, crop them to the screen size + if ((x0<0) || (x0>xb) || (x1<0) || (x1>xb) || + (y0<0) || (y0>yb) || (y1<0) || (y1>yb)) + { + DrawIt=FALSE; + double z,dx0,dx1,dy0,dy1,dxb,dyb; + dx0=(double) x0; + dy0=(double) y0; + dx1=(double) x1; + dy1=(double) y1; + dxb=(double) xb; + dyb=(double) yb; + + + if ((x1-x0)!=0) + { + // test left side; + z=(-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0<0) + { + dx0=0; + x0=0; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=0; + x1=0; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + // test right side; + z=(dxb-dx0)/(dx1-dx0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(x0>xb) + { + dx0=dxb; + x0=xb; + dy0=dy0+z*(dy1-dy0); + y0=(int) dy0; + } + else{ + dx1=dxb; + x1=xb; + dy1=dy0+z*(dy1-dy0); + y1=(int) dy1; + } + } + + } + + if ((y1-y0)!=0) + { + // test top side; + z=(-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0<0) + { + dy0=0; + y0=0; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=0; + y1=0; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + + // test bottom side; + z=(dyb-dy0)/(dy1-dy0); + if ((z>=0.) && (z<=1.)) + { + DrawIt=TRUE; + if(y0>dyb) + { + dy0=dyb; + y0=yb; + dx0=dx0+z*(dx1-dx0); + x0=(int) dx0; + } + else{ + dy1=dyb; + y1=yb; + dx1=dx0+z*(dx1-dx0); + x1=(int) dx1; + } + } + } + } + + if(!DrawIt) return; + + l=(double)((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + l=sqrt(l); + k=(int) l; + for(i=0;i<=k;i++) + { + if(k!=0){ + x=x0+((x1-x0)*i)/k; + y=y0+((y1-y0)*i)/k; + } + else{ + x=x0; + y=y0; + } + + z=x+y*r.right; + + // check if this point is already in the line + // in the case that a red line is supposed to be drawn; + + if(flag==FALSE) + { + // bisection search to see if the pixel under + // consideration is already in LinePix + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj) InLine=TRUE; + } + zj=LinePix[hi].z; + if(z>=zj){ + hi+=1; + lo=hi; + if(z==zj) InLine=TRUE; + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + break; + } + else if(zjGetPixel(x,y); + if (hi==(int) LinePix.GetSize()) LinePix.Add(NewPixel); + else LinePix.InsertAt(hi,NewPixel); + } + } + + // if line is to be erased, get entry out of the pixel list + if(flag!=FALSE){ + // bisection search to find the pixel + InLine=FALSE; + lo=0; + hi=(int) LinePix.GetSize()-1; + if(hi>=0){ + zj=LinePix[0].z; + if(z<=zj){ + hi=0; + if(z==zj){ + InLine=TRUE; + p=0; + } + } + zj=LinePix[hi].z; + if(z>=zj){ + lo=hi; + if(z==zj){ + InLine=TRUE; + p=hi; + } + } + while((hi-lo)>1){ + j=(lo+hi)/2; + zj=LinePix[j].z; + if(zj==z){ + InLine=TRUE; + p=j; + break; + } + else if(zjPtVisible(x,y)!=FALSE) + { + if(flag==FALSE) pDC->SetPixel(x,y,Red); + else if(InLine==TRUE) pDC->SetPixel(x,y,c); + } + } + +} + + +void ChviewView::OnMenuPlot() +{ + hvCXYPlotDlg dlg; + ChviewDoc *pDoc=GetDocument(); + int PlotType,npoints,FileFormat; + BOOL ToFile; + + if ((EditAction!=1) || (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot create a plot;\nNo contour has been defined"); + return; + } + + dlg.m_npoints=d_PlotPoints; + if (dlg.DoModal()==IDOK){ + PlotType=dlg.XYPlotType; + FileFormat=dlg.FileFormat; + ToFile=dlg.m_ToFile; + npoints=dlg.m_npoints; + CXYPlot xyplot; + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->GetLineValues(xyplot,PlotType,npoints); + if (bLinehook==FALSE) EndWaitCursor(); + if(ToFile==FALSE){ + CMetaFileDC Meta; + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + HGLOBAL BoundingBox=GlobalAlloc(0,256); + xyplot.MakePlot(&Meta,(char *) BoundingBox); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + if (hMeta==NULL) MsgBox("No Handle..."); + if (OpenClipboard()==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + EmptyClipboard(); + if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL) + MsgBox("Couldn't SetClipboardData"); + if(SetClipboardData(CF_TEXT,BoundingBox)==NULL) + MsgBox("Couldn't SetClipboardData"); + CloseClipboard(); + + // fire up plot viewer; + ((CFemmApp *)AfxGetApp())->CreateNewDocument(8); + } + } + else xyplot.ToDisk(FileFormat); + } +} + +void ChviewView::OnMenuIntegrate() +{ + ChviewDoc *pDoc=GetDocument(); + int inttype; + + if (EditAction==0){ + MsgBox("Cannot integrate;\nNo contour or area\nhas been defined."); + return; + } + + if ((EditAction==1) && (pDoc->contour.GetSize()==0)){ + MsgBox("Cannot integrate;\nNo contour has been defined"); + return; + } + + if (EditAction==2){ + int i; + BOOL flg=FALSE; + for(i=0;iblocklist.GetSize();i++) + if (pDoc->blocklist[i].IsSelected==TRUE) flg=TRUE; + for(i=0;imeshnode.GetSize();i++) + if (pDoc->meshnode[i].IsSelected==TRUE) flg=TRUE; + if(flg==FALSE){ + MsgBox("Cannot integrate;\nNo area has been selected"); + return; + } + } + + if(EditAction==1){ + hvCLIntDlg dlg; + int inttype; + double z[4]; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.linttype; + char s[512]; + switch(inttype) + { + case 0: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Temperature Difference = %g K",Re(z[0])); + MyMessageBox(s); + break; + + case 1: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + sprintf(s,"Heat Flux = %g W\nAverage Heat Flux = %g W/m^2",z[0],z[1]); + MyMessageBox(s); + break; + + case 2: + pDoc->LineIntegral(inttype,z); + sprintf(s,"Contour length = %g meters\nSurface Area = %g meter^2",z[0],z[1]); + MyMessageBox(s); + break; + + case 3: + if (bLinehook==FALSE) BeginWaitCursor(); + pDoc->LineIntegral(inttype,z); + if (bLinehook==FALSE) EndWaitCursor(); + sprintf(s,"Average Temperature = %g K",z[0]); + MyMessageBox(s); + break; + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + } + } + + if(EditAction==2){ + hvCBlockInt dlg; + + if(dlg.DoModal()==IDOK){ + inttype=dlg.binttype; + CComplex z; + char s[512]; + // Average Temp over volume + // Block cross-section area + // Block volume + // Average F over volume + // Average G over volume + switch(inttype) + { + case 0: + z=pDoc->BlockIntegral(0); + sprintf(s,"%g K",Re(z)); + break; + + case 1: + z=pDoc->BlockIntegral(1); + sprintf(s,"%g meter^2",Re(z)); + break; + + case 2: + z=pDoc->BlockIntegral(2); + sprintf(s,"%g meter^3",Re(z)); + break; + + case 3: + z=pDoc->BlockIntegral(3); + if (pDoc->ProblemType==PLANAR) + sprintf(s,"Fx = %g W/m^2\nFy = %g W/m^2",Re(z),Im(z)); + else + sprintf(s,"Fr = %g W/m^2\nFz = %g W/m^2",Re(z),Im(z)); + break; + + case 4: + z=pDoc->BlockIntegral(4); + if (pDoc->ProblemType==PLANAR) + sprintf(s,"Gx = %g K/m\nGy = %g K/m",Re(z),Im(z)); + else + sprintf(s,"Gr = %g K/m\nGz = %g K/m",Re(z),Im(z)); + break; + + + default: + sprintf(s,"This space left intentionally blank"); + break; + } + MyMessageBox(s); + } + + } +} + + + +void ChviewView::OnSmooth() +{ + ChviewDoc *pDoc=GetDocument(); + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + + if (pDoc->Smooth==TRUE){ + pDoc->Smooth=FALSE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + } + else{ + pDoc->Smooth=TRUE; + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + } + RedrawView(); +} + +BOOL ChviewView::OnEraseBkgnd(CDC* pDC) +{ + + CBrush backBrush(BackColor); + + // Save old brush + CBrush* pOldBrush = pDC->SelectObject(&backBrush); + + CRect rect; + pDC->GetClipBox(&rect); // Erase the area needed + + pDC->PatBlt(rect.left, rect.top, rect.Width(), + rect.Height(), PATCOPY); + pDC->SelectObject(pOldBrush); + + return TRUE; + +} + +void ChviewView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + ChviewDoc *pDoc=GetDocument(); + + if(EditAction==0){ + int i=pDoc->ClosestNode(mx,my); + if(i>=0){ + char s[256]; + sprintf(s,"Closest input node:\n(%g,%g)",pDoc->nodelist[i].x, + pDoc->nodelist[i].y); + AfxMessageBox(s,MB_ICONINFORMATION); + } + } + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + CView::OnRButtonDblClk(nFlags, point); +} + + + + +void ChviewView::OnPanDown() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy-=0.25*y/mag; + + RedrawView(); +} + +void ChviewView::OnPanLeft() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox-=0.25*x/mag; + + RedrawView(); +} + +void ChviewView::OnPanRight() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + ox+=0.25*x/mag; + + RedrawView(); +} + +void ChviewView::OnPanUp() +{ + RECT r; + double x,y; + + GetClientRect(&r); + x=r.right; y=r.bottom; + oy+=0.25*y/mag; + + RedrawView(); +} + +void ChviewView::OnViewCircprops() +{ + hvCCircDlg dlg; + + dlg.TheDoc=GetDocument(); + dlg.DoModal(); + +} + +void ChviewView::RedrawView() +{ + LinePix.RemoveAll(); + InvalidateRect(NULL); +} + +BOOL ChviewView::ScanPreferences() +{ + FILE *fp; + CString fname; + + fname=BinDir+"hview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + VectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ShowNames); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +BOOL ChviewView::WritePreferences() +{ + FILE *fp; + CString fname; + ChviewDoc *pDoc=GetDocument(); + + fname=BinDir+"hview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("NameColor",NameColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorColor", VectorColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",d_EditAction); + fprintf(fp," = %i\n",d_DensityPlot); + fprintf(fp," = %i\n",d_VectorPlot); + fprintf(fp," = %i\n",d_GridFlag); + fprintf(fp," = %i\n",d_SnapFlag); + fprintf(fp," = %i\n",d_MeshFlag); + fprintf(fp," = %i\n",d_LegendFlag); + fprintf(fp," = %i\n",d_NumContours); + fprintf(fp," = %i\n",d_ShowAr); + fprintf(fp," = %i\n",d_ShowMask); + fprintf(fp," = %i\n",d_GreyContours); + fprintf(fp," = %i\n",d_PtsFlag); + fprintf(fp," = %i\n",d_ResetOnReload); + fprintf(fp," = %i\n",d_Smooth); + fprintf(fp," = %i\n",d_PlotPoints); + fprintf(fp," = %i\n",d_ShowNames); + fprintf(fp," = %i\n", + pDoc->d_LineIntegralPoints); + + fclose(fp); + } + else return FALSE; + + return TRUE; +} + +void ChviewView::CheckIt() +{ + // make sure all of the right things are checked + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + CMenu* MMnu=MFrm->GetMenu(); + CToolBar *pToolBar1,*pToolBar2; + pToolBar1=&MFrm->m_HV_toolBar1; + pToolBar2=&MFrm->m_leftbar; + CToolBarCtrl *tc1=&pToolBar1->GetToolBarCtrl(); + CToolBarCtrl *tc2=&pToolBar2->GetToolBarCtrl(); + + if(SnapFlag==FALSE){ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SNAP_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SNAP_GRID, MF_CHECKED); + tc2->PressButton(ID_SNAP_GRID,TRUE); + } + + + if(GridFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_UNCHECKED); + tc2->PressButton(ID_SHOW_GRID,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_GRID, MF_CHECKED); + tc2->PressButton(ID_SHOW_GRID,TRUE); + } + + if(MeshFlag==FALSE){ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_UNCHECKED); + tc1->PressButton(ID_SHOW_MESH,FALSE); + } + else{ + MMnu->CheckMenuItem(ID_SHOW_MESH, MF_CHECKED); + tc1->PressButton(ID_SHOW_MESH,TRUE); + } + + MMnu->CheckMenuItem(ID_MENU_AREA, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_UNCHECKED); + MMnu->CheckMenuItem(ID_MENU_POINT, MF_UNCHECKED); + tc1->PressButton(ID_MENU_AREA, FALSE); + tc1->PressButton(ID_MENU_CONTOUR, FALSE); + tc1->PressButton(ID_MENU_POINT,FALSE); + + if (EditAction==2){ + MMnu->CheckMenuItem(ID_MENU_AREA, MF_CHECKED); + tc1->PressButton(ID_MENU_AREA, TRUE); + } + if (EditAction==1){ + MMnu->CheckMenuItem(ID_MENU_CONTOUR, MF_CHECKED); + tc1->PressButton(ID_MENU_CONTOUR, TRUE); + } + if (EditAction==0){ + MMnu->CheckMenuItem(ID_MENU_POINT, MF_CHECKED); + tc1->PressButton(ID_MENU_POINT,TRUE); + } + + if(PtsFlag==TRUE) + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_CHECKED); + else + MMnu->CheckMenuItem(ID_MENUSHOWPTS, MF_UNCHECKED); + + ChviewDoc *pDoc=GetDocument(); + if (pDoc->Smooth==FALSE) + MMnu->CheckMenuItem(ID_SMOOTH, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_SMOOTH, MF_CHECKED); + + if (ShowNames==FALSE) + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_UNCHECKED); + else + MMnu->CheckMenuItem(ID_VIEW_SHOWBLOCKNAMES, MF_CHECKED); + + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + +} + +void ChviewView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + ChviewDoc *pDoc=GetDocument(); + + if(EditAction==1) + { + if(pDoc->contour.GetSize()>1) + { + CBendContourDlg dlg; + dlg.DoModal(); + if (dlg.m_angle!=0){ + EraseUserContour(FALSE); + pDoc->BendContour(dlg.m_angle,dlg.m_anglestep); + DrawUserContour(TRUE); + } + } + } + + if(EditAction==2) + { + int i,k,grp,sel; + + if (pDoc->meshelem.GetSize()>0){ + k=pDoc->InTriangle(mx,my); + if(k>=0){ + pDoc->bHasMask=FALSE; + grp=pDoc->blocklist[pDoc->meshelem[k].lbl].InGroup; + sel=pDoc->blocklist[pDoc->meshelem[k].lbl].IsSelected; + for(i=0;iblocklist.GetSize();i++) + if ((pDoc->blocklist[i].InGroup==grp) && + (pDoc->blocklist[i].IsSelected!=sel)) + { + pDoc->blocklist[i].IsSelected=sel; + DrawSelected=i; + CDC *pDC=GetDC(); + OnDraw(pDC); + DrawSelected=-1; + ReleaseDC(pDC); + } + } + } + } + + CView::OnLButtonDblClk(nFlags, point); +} + + + +void ChviewView::OnViewInfo() +{ + ChviewDoc *pDoc=GetDocument(); + CString s,z,outbox; + + // first line; + outbox.Format("Title: %s\r\n",pDoc->GetTitle()); + + // second line; + switch(pDoc->LengthUnits){ + case 0: + s="Length Units: Inches"; + z=" in"; + break; + case 1: + s="Length Units: Millimeters"; + z=" mm"; + break; + case 2: + s="Length Units: Centimeters"; + z=" cm"; + break; + case 4: + s="Length Units: Mils"; + z=" mil"; + break; + case 5: + s="Length Units: Micrometers"; + z=" um"; + break; + default: + s="Length Units: Meters"; + z=" m"; + break; + } + outbox+="\r\n" + s; + + // third line + if(pDoc->ProblemType==TRUE) s="Axisymmetric Solution"; + else{ + s.Format("2-D Planar (Depth: %g", + pDoc->Depth/pDoc->LengthConv[pDoc->LengthUnits]); + s=s+z+")"; + } + outbox+="\r\n" + s; + + // fourth line + s.Format(""); + outbox+="\r\n" + s; + + // fifth line + s.Format(""); + outbox+="\r\n" + s; + + // sixth line + s.Format("%i Nodes",pDoc->meshnode.GetSize()); + outbox+="\r\n" + s; + + // seventh line + s.Format("%i Elements",pDoc->meshelem.GetSize()); + outbox+="\r\n" + s; + + // display it + Dspl->SetDlgItemText(IDC_OUTBOX,outbox); + OutputWindowText=outbox; +} + +void ChviewView::OnViewShowblocknames() +{ + // TODO: Add your command handler code here + ShowNames=1-ShowNames; + RedrawView(); +} + +void ChviewView::OnVplot() +{ + // TODO: Add your command handler code here + hvCVPlotDlg dlg; + + dlg.m_vectorscalefactor=VectorScaleFactor; + dlg.m_plottype=VectorPlot; + if(dlg.DoModal()==IDOK) + { + VectorScaleFactor=dlg.m_vectorscalefactor; + VectorPlot=dlg.m_plottype; + InvalidateRect(NULL); + } +} + +void ChviewView::MyMoveTo(CDC *pDC, int x, int y) +{ + Xm=x; + Ym=y; +} + +void ChviewView::MyLineTo(CDC *pDC, int x, int y) +{ + // trivial case + if ((x==Xm) && (y==Ym)) return; + + RECT r; + int Zm; + GetClientRect(&r); + Zm=__max(__max(r.right,r.bottom),__max(r.left,r.top)); + Zm=(Zm*3)/2; + + // as long as all the coordinates are small enough, + // everything works normally + if ((abs(Xm) MoveTo(Xm,Ym); + pDC-> LineTo(x,y); + } + else{ + // otherwise, we have to do some limiting to make sure + // that the plotting routines don't go berzerk. + CComplex p,q,pc,qc; + double a,b,c,u0,u1; + + p=(Xm+I*Ym)/((double) Zm); + q=(x+I*y)/((double) Zm); + pc=conj(p); + qc=conj(q); + + c = Re(p*pc-1.); + b = Re(-2.*p*pc + pc*q + p*qc); + a = Re(p*pc - pc*q - p*qc + q*qc); + + if (fabs(a)!=0) + { + b/=a; + c/=a; + if((b*b-4.*c)>0) + { + // there is some possible intersection with the viewable region... + u0=-b/2. + sqrt(b*b-4.*c)/2.; + u1=-b/2. - sqrt(b*b-4.*c)/2.; + if(u10)) + { + if (u0<0) u0=0; + if (u1>1) u1=1; + pc=p*(1.-u0) + q*u0; + qc=p*(1.-u1) + q*u1; + pc*=((double) Zm); + qc*=((double) Zm); + pDC-> MoveTo((int) Re(pc), (int) Im(pc)); + pDC-> LineTo((int) Re(qc), (int) Im(qc)); + } + } + } + + } + + // update the current position + Xm=x; + Ym=y; +} + +BOOL ChviewView::IsMinimized() +{ + CChildFrame *pChildFrm = (CChildFrame *)GetParentFrame(); + if (pChildFrm->GetStyle() & WS_MINIMIZE) return TRUE; return FALSE; +} + +void ChviewView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) +{ + if((bActivate) && (pActivateView==this)) + { + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetTopLevelFrame(); + if (!MFrm->IsIconic()){ + MFrm->SetBar(6); + CheckIt(); + } + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + + CView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +BOOL ChviewView::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 CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +void ChviewView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + // The child frame makes a special effort to pass down the + // WM_SIZE message when a window is minimized. The view + // uses this message to minimize the output window, if it is visible. + if(nType==SIZE_MINIMIZED) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if(MFrm->m_dlgBar.GetStyle() & WS_VISIBLE) MFrm->m_dlgBar.ShowWindow(SW_HIDE); + } + + if((nType==SIZE_MAXIMIZED) || (nType==SIZE_RESTORED)) + { + CMainFrame *MFrm=(CMainFrame *)theApp.GetMainWnd(); + if((theApp.bShowOutputWindow) && (!IsMinimized()) && (!MFrm->IsIconic())){ + MFrm->m_dlgBar.ShowWindow(SW_SHOWNOACTIVATE); + MFrm->m_dlgBar.SetDlgItemText(IDC_OUTBOX,OutputWindowText); + } + } + +} diff --git a/femm/hviewView.h b/femm/hviewView.h new file mode 100644 index 0000000..838723f --- /dev/null +++ b/femm/hviewView.h @@ -0,0 +1,230 @@ +// hviewView.h : interface of the ChviewView class +// +///////////////////////////////////////////////////////////////////////////// + +class ChviewView : public CView +{ +protected: // create from serialization only + ChviewView(); + DECLARE_DYNCREATE(ChviewView) + +// Attributes +public: + + ChviewDoc* GetDocument(); + + void ScreenToDwg(int xs, int ys, double *xd, double *yd, RECT *r); + BOOL DwgToScreen(double xd, double yd, int *xs, int *ys, RECT *r); + void EnterPoint(); + + int EditAction; // tells if operating on points, lines, or blox + double mx,my; // location of the mouse in model coordinates + double ox,oy,mag; // location of lower left corner & scaling factor + CStatusBar* StatBar; // pointer to the main window's status bar + double GridSize; // size of each block in the grid + BOOL GridFlag; // Flag telling whether or not to show grid + BOOL SnapFlag; + BOOL MeshFlag; + BOOL LegendFlag; + BOOL GreyContours; + BOOL PtsFlag; + BOOL Coords; // False=Cartesian; True=Polar + BOOL ShowNames; + double VectorScaleFactor; + int ZoomWndFlag; + int DrawSelected; + double wzx,wzy; + +// default behaviors + int d_EditAction; + BOOL d_GridFlag; + BOOL d_SnapFlag; + BOOL d_MeshFlag; + BOOL d_LegendFlag; + BOOL d_GreyContours; + int d_NumContours; + BOOL d_ShowAr; + BOOL d_ShowMask; + int d_DensityPlot; + int d_VectorPlot; + BOOL d_PtsFlag; + BOOL d_ResetOnReload; + BOOL d_Smooth; + BOOL d_PlotPoints; + BOOL d_ShowNames; + + COutBox *Dspl; + CString BinDir; // pathname for triangle.exe + + int NumContours; + BOOL ShowAr,ShowMask; + int DensityPlot; + int VectorPlot; + CString OutputWindowText; + + CArray< CPixel, CPixel& > LinePix; + CArray< CZPix, CZPix& > ZoomPix; + + // Greyscale Density Plot Colormap + COLORREF Grey00; + COLORREF Grey01; + COLORREF Grey02; + COLORREF Grey03; + COLORREF Grey04; + COLORREF Grey05; + COLORREF Grey06; + COLORREF Grey07; + COLORREF Grey08; + COLORREF Grey09; + COLORREF Grey10; + COLORREF Grey11; + COLORREF Grey12; + COLORREF Grey13; + COLORREF Grey14; + COLORREF Grey15; + COLORREF Grey16; + COLORREF Grey17; + COLORREF Grey18; + COLORREF Grey19; + + // Density Plot Colormap + COLORREF Color00; + COLORREF Color01; + COLORREF Color02; + COLORREF Color03; + COLORREF Color04; + COLORREF Color05; + COLORREF Color06; + COLORREF Color07; + COLORREF Color08; + COLORREF Color09; + COLORREF Color10; + COLORREF Color11; + COLORREF Color12; + COLORREF Color13; + COLORREF Color14; + COLORREF Color15; + COLORREF Color16; + COLORREF Color17; + COLORREF Color18; + COLORREF Color19; + + // Other colors + COLORREF SelColor; + COLORREF MeshColor; + COLORREF BlockColor; + COLORREF LineColor; + COLORREF RegionColor; + COLORREF GridColor; + COLORREF BackColor; + COLORREF TextColor; + COLORREF NodeColor; + COLORREF RealFluxLineColor; + COLORREF NameColor; + COLORREF MaskLineColor; + COLORREF VectorColor; + +// Operations +public: + + void DoContours(CDC *pDC, int *p, int side, int Aflag); + void PlotFluxDensity(CDC *pDC,int elmnum,int flag); + void DisplayPointProperties(double px, double py); + void DrawUserContour(BOOL flag); + void EraseUserContour(BOOL flag); + void SpecialLine(CDC *pDC, int x0, int y0, int x1, int y1, BOOL flag); + void PlotSelectedElm(CDC *pDC,hviewtype::CElement &elm); + void RedrawView(); + void UnselectAll(); + + void MyMoveTo(CDC *pDC, int x, int y); + void MyLineTo(CDC *pDC, int x, int y); + BOOL IsMinimized(); + BOOL ScanPreferences(); + BOOL WritePreferences(); + void CheckIt(); + void LuaViewInfo(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ChviewView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~ChviewView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(ChviewView) + afx_msg void OnSmooth(); + afx_msg void OnZoomIn(); + afx_msg void OnSnapGrid(); + afx_msg void OnShowMesh(); + afx_msg void OnShowGrid(); + afx_msg void OnSetGrid(); + afx_msg void OnCplot(); + afx_msg void OnDplot(); + afx_msg void OnZoomNatural(); + afx_msg void OnZoomOut(); + afx_msg void OnZoomWindow(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnEditCopy(); + afx_msg void OnReload(); + afx_msg void OnMenuArea(); + afx_msg void OnMenuContour(); + afx_msg void OnMenuPoint(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMenuPlot(); + afx_msg void OnMenuIntegrate(); + afx_msg void OnMenushowpts(); + afx_msg void OnKbdZoom(); + afx_msg void Onintegral(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnPanDown(); + afx_msg void OnPanLeft(); + afx_msg void OnPanRight(); + afx_msg void OnPanUp(); + afx_msg void OnHelpFinder(); + afx_msg void OnViewCircprops(); + afx_msg void OnEditCopyAsMetafile(); + afx_msg void OnHelpLicense(); + afx_msg void OnViewInfo(); + afx_msg void OnViewShowblocknames(); + afx_msg void OnVplot(); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); +}; + +#ifndef _DEBUG // debug version in hviewView.cpp +inline ChviewDoc* ChviewView::GetDocument() + { return (ChviewDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + + diff --git a/femm/luaDDX.cpp b/femm/luaDDX.cpp new file mode 100644 index 0000000..3524a90 --- /dev/null +++ b/femm/luaDDX.cpp @@ -0,0 +1,155 @@ +#include "stdafx.h" +#include "lua.h" +#include "femm.h" + +#undef DDX_Text + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +extern CFemmApp theApp; +extern lua_State * lua; + +// changed 27Nov2005 to work right with complex-valued Lua + +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, int &x) +{ + // if initializing things, just call DDX_Text in the usual way... + if (pDX->m_bSaveAndValidate==FALSE) + DDX_Text(pDX, nIDC, x); + // otherwise, side-track things by sending the contents + // to Lua, processing them, and then stripping off the results; + else{ + CString tolua; + int i,k; + DDX_Text(pDX, nIDC, tolua); + tolua="return " + tolua; + i=lua_gettop(lua); + lua_dostring(lua,tolua); + k=lua_gettop(lua); + if (i!=k){ + tolua=lua_tostring(lua,-1); + if (tolua.GetLength()==0){ + AfxMessageBox("Input does not evaluate to a numerical value"); + pDX->Fail(); + } + else x=(int)Re(lua_tonumber(lua,-1)); + } + else pDX->Fail(); + } + +} + +void Lua_DDX_Text(CDataExchange* pDX, int nIDC, CString& value) +{ + DDX_Text(pDX, nIDC, value); +} + +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, double &x) +{ + // if initializing things, just call DDX_Text in the usual way... + if (pDX->m_bSaveAndValidate==FALSE) + DDX_Text(pDX, nIDC, x); + // otherwise, side-track things by sending the contents + // to Lua, processing them, and then stripping off the results; + else{ + CString tolua; + int i,k; + DDX_Text(pDX, nIDC, tolua); + tolua="return " + tolua; + i=lua_gettop(lua); + lua_dostring(lua,tolua); + k=lua_gettop(lua); + if (i!=k){ + tolua=lua_tostring(lua,-1); + if (tolua.GetLength()==0){ + AfxMessageBox("Input does not evaluate to a numerical value"); + pDX->Fail(); + } + else x=Re(lua_tonumber(lua,-1)); + } + else pDX->Fail(); + } + +} + +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, CComplex &x) +{ + // if initializing things, call the DDX_Text version used to + // initialize strings. The string form of the desired complex + // number is used as the initializer. We have to do this because + // there is no native complex form of DDX_Text. + if (pDX->m_bSaveAndValidate==FALSE) + { + CString tmp; + tmp.Format("%s",ToString(x,16)); + DDX_Text(pDX, nIDC, tmp); + } + // otherwise, side-track things by sending the contents + // to Lua, processing them, and then stripping off the results; + else{ + CString tolua; + int i,k; + DDX_Text(pDX, nIDC, tolua); + tolua="return " + tolua; + i=lua_gettop(lua); + lua_dostring(lua,tolua); + k=lua_gettop(lua); + if (i!=k){ + tolua=lua_tostring(lua,-1); + if (tolua.GetLength()==0){ + AfxMessageBox("Input does not evaluate to a numerical value"); + pDX->Fail(); + } + else x=lua_tonumber(lua,-1); + } + else pDX->Fail(); + } + +} + +// Special form to use for magnet direction, where result could either be +// a hard number or a function to be evaluated later... +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, double &x, CString &s) +{ + // if initializing things, just call DDX_Text in the usual way... + if (pDX->m_bSaveAndValidate==FALSE) + DDX_Text(pDX, nIDC, x); + // otherwise, side-track things by sending the contents + // to Lua, processing them, and then stripping off the results; + else{ + CString tolua; + int i,k; + DDX_Text(pDX, nIDC, tolua); + + lua_State *LocalLua = lua_open(100); + lua_baselibopen(LocalLua); + lua_strlibopen(LocalLua); + lua_mathlibopen(LocalLua); + + tolua="return " + tolua; + i=lua_gettop(LocalLua); + lua_dostring(LocalLua,tolua); + k=lua_gettop(LocalLua); + if (i!=k){ + tolua=lua_tostring(LocalLua,-1); + if (tolua.GetLength()==0){ + DDX_Text(pDX, nIDC, s); + x=0; + } + else{ + x=Re(lua_tonumber(LocalLua,-1)); + s.Empty(); + } + } + else{ + DDX_Text(pDX, nIDC, s); + x=0; + } + lua_close(LocalLua); + } + +} diff --git a/femm/luaDDX.h b/femm/luaDDX.h new file mode 100644 index 0000000..24f6db6 --- /dev/null +++ b/femm/luaDDX.h @@ -0,0 +1,10 @@ +void Lua_DDX_Text(CDataExchange* pDX, int nIDC, int& value); + +void Lua_DDX_Text(CDataExchange* pDX, int nIDC, CString& value); + +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, double &x); + +void Lua_DDX_Text(CDataExchange *pDX, int nIDC, CComplex &x); + +void Lua_DDX_Text(CDataExchange* pDX, int nIDC, double &x, CString& value); + diff --git a/femm/luadebug.h b/femm/luadebug.h new file mode 100644 index 0000000..77753d3 --- /dev/null +++ b/femm/luadebug.h @@ -0,0 +1,46 @@ +/* +** $Id: luadebug.h,v 1.17 2000/10/30 12:38:50 roberto Exp $ +** Debugging API +** See Copyright Notice in lua.h +*/ + + +#ifndef luadebug_h +#define luadebug_h + + +#include "lua.h" + +typedef struct lua_Debug lua_Debug; /* activation record */ +typedef struct lua_Localvar lua_Localvar; + +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); + +LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); +LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + const char *event; /* `call', `return' */ + int currentline; /* (l) */ + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `tag method', `local', `field' */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ + const char *source; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct lua_TObject *_func; /* active function */ +}; + + +#endif diff --git a/femm/makemask.cpp b/femm/makemask.cpp new file mode 100644 index 0000000..01097d4 --- /dev/null +++ b/femm/makemask.cpp @@ -0,0 +1,397 @@ +#include "stdafx.h" +#include +#include +#include "problem.h" +#include "femm.h" +#include "xyplot.h" +#include "femmviewDoc.h" +#include "femmviewView.h" +#include "MainFrm.h" +#include "maskprogress.h" +#include "lua.h" + +#include "spars.h" + +extern BOOL bLinehook; +extern CLuaConsoleDlg *LuaConsole; + +// #define SIMPLE + +#ifdef SIMPLE + +BOOL CFemmviewDoc::MakeMask() +{ + // Good placeholder mask generator + // This gives a valid mask that butts right up against the + // selected region. This mask yields the same results as the + // Coulomb virtual work method. + + int i,j; + + for(i=0;ibw) bw=d; + } + } + bw++; + + L.Create(NumNodes,bw); + + // if the problem is axisymmetric, does the selection lie along r=0? + if(ProblemType==1) + for(i=0;i=0) lblflag[i]=1; + } + + // Determine which nodal values should be fixed + // and what values they should be fixed at; + for(i=0;i0) + { + CComplex *p; + int npts; + + p=(CComplex *)calloc(nodelist.GetSize(),sizeof(CComplex)); + for(i=0,npts=0;i=0) + { + p[npts]=nodelist[i].CC(); + npts++; + } + + if(npts>0) + for(i=0;i0){ + p[j]=p[npts]; + j=npts; + } + else{ + j=npts; + i=NumNodes; + } + } + free(p); + } + + // build up element matrices; + for(i=0;iToOutput(outmsg); + } + else{ + outmsg ="The selected region is invalid. A valid selection\n"; + outmsg+="cannot abut a region which is not free space."; + MsgBox(outmsg); + } + free(matflag); + free(lblflag); + return FALSE; + } + } + + switch(WeightingScheme) + { + case 1: + // all elements evenly weighted + v=1; + break; + + case 2: + // weights each element with the sqrt of its own area; + v=sqrt(a); + break; + + case 3: + // determine a weighting for the element + // based on an error measure; + for(j=0,bsq=0,dbsq=0;j<3;j++) + { + dbsq+=Re((meshelem[i].B1-meshelem[i].b1[j])* + conj(meshelem[i].B1-meshelem[i].b1[j]) + + (meshelem[i].B2-meshelem[i].b2[j])* + conj(meshelem[i].B2-meshelem[i].b2[j])); + bsq +=Re(meshelem[i].B1*conj(meshelem[i].B1) + + meshelem[i].B2*conj(meshelem[i].B2)); + } + if(bsq!=0) v=dbsq/bsq; + else(v=1); + break; + + case 4: + // determine a weighting for the element + // based on an error measure; + for(k=0,dbsq=0,bsq=0;k<3;k++) + for(j=0;j=0) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + for (k=j;k<3;k++) + if(Me[j][k]!=0) L.Put(L.Get(n[j],n[k])-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // solve the problem; + bLinehook=BuildMask; + if (L.PCGSolve(FALSE)==FALSE) return FALSE; + bLinehook=FALSE; + for(i=0;i0.5) meshnode[i].msk=1; + else meshnode[i].msk=0; + break; + + default: + meshnode[i].msk = L.V[i]; + break; + } + } + free(matflag); + free(lblflag); + bHasMask=TRUE; + + return TRUE; +} + +#endif + +BOOL CFemmviewDoc::IsKosher(int k) +{ + // If: + // 1) this is an axisymmetric problem; + // 2) the selected geometry lies along the r=0 axis, and + // 3) we have a node on the r=0 axis that we are trying to determine + // if we should set to zero. + // This routine determines whether the node is at the extents of + // the r=0 domain (or lies at a break in some sub-interval). + // + // Returns TRUE if it is OK to define the node as zero; + + if((ProblemType==0) || (meshnode[k].x>1.e-6)) return TRUE; + + int i,j,n; + int score=0; + + for(i=0;i1) return FALSE; + } + } + } + + return TRUE; +} diff --git a/femm/mathlink.h b/femm/mathlink.h new file mode 100644 index 0000000..cb032c5 --- /dev/null +++ b/femm/mathlink.h @@ -0,0 +1,3136 @@ +/************************************************************************* + + Copyright 1986 through 2002 by Wolfram Research Inc. + All rights reserved + +*************************************************************************/ + +#ifndef _MATHLINK_H +#define _MATHLINK_H + +#if __BORLANDC__ && ! __BCPLUSPLUS__ +#pragma warn -stu +#endif + +#ifndef _MLVERS_H +#define _MLVERS_H + +#ifndef _MLPLATFM_H +#define _MLPLATFM_H + +#if ! MACINTOSH_MATHLINK && ! WINDOWS_MATHLINK && ! UNIX_MATHLINK && ! OS2_MATHLINK +# if 0 +# if __BEOS__ +# define BE_MATHLINK 1 +# elif macintosh || Macintosh || THINK_C || defined(_MAC) || defined(__MRC__) +# define MACINTOSH_MATHLINK 1 +# elif defined(WIN16) || defined(_WIN16) +# define WINDOWS_MATHLINK 1 +# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +# define WINDOWS_MATHLINK 1 +# elif unix || __unix || __unix__ ||_AIX +# define UNIX_MATHLINK 1 +# endif +# endif +# define WINDOWS_MATHLINK 1 +#endif + +#if MACINTOSH_MATHLINK +# if (powerc || __powerc || __powerc__) +# define POWERMACINTOSH_MATHLINK 1 +# else +# define M68KMACINTOSH_MATHLINK 1 +# if defined(__CFM68K__) +# define CFM68K_MACINTOSH_MATHLINK 1 +# else +# define CLASSIC68K_MACINTOSH_MATHLINK 1 +# endif +# endif +#elif WINDOWS_MATHLINK +# if defined(WIN32) || defined(__WIN32__) || defined(__NT__) || defined(_WIN32) +# define WIN32_MATHLINK 1 +# if( _M_IX86 || __i386 || __i386__ || i386) +# define I86_WIN32_MATHLINK 1 +# elif _M_ALPHA || __alpha || __alpha__ || alpha +# define ALPHA_WIN32_MATHLINK 1 +# else +# endif +# else +# define WIN16_MATHLINK 1 +# endif +#elif UNIX_MATHLINK +# if (__sun || __sun__ || sun) && !defined(SUN_MATHLINK) +# define SUN_MATHLINK 1 +# if __SVR4 || __svr4__ +# define SOLARIS_MATHLINK 1 +# else +# define SUNOS_MATHLINK 1 +# endif +# if __sparc || __sparc__ || sparc +# define SPARC_SUN_MATHLINK 1 +# elif __i386 || __i386__ || i386 +# define I86_SUN_MATHLINK 1 +# else + unknown platform +# endif +# elif (__MACH || __MACH__ || MACH) && !defined(DARWIN_MATHLINK) +# define DARWIN_MATHLINK 1 +# if __ppc || __ppc__ || ppc +# define PPC_DARWIN_MATHLINK 1 +# else + not yet implemented +# endif +# elif (__linux || __linux__ || linux) && !defined(LINUX_MATHLINK) +# define LINUX_MATHLINK 1 +# if __i386 || __i386__ || i386 +# define I86_LINUX_MATHLINK 1 +# elif __PPC || __PPC__ || PPC +# define PPC_LINUX_MATHLINK 1 +# elif __alpha || __alpha__ || alpha +# define AXP_LINUX_MATHLINK 1 +# else + not yet implemented +# endif +# elif (__osf || __osf__ || osf || OSF1) && !defined(DIGITAL_MATHLINK) +# define DIGITAL_MATHLINK 1 +# if __alpha || __alpha__ || alpha +# define ALPHA_DIGITAL_MATHLINK 1 +# else + unknown platform +# endif +# elif (_AIX || _IBMR2 || __xlC__) && !defined(AIX_MATHLINK) +# define AIX_MATHLINK 1 +# elif (__sgi || __sgi__ || sgi || mips) && !defined(IRIX_MATHLINK) +# define IRIX_MATHLINK 1 +# elif (hpux || __hpux) && !defined(HPUX_MATHLINK) +# define HPUX_MATHLINK 1 +# elif (M_I386 || _SCO_DS || SCO) && !defined(SCO_MATHLINK) +# define SCO_MATHLINK 1 +# elif (__NetBSD__) && !defined(NETBSD_MATHLINK) +# define NETBSD_MATHLINK 1 +# elif (__FreeBSD__) && !defined(FREEBSD_MATHLINK) +# define FREEBSD_MATHLINK 1 +# elif (bsdi || __bsdi__) && !defined(BSDI_MATHLINK) +# define BSDI_MATHLINK 1 +# else +# endif +#else +# if defined(__amigaos__) || defined(AMIGA) +# define AMIGA_MATHLINK 1 +# endif +# if __BEOS__ +# define BE_MATHLINK 1 +# endif +#endif + + + +#ifndef NO_GLOBAL_DATA +# if M68KMACINTOSH_MATHLINK +# define NO_GLOBAL_DATA 1 +# else +# define NO_GLOBAL_DATA 0 +# endif +#endif + +#if WINDOWS_MATHLINK || __i386 || __i386__ || i386 || _M_IX86 || __alpha || __alpha__ || alpha +# define LITTLEENDIAN_NUMERIC_TYPES 1 +#else +# define BIGENDIAN_NUMERIC_TYPES 1 +#endif + +#endif /* _MLPLATFM_H */ + +#ifndef MLVERSION +# define MLVERSION 3 +#endif + +#if !OLD_VERSIONING + + +/* + * MathLink adopts a simple versioning strategy that can be adapted to many + * compile-time and run-time environments. In particular, it is amenable to + * the various shared library facilities in use. (Although certain of these + * facilities provide more sophisticated mechanisms than are required by the + * following simple strategy.) + * + * MathLink evolves by improving its implementation and by improving its + * interface. The values of MLREVISION or MLINTERFACE defined here are + * incremented whenever an improvement is made and released. + * + * MLREVISION is the current revision number. It is incremented every time + * a change is made to the source and MathLink is rebuilt and distributed + * on any platform. (Bug fixes, optimizations, or other improvements + * transparent to the interface increment only this number.) + * + * MLINTERFACE is a name for a documented interface to MathLink. This + * number is incremented whenever a named constant or function is added, + * removed, or its behavior is changed in a way that could break existing + * correct* client programs. It is expected that the interface to MathLink + * is improved over time so that implemenations of higher numbered + * interfaces are more complete or more convenient to use for writing + * effective client programs. In particular, a specific interface provides + * all the useful functionality of an earlier interface. + * + * *(It is possible that an incorrect MathLink program still works + * because it relies on some undocumented detail of a particular + * revision. It may not always be possible to change the interface + * number when such a detail changes. For example, one program may + * be relying on a bug in MathLink that a great many other programs + * need fixed. In this case, we would likely choose to potentially + * break the incorrect program in order to fix the correct programs + * by incrementing the revision number leaving the interface number + * unchanged. It is possible to bind to a particular revision of a + * MathLink interface if that is important for some programs. One + * could use a statically linked version of the library, make use of + * the search algorithm used by the runtime loader, or dynamically + * load the MathLink library manually.) + * + * + * If a distributed MathLink implmentation were labeled with its revision + * and interface numbers in dotted notation so that, say, ML.1.6 means the + * sixth revision of interface one, then the following may represent the + * distribution history of MathLink. + * + * first distribution + * ML.1.5 (Perhaps earlier revisions were never + * distributed for this platform.) + * + * second distribution + * ML.1.6 (Bug fixes or other improvements were + * made that don't affect the interface.) + * + * third distribution + * ML.2.7 (Perhaps some new functions were added.) + * + * ML.1.7 (And improvements were made that don't + * affect the old interface.) + * + * fourth distribution + * ML.3.8 (Perhaps the return values of an existing + * function changed.) + * ML.2.8 (Revision 8 also adds improvements transparent + * to interface 2.) + * ML.1.7 (Clients of interface 1 see no improvements + * in this eighth revision.) + * + * Note that the distribution history may not be the same on different + * platforms. But revision numbers represent a named body of source code + * across all platforms. + * + * The mechanism for deploying this strategy differs between platforms + * because of differing platform-specific facilities and conventions. + * The interface and revision numbers may form part of the filename of + * the MathLink library, or they may not. This information is always + * available in some conventional form so that it is easy and natural for + * client programs to bind with and use the best available implementation + * of a particular MathLink interface. The details are described in the + * MathLink Developer's Guide for each platform. + */ + +#define MLREVISION 10 + +#define MLAPI1REVISION 1 /* the first revision to support interface 1 */ +#define MLAPI2REVISION 6 /* the first revision to support interface 2 */ + + +#ifndef MLINTERFACE +# define MLINTERFACE 2 +# define MLAPIREVISION MLAPI2REVISION + /* + * Interface 2 adds the following exported functions: + * MLGetBinaryNumberArray0 + * MLTransfer0 + * MLNextCharacter0 + * And, for WINDOWS_MATHLINK, some constants in "mlntypes.h" + * were changed in a way that causes MLGetRawType to return + * different values. + * + * MLPutNullSequence and MLEGETENDEXPR pushed to interface 3 + */ +#else +# if MLINTERFACE == 1 +# define MLAPIREVISION MLAPI1REVISION +# elif MLINTERFACE == 2 +# define MLAPIREVISION MLAPI2REVISION +# else +/* syntax error */ ) +# endif +#endif + + +/* It may be possible for an implementation of one MathLink interface to + * fully support an earlier interface. MLNewParameters() may succeed when + * passed an interface number less than the value of MLAPIREVISION when the + * library was built. This would happen, if the newer interface is a proper + * superset of the older interface, or if the implementation can adjust its + * behavior at runtime to conform to the older requested interface. + */ + +#ifndef MLOLDDEFINITION +# if WINDOWS_MATHLINK +# if MLINTERFACE == 1 +# define MLOLDDEFINITION MLAPI1REVISION +# elif MLINTERFACE == 2 +# define MLOLDDEFINITION MLAPI2REVISION +# else +/* syntax error */ ) +# endif +# else +# define MLOLDDEFINITION MLAPI1REVISION +# endif +#endif + + +#if 0 +MLParameters s; +MLNewParameters( s, MLREVISION, MLAPIREVISION); or MLNewParameters( s, 0, MLAPIREVISION); +MLSetAllocParameter( s, allocator, deallocator); +MLIntialize(s); +#endif + + + + + + + + +#else +/* syntax error */ ) +#endif + +#endif /* _MLVERS_H */ + + + +#ifndef ML_EXTERN_C + +#if defined(__cplusplus) +# define ML_C "C" +# define ML_EXTERN_C extern "C" { +# define ML_END_EXTERN_C } +#else +# define ML_C +# define ML_EXTERN_C +# define ML_END_EXTERN_C +#endif + +#endif + + + +#if WINDOWS_MATHLINK && (MPREP_REVISION || !defined(APIENTRY) || !defined(FAR)) + +#if defined(WIN32_LEAN_AND_MEAN) && defined(WIN32_EXTRA_LEAN) +# include +#elif defined( WIN32_LEAN_AND_MEAN) +# define WIN32_EXTRA_LEAN +# include +# undef WIN32_EXTRA_LEAN +#elif defined( WIN32_EXTRA_LEAN) +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +#else +# define WIN32_EXTRA_LEAN +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_EXTRA_LEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif + +#ifndef _MLCFM_H +#define _MLCFM_H + + +#if MACINTOSH_MATHLINK +#ifndef GENERATINGCFM +# ifdef USESROUTINEDESCRIPTORS +# define GENERATINGCFM USESROUTINEDESCRIPTORS +# elif MACINTOSH_MATHLINK +# include +# ifndef GENERATINGCFM +# define GENERATINGCFM USESROUTINEDESCRIPTORS +# endif +# else +# define GENERATINGCFM 0 +# endif +#endif +#endif /* MACINTOSH_MATHLINK */ + + +#if MACINTOSH_MATHLINK +# include +#elif DARWIN_MATHLINK && defined(__CONDITIONALMACROS__) +# if defined(GENERATINGCFM) +# undef GENERATINGCFM +# define GENERATINGCFM 0 +# endif /* defined(GENERATINGCFM) */ +# if defined(GENERATING68K) +# undef GENERATING68K +# define GENERATING68K 0 +# endif /* defined(GENERATING68K) */ +#else + enum { + kPascalStackBased = 0, + kCStackBased = 0, + kThinkCStackBased = 0 + }; +# define SIZE_CODE(size) (0) +# define RESULT_SIZE(sizeCode) (0) +# define STACK_ROUTINE_PARAMETER(whichParam, sizeCode) (0) +#endif + + +#endif /* _MLCFM_H */ + + +#ifdef __CFM68K__ +#pragma import on +#endif + + +#ifndef _MLDEVICE_H +#define _MLDEVICE_H + + +#ifndef P + +# ifndef MLPROTOTYPES +# define MLPROTOTYPES 1 +# endif + +# if MLPROTOTYPES || __STDC__ || defined(__cplusplus) || ! UNIX_MATHLINK +# define P(s) s +# undef MLPROTOTYPES +# define MLPROTOTYPES 1 +# else +# define P(s) () +# undef MLPROTOTYPES +# define MLPROTOTYPES 0 +# endif +#endif +#ifndef _MLFAR_H +#define _MLFAR_H + +#ifndef FAR + +#if WINDOWS_MATHLINK +# ifndef FAR +/* syntax error */ ) +# endif +#else +# define FAR +#endif + + +#endif + +/* //rename this file mlfarhuge.h */ + +#ifndef MLHUGE +# if WINDOWS_MATHLINK && ! WIN32_MATHLINK +# define MLHUGE huge +# else +# define MLHUGE +# endif +#endif + +#endif /* _MLFAR_H */ + +#ifndef _MLTYPES_H +#define _MLTYPES_H + + +#if WINDOWS_MATHLINK +# ifndef APIENTRY +# define APIENTRY far pascal +# endif +# ifndef CALLBACK +# define CALLBACK APIENTRY +# endif +# if WIN32_MATHLINK + /* try this #define MLEXPORT __declspec(dllexport) */ +# define MLEXPORT +# else +# define MLEXPORT __export +# endif +# define MLCB APIENTRY MLEXPORT +# define MLAPI APIENTRY + +#elif OS2_MATHLINK +# include +# define MLEXPORT +# define MLCB APIENTRY +# define MLAPI APIENTRY +#elif CLASSIC68K_MACINTOSH_MATHLINK +# define MLAPI pascal +# define MLEXPORT +# if defined(__MWERKS__) +# if !__fourbyteints__ +# define __uint_ct__ unsigned long +# define __int_ct__ long +# endif +# elif defined(THINK_C) || defined(SYMANTEC_C) || defined(SYMANTEC_CPLUS) +# if !__option(int_4) +# define __uint_ct__ unsigned long +# define __int_ct__ long +# endif +# endif +#else +# define MLCB +# define MLAPI +# define MLEXPORT +#endif + +#define MLAPI_ MLAPI + + +#ifndef MLDEFN +# define MLDEFN( rtype, name, params) extern rtype MLAPI MLEXPORT name params +#endif +#ifndef MLDECL +# define MLDECL( rtype, name, params) extern rtype MLAPI name P(params) +#endif + +#ifndef ML_DEFN +# define ML_DEFN( rtype, name, params) extern rtype MLAPI_ MLEXPORT name params +#endif +#ifndef ML_DECL +# define ML_DECL( rtype, name, params) extern ML_C rtype MLAPI_ name P(params) +#endif + + + +#if MACINTOSH_MATHLINK + +#ifndef MLCBPROC +# define MLCBPROC( rtype, name, params) typedef pascal rtype (* name) P(params) +#endif +#ifndef MLCBDECL +# define MLCBDECL( rtype, name, params) extern pascal rtype name P(params) +#endif +#ifndef MLCBDEFN +# define MLCBDEFN( rtype, name, params) extern pascal rtype name params +#endif + +#elif OS2_MATHLINK + +#ifndef MLCBPROC +# define MLCBPROC( rtype, name, params) typedef rtype (* MLCB name) P(params) +#endif +#ifndef MLCBDECL +# define MLCBDECL( rtype, name, params) extern rtype MLCB name P(params) +#endif +#ifndef MLCBDEFN +# define MLCBDEFN( rtype, name, params) extern rtype MLCB name params +#endif + +#else + +#ifndef MLCBPROC +# define MLCBPROC( rtype, name, params) typedef rtype (MLCB * name) P(params) +#endif +#ifndef MLCBDECL +# define MLCBDECL( rtype, name, params) extern rtype MLCB name P(params) +#endif +#ifndef MLCBDEFN +# define MLCBDEFN( rtype, name, params) extern rtype MLCB name params +#endif + +#endif + + + + +/* move into mlalert.h */ +#ifndef MLDPROC +# define MLDPROC MLCBPROC +#endif +#ifndef MLDDECL +# define MLDDECL MLCBDECL +#endif +#ifndef MLDDEFN +# define MLDDEFN MLCBDEFN +#endif + + + + +/* move into ml3state.h or mlstrenv.h */ +#ifndef MLTPROC +# define MLTPROC MLCBPROC +#endif +#ifndef MLTDECL +# define MLTDECL MLCBDECL +#endif +#ifndef MLTDEFN +# define MLTDEFN MLCBDEFN +#endif + + +/* move into mlnumenv.h */ +#ifndef MLNPROC +# define MLNPROC MLCBPROC +#endif +#ifndef MLNDECL +# define MLNDECL MLCBDECL +#endif +#ifndef MLNDEFN +# define MLNDEFN MLCBDEFN +#endif + + +/* move into mlalloc.h */ +#ifndef MLAPROC +# define MLAPROC MLCBPROC +#endif +#ifndef MLADECL +# define MLADECL MLCBDECL +#endif +#ifndef MLADEFN +# define MLADEFN MLCBDEFN +#endif +#ifndef MLFPROC +# define MLFPROC MLCBPROC +#endif +#ifndef MLFDECL +# define MLFDECL MLCBDECL +#endif +#ifndef MLFDEFN +# define MLFDEFN MLCBDEFN +#endif + + + + +/* move into mlstddev.h */ +#ifndef MLYPROC +# define MLYPROC MLCBPROC +#endif +#ifndef MLYDECL +# define MLYDECL MLCBDECL +#endif +#ifndef MLYDEFN +# define MLYDEFN MLCBDEFN +#endif +#ifndef MLMPROC +# define MLMPROC MLCBPROC +#endif +#ifndef MLMDECL +# define MLMDECL MLCBDECL +#endif +#ifndef MLMDEFN +# define MLMDEFN MLCBDEFN +#endif + + +/* move into mlmake.h */ +#ifndef MLUPROC +# define MLUPROC MLCBPROC +#endif +#ifndef MLUDECL +# define MLUDECL MLCBDECL +#endif +#ifndef MLUDEFN +# define MLUDEFN MLCBDEFN +#endif + + +/* move into mlmake.h */ +#ifndef MLBPROC +# define MLBPROC MLCBPROC +#endif +#ifndef MLBDECL +# define MLBDECL MLCBDECL +#endif +#ifndef MLBDEFN +# define MLBDEFN MLCBDEFN +#endif + +#ifndef MLDMPROC +# define MLDMPROC MLCBPROC +#endif +#ifndef MLDMDECL +# define MLDMDECL MLCBDECL +#endif +#ifndef MLDMDEFN +# define MLDMDEFN MLCBDEFN +#endif + + +#ifndef __uint_ct__ +#define __uint_ct__ unsigned int +#endif +#ifndef __int_ct__ +#define __int_ct__ int +#endif + + +typedef unsigned char uchar_ct; +typedef uchar_ct FAR * ucharp_ct; +typedef ucharp_ct FAR * ucharpp_ct; +typedef ucharpp_ct FAR * ucharppp_ct; +typedef unsigned short ushort_ct; +typedef ushort_ct FAR * ushortp_ct; +typedef ushortp_ct FAR * ushortpp_ct; +typedef ushortpp_ct FAR * ushortppp_ct; +typedef __uint_ct__ uint_ct; +typedef __int_ct__ int_ct; +typedef void FAR * voidp_ct; +typedef voidp_ct FAR * voidpp_ct; +typedef char FAR * charp_ct; +typedef charp_ct FAR * charpp_ct; +typedef charpp_ct FAR * charppp_ct; +typedef long FAR * longp_ct; +typedef longp_ct FAR * longpp_ct; +typedef unsigned long ulong_ct; +typedef ulong_ct FAR * ulongp_ct; + + + + +#ifndef MLCONST +# if MLPROTOTYPES +# define MLCONST const +# else +# define MLCONST +# endif +#endif + +typedef MLCONST unsigned short FAR * kushortp_ct; +typedef MLCONST unsigned short FAR * FAR * kushortpp_ct; +typedef MLCONST unsigned char FAR * kucharp_ct; +typedef MLCONST unsigned char FAR * FAR * kucharpp_ct; +typedef MLCONST char FAR * kcharp_ct; +typedef MLCONST char FAR * FAR * kcharpp_ct; +typedef MLCONST void FAR * kvoidp_ct; + + +typedef void FAR * MLPointer; + +#ifndef __MLENV__ + typedef struct ml_environment FAR *MLENV; + typedef MLENV MLEnvironment; +# define __MLENV__ +#endif + +#ifndef __MLINK__ + typedef struct MLink FAR *MLINK; +# define __MLINK__ +#endif + +#ifndef __MLMARK__ + typedef struct MLinkMark FAR *MLMARK; + typedef MLMARK MLINKMark; +# define __MLMARK__ +#endif + +#ifndef __mlapi_token__ +#define __mlapi_token__ int_ct +#endif +typedef __mlapi_token__ mlapi_token; + + +typedef unsigned long mlapi__token; +typedef mlapi__token FAR * mlapi__tokenp; + +#ifndef __mlapi_packet__ +#define __mlapi_packet__ int_ct +#endif +typedef __mlapi_packet__ mlapi_packet; + + +typedef long mlapi_error; +typedef long mlapi__error; + +typedef long long_st; +typedef longp_ct longp_st; +typedef longpp_ct longpp_st; + +typedef long long_et; + + +#ifndef __mlapi_result__ +#define __mlapi_result__ int_ct +#endif +typedef __mlapi_result__ mlapi_result; + + +#define MLSUCCESS (1) /*bugcheck: this stuff doesnt belong where it can be seen at MLAPI_ layer */ +#define MLFAILURE (0) + +ML_EXTERN_C + +#if WINDOWS_MATHLINK +typedef int (CALLBACK *__MLProcPtr__)(); +#else +typedef long (*__MLProcPtr__)(); +#endif + +ML_END_EXTERN_C + +#endif /* _MLTYPES_H */ + + +#if WINDOWS_MATHLINK +# ifndef APIENTRY +# define APIENTRY far pascal +# endif +# define MLBN APIENTRY /* bottleneck function: upper layer calls lower layer */ +#else +# define MLBN +#endif + +#define BN MLBN + + + +ML_EXTERN_C + + + +typedef void FAR * dev_voidp; +typedef dev_voidp dev_type; +typedef dev_type FAR * dev_typep; +typedef long devproc_error; +typedef unsigned long devproc_selector; + + +#define MLDEV_WRITE_WINDOW 0 +#define MLDEV_WRITE 1 +#define MLDEV_HAS_DATA 2 +#define MLDEV_READ 3 +#define MLDEV_READ_COMPLETE 4 +#define MLDEV_ACKNOWLEDGE 5 + +#define T_DEV_WRITE_WINDOW MLDEV_WRITE_WINDOW +#define T_DEV_WRITE MLDEV_WRITE +#define T_DEV_HAS_DATA MLDEV_HAS_DATA +#define T_DEV_READ MLDEV_READ +#define T_DEV_READ_COMPLETE MLDEV_READ_COMPLETE + + +#ifndef SCATTERED +#define SCATTERED 0 +#undef NOT_SCATTERED +#define NOT_SCATTERED 1 +#endif + + +#if powerc +#pragma options align=mac68k +#endif + +typedef struct read_buf { + unsigned short length; + unsigned char* ptr; +} read_buf; + +typedef read_buf FAR * read_bufp; +typedef read_bufp FAR * read_bufpp; + +#if powerc +#pragma options align=reset +#endif + + + +MLDMPROC( devproc_error, MLDeviceProcPtr, ( dev_type dev, devproc_selector selector, dev_voidp p1, dev_voidp p2)); +MLDMDECL( devproc_error, MLDeviceMain, ( dev_type dev, devproc_selector selector, dev_voidp p1, dev_voidp p2)); + +#if MACINTOSH_MATHLINK +enum { + uppMLDeviceProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(devproc_error))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(dev_type))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(devproc_selector))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(dev_voidp))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(dev_voidp))) +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLDeviceUPP; +# define CallMLDeviceProc(userRoutine, thing, selector, p1, p2) \ + CallUniversalProc((userRoutine), uppMLDeviceProcInfo, (thing), (selector), (p1), (p2)) +# define NewMLDeviceProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)(userRoutine), uppMLDeviceProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLDeviceProcPtr MLDeviceUPP; +# define CallMLDeviceProc(userRoutine, thing, selector, p1, p2) (*(userRoutine))((thing), (selector), (dev_voidp)(p1), (dev_voidp)(p2)) +# define NewMLDeviceProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#else /* !MACINTOSH_MATHLINK */ + typedef MLDeviceProcPtr MLDeviceUPP; +# define CallMLDeviceProc(userRoutine, thing, selector, p1, p2) (*(userRoutine))((thing), (selector), (dev_voidp)(p1), (dev_voidp)(p2)) +# define NewMLDeviceProc(userRoutine) (userRoutine) +#endif /* MACINTOSH_MATHLINK */ + +typedef MLDeviceUPP dev_main_type; +typedef dev_main_type FAR * dev_main_typep; + +ML_END_EXTERN_C + + +#endif /* _MLDEVICE_H */ + + +#ifndef _MLAPI_H +#define _MLAPI_H + + +ML_EXTERN_C + +#ifndef _MLALLOC_H +#define _MLALLOC_H + + + + +MLAPROC( MLPointer, MLAllocatorProcPtr, (unsigned long)); + +#if MACINTOSH_MATHLINK +enum { + uppMLAllocatorProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(MLPointer))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned long))) +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLAllocatorUPP; +# define CallMLAllocatorProc(userRoutine, size) \ + (MLPointer)CallUniversalProc((userRoutine), uppMLAllocatorProcInfo, (size)) +# define NewMLAllocatorProc(userRoutine) \ + NewRoutineDescriptor(MLAllocatorCast((userRoutine)), uppMLAllocatorProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLAllocatorProcPtr MLAllocatorUPP; +# define CallMLAllocatorProc(userRoutine, size) (*(userRoutine))((size)) +# define NewMLAllocatorProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#else /* !MACINTOSH_MATHLINK */ + typedef MLAllocatorProcPtr MLAllocatorUPP; +# define CallMLAllocatorProc(userRoutine, size) (*(userRoutine))((size)) +# define NewMLAllocatorProc(userRoutine) (userRoutine) +#endif /* MACINTOSH_MATHLINK */ + + + + +MLFPROC( void, MLDeallocatorProcPtr, (MLPointer)); + +#if MACINTOSH_MATHLINK +enum { + uppMLDeallocatorProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLPointer))) +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLDeallocatorUPP; +# define CallMLDeallocatorProc(userRoutine, p) \ + CallUniversalProc((userRoutine), uppMLDeallocatorProcInfo, (p)) +# define NewMLDeallocatorProc(userRoutine) \ + NewRoutineDescriptor(MLDeallocatorCast((userRoutine)), uppMLDeallocatorProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLDeallocatorProcPtr MLDeallocatorUPP; +# define CallMLDeallocatorProc(userRoutine, p) (*(userRoutine))((p)) +# define NewMLDeallocatorProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#else /* !MACINTOSH_MATHLINK */ + typedef MLDeallocatorProcPtr MLDeallocatorUPP; +# define CallMLDeallocatorProc(userRoutine, p) (*(userRoutine))((p)) +# define NewMLDeallocatorProc(userRoutine) (userRoutine) +#endif /* MACINTOSH_MATHLINK */ + + + +#endif /* _MLALLOC_H */ + + +/* explicitly not protected by _MLALLOC_H in case MLDECL is redefined for multiple inclusion */ + + +/* just some type-safe casts */ +MLDECL( __MLProcPtr__, MLAllocatorCast, ( MLAllocatorProcPtr f)); +MLDECL( __MLProcPtr__, MLDeallocatorCast, ( MLDeallocatorProcPtr f)); + +ML_END_EXTERN_C + +typedef MLAllocatorUPP MLAllocator; +typedef MLAllocator FAR * MLAllocatorp; +#define MLCallAllocator CallMLAllocatorProc +#define MLNewAllocator NewMLAllocatorProc + +typedef MLDeallocatorUPP MLDeallocator; +typedef MLDeallocator FAR * MLDeallocatorp; +#define MLCallDeallocator CallMLDeallocatorProc +#define MLNewDeallocator NewMLDeallocatorProc + +#define MLallocator MLAllocator +#define MLdeallocator MLDeallocator + +#endif /* _MLAPI_H */ + + +#ifndef _MLNTYPES_H +#define _MLNTYPES_H + + +#ifndef _MLNUMENV_H +#define _MLNUMENV_H + + +/* mlne__s2 must convert empty strings to zero */ + + + +ML_EXTERN_C + + +#define REALBIT 4 +#define REAL_MASK (1 << REALBIT) +#define XDRBIT 5 +#define XDR_MASK (1 << XDRBIT) +#define BINARYBIT 7 +#define BINARY_MASK (1 << BINARYBIT) +#define SIZEVARIANTBIT 6 +#define SIZEVARIANT_MASK (1 << SIZEVARIANTBIT) + + + +#define MLNE__IMPLIED_SIZE( tok, num_dispatch) ((tok) & XDR_MASK || !((tok) & SIZEVARIANT_MASK) \ + ? (tok) & 0x08 ? (tok) & (0x0E + 2) : (1 << ((tok)>>1 & 0x03)) \ + : call_num_dispatch( (num_dispatch), MLNE__SIZESELECTOR((tok)), 0,0,0)) + +/* Range[-128, 127] */ +#define MLTK_8BIT_SIGNED_2sCOMPLEMENT_INTEGER 160 /* ((unsigned char)'\240') */ +/* Range[0, 255] */ +#define MLTK_8BIT_UNSIGNED_2sCOMPLEMENT_INTEGER 161 /* ((unsigned char)'\241') */ +#define MLTK_8BIT_UNSIGNED_INTEGER MLTK_8BIT_UNSIGNED_2sCOMPLEMENT_INTEGER + +/* Range[-32768, 32767] */ +#define MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 162 /* ((unsigned char)'\242') */ +/* Range[0, 65535] */ +#define MLTK_16BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 163 /* ((unsigned char)'\243') */ +#define MLTK_16BIT_UNSIGNED_BIGENDIAN_INTEGER MLTK_16BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +/* Range[-2147483648, 2147483647] */ +#define MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 164 /* ((unsigned char)'\244') */ +/* Range[0, 4294967295] */ +#define MLTK_32BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 165 /* ((unsigned char)'\245') */ +#define MLTK_32BIT_UNSIGNED_BIGENDIAN_INTEGER MLTK_32BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +/* Range[-9223372036854775808, 9223372036854775807] */ +#define MLTK_64BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 166 /* ((unsigned char)'\246') */ +/* Range[0, 18446744073709551615] */ +#define MLTK_64BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER 167 /* ((unsigned char)'\247') */ +#define MLTK_64BIT_UNSIGNED_BIGENDIAN_INTEGER MLTK_64BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER + + +/* Range[-32768, 32767] */ +#define MLTK_16BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 226 /* ((unsigned char)'\342') */ +/* Range[0, 65535] */ +#define MLTK_16BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 227 /* ((unsigned char)'\343') */ +#define MLTK_16BIT_UNSIGNED_LITTLEENDIAN_INTEGER MLTK_16BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +/* Range[-2147483648, 2147483647] */ +#define MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 228 /* ((unsigned char)'\344') */ +/* Range[0, 4294967295] */ +#define MLTK_32BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 229 /* ((unsigned char)'\345') */ +#define MLTK_32BIT_UNSIGNED_LITTLEENDIAN_INTEGER MLTK_32BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +/* Range[-9223372036854775808, 9223372036854775807] */ +#define MLTK_64BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 230 /* ((unsigned char)'\346') */ +/* Range[0, 18446744073709551615] */ +#define MLTK_64BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER 231 /* ((unsigned char)'\347') */ +#define MLTK_64BIT_UNSIGNED_LITTLEENDIAN_INTEGER MLTK_64BIT_UNSIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER + +/* Interval[{-3.402823e+38, 3.402823e+38}] */ +#define MLTK_BIGENDIAN_IEEE754_SINGLE 180 /* ((unsigned char)'\264') */ +/* Interval[{-1.79769313486232e+308, 1.79769313486232e+308}] */ +#define MLTK_BIGENDIAN_IEEE754_DOUBLE 182 /* ((unsigned char)'\266') */ + +/* Interval[{-3.402823e+38, 3.402823e+38}] */ +#define MLTK_LITTLEENDIAN_IEEE754_SINGLE 244 /* ((unsigned char)'\364') */ +/* Interval[{-1.79769313486232e+308, 1.79769313486232e+308}] */ +#define MLTK_LITTLEENDIAN_IEEE754_DOUBLE 246 /* ((unsigned char)'\366') */ + +/* Note, if the future brings... + * #define MLTK_128BIT_UNSIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER ((unsigned char)'\257') + * with Range[0, 340282366920938463463374607431768211456 (*approximately 3.40282e+38*)] + * the dynamic range is still a monotonically increasing function of the token value. + * An implementation might choose to set the high varient bit to mainain this property + * and dispatch more efficiently by avoiding overflow checks + */ + +#define MLNE__SELECTOR( dtok, stok) \ + (((dtok) << 8) | (stok)) /* maybe should mask of high word and cast stok */ + +#define MLNE__SIZESELECTOR( tok) MLNE__SELECTOR( 0, tok) +#define MLNE__INITSELECTOR (0) +#define MLNE__TOSTRINGSELECTOR( tok) MLNE__SELECTOR( MLNE__IS_REAL(tok) ? MLTKREAL : MLTKINT, tok) +#define MLNE__FROMSTRINGSELECTOR( dtok, stok) MLNE__SELECTOR( dtok, stok) + +#define MLNE__STOK( selector) ( (selector) & 0x000000FF) +#define MLNE__DTOK( selector) ( ((selector) & 0x0000FF00)>>8) + +#define MLNE__IS_BINARY( tok) ((tok) & BINARY_MASK) +#define MLNE__IS_REAL( tok) ((tok) & REAL_MASK) +#define MLNE__TEXT_TOKEN( tok) (MLNE__IS_REAL( tok) ? MLTKREAL : MLTKINT) + + + +MLNDECL( long_et, mlne__dispatch, ( unsigned long selector, void* dptr, void* sptr, long* countp)); +MLNPROC( long_et, dispatch_procptr_mlnet, ( unsigned long selector, void* dptr, void* sptr, long* countp)); + +/* will null terminate strings only if countp is null */ + +#if MACINTOSH_MATHLINK +enum { + uppNumDispatchProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(long_et))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned long))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long*))) +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM && GENERATING68K /* on the powerpc use standard native shared library calling conventions */ + typedef UniversalProcPtr dispatch_function_mlnet; +# define call_num_dispatch( num_dispatch, selector, dptr, sptr, countp) \ + (long_et)CallUniversalProc( (num_dispatch), uppNumDispatchProcInfo, (selector), (dptr), (sptr), (countp)) +# define new_num_dispatch(num_dispatch) \ + NewRoutineDescriptor((ProcPtr)(num_dispatch), uppNumDispatchProcInfo, GetCurrentArchitecture()) +#else /* !(GENERATINGCFM && GENERATING68K && !DIRECT_TEXT_CALLS) */ + typedef dispatch_procptr_mlnet dispatch_function_mlnet; +# define call_num_dispatch(num_dispatch, selector, dptr, sptr, countp) \ + ((*(num_dispatch))( (selector), (dptr), (sptr), (countp))) +# define new_num_dispatch(num_dispatch) (num_dispatch) +#endif /* GENERATINGCFM && GENERATING68K && !DIRECT_TEXT_CALLS */ +#else /* !MACINTOSH_MATHLINK */ + typedef dispatch_procptr_mlnet dispatch_function_mlnet; +# define call_num_dispatch(num_dispatch, selector, dptr, sptr, countp) \ + ((*(num_dispatch))( (selector), (dptr), (sptr), (countp))) +# define new_num_dispatch(num_dispatch) (num_dispatch) +#endif /* MACINTOSH_MATHLINK */ + + + +ML_END_EXTERN_C + + +#endif /* _MLNUMENV_H */ + +#ifndef MLINTERFACE +/* syntax error */ ) +#endif + +/* MLTK_CSHORT_P 193 + MLTK_CINT_P 194 + MLTK_CLONG_P 195 + MLTK_CFLOAT_P 209 + MLTK_CDOUBLE_P 210 + MLTK_CLONGDOUBLE_P 211 */ + +#define MLTK_CSHORT_P (( BINARY_MASK | SIZEVARIANT_MASK | 1)) +#define MLTK_CINT_P (( BINARY_MASK | SIZEVARIANT_MASK | 2)) +#define MLTK_CLONG_P (( BINARY_MASK | SIZEVARIANT_MASK | 3)) +#define MLTK_CFLOAT_P (( BINARY_MASK | SIZEVARIANT_MASK | REAL_MASK | 1)) +#define MLTK_CDOUBLE_P (( BINARY_MASK | SIZEVARIANT_MASK | REAL_MASK | 2)) +#define MLTK_CLONGDOUBLE_P (( BINARY_MASK | SIZEVARIANT_MASK | REAL_MASK | 3)) + + +#define MLTK_CUCHAR MLTK_8BIT_UNSIGNED_2sCOMPLEMENT_INTEGER +#define MLTK_MLUCHAR MLTK_8BIT_UNSIGNED_2sCOMPLEMENT_INTEGER + +#if MACINTOSH_MATHLINK + /* two private tokens */ + /* Interval[{-1.189731495357231765e+4932, 1.189731495357231765e+4932}] */ +# define MLTK_80BIT_SANE_EXTENDED 152 /* ((unsigned char)'\230') */ +# define MLTK_96BIT_68881_EXTENDED 154 /* ((unsigned char)'\232') */ +#endif + +#if POWERMACINTOSH_MATHLINK + /* one private token */ +# define MLTK_128BIT_LONGDOUBLE 158 /* ((unsigned char)'\236') */ +#endif + +#if WINDOWS_MATHLINK + /* one private token */ + /* Interval[{-1.189731495357231765e+4932, 1.189731495357231765e+4932}] */ +# define MLTK_INTEL_80BIT_EXTENDED 216 /* ((unsigned char)'\330') */ +# if MLINTERFACE > 1 +# define NEW_WIN32_NUMENV 1 +# endif +#endif + + + + + +#if M68KMACINTOSH_MATHLINK +# define MATHLINK_NUMERICS_ENVIRONMENT_ID "Sep 16 1996, 23:14:20" + +# define MLTK_CSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER + +# define MLTK_CFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE + +# if defined(__MWERKS__) +# if __fourbyteints__ +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# else +# define MLTK_CINT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# endif +# if __MC68881__ +# define MLTK_CLONGDOUBLE MLTK_96BIT_68881_EXTENDED +# else +# define MLTK_CLONGDOUBLE MLTK_80BIT_SANE_EXTENDED +# endif +# if __IEEEdoubles__ || __ieeedoubles__ +# define MLTK_CDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# else +# define MLTK_CDOUBLE MLTK_CLONGDOUBLE +# endif +# elif defined(THINK_C) || defined(SYMANTEC_C) || defined(SYMANTEC_CPLUS) +# if __option(int_4) +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# else +# define MLTK_CINT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# endif +# if __option(native_fp) && !__option(mc68881) +# define MLTK_CLONGDOUBLE MLTK_80BIT_SANE_EXTENDED +# else +# define MLTK_CLONGDOUBLE MLTK_96BIT_68881_EXTENDED +# endif +# if __option(double_8) +# define MLTK_CDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# else +# define MLTK_CDOUBLE MLTK_CLONGDOUBLE +# endif +# else /* applec */ +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# if mc68881 +# define MLTK_CLONGDOUBLE MLTK_96BIT_68881_EXTENDED +# else +# define MLTK_CLONGDOUBLE MLTK_80BIT_SANE_EXTENDED +# endif +# endif + +# if 0 /* no more statically linked Macintosh libraries STATICALLY_LINKED_MATHLINK */ +# define MLTK_MLSHORT MLTK_CSHORT +# define MLTK_MLINT MLTK_CINT +# define MLTK_MLLONG MLTK_CLONG +# define MLTK_MLFLOAT MLTK_CFLOAT +# define MLTK_MLDOUBLE MLTK_CDOUBLE +# define MLTK_MLLONGDOUBLE MLTK_CLONGDOUBLE +# else +# define MLTK_MLSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE +# define MLTK_MLDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# define MLTK_MLLONGDOUBLE MLTK_80BIT_SANE_EXTENDED +# endif + +#elif POWERMACINTOSH_MATHLINK +# define MATHLINK_NUMERICS_ENVIRONMENT_ID "newdog" + +# define MLTK_CSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER + +# define MLTK_CFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE +# define MLTK_CDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE + + +# ifndef MLTK_CLONGDOUBLE +# if defined(__MWERKS__) || defined(SYMANTEC_C) || defined(SYMANTEC_CPLUS) +# define MLTK_CLONGDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# elif defined(__MRC__) && __MRC__ >= 0x0300 && __MRC__ != 0x0800 + /* MrC version 1.0 defined __MRC__ to be 0x0800 presumably because of its Symantec heritage */ + /* One cannot querry value of -ldsize with old MrC or PPCC -- assume -ldsize 128 */ +# if __option(ldsize128) +# define MLTK_CLONGDOUBLE MLTK_128BIT_LONGDOUBLE +# else +# define MLTK_CLONGDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# endif +# else +# define MLTK_CLONGDOUBLE MLTK_128BIT_LONGDOUBLE +# endif +# endif + +# define MLTK_MLSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE +# define MLTK_MLDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# define MLTK_MLLONGDOUBLE MLTK_128BIT_LONGDOUBLE + +#elif SUN_MATHLINK + + +# if __sparc || __sparc__ || sparc + +# define MLTK_CSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_CFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE +# define MLTK_CDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# ifndef MLTK_CLONGDOUBLE +# if __SUNPRO_C >= 0x301 + /* one private token */ +# define MLTK_128BIT_LONGDOUBLE 158 /* ((unsigned char)'\236') */ +# define MLTK_CLONGDOUBLE MLTK_128BIT_LONGDOUBLE +# elif defined(__GNUC__) || defined(__GNUG__) +# define MLTK_CLONGDOUBLE MLTK_CDOUBLE +# else + /* no error directive here as the user may be + * using a different compiler. Some macros + * simply won't be available. + */ +# endif +# endif + +# define MLTK_MLSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_BIGENDIAN_INTEGER +# define MLTK_MLFLOAT MLTK_BIGENDIAN_IEEE754_SINGLE +# define MLTK_MLDOUBLE MLTK_BIGENDIAN_IEEE754_DOUBLE +# define MLTK_MLLONGDOUBLE MLTK_128BIT_LONGDOUBLE + +# elif __i386 || __i386__ || i386 + +/* syntax error */ ) + +# if __SUNPRO_C >= 0x301 + /* one private token */ + /* Interval[{-1.189731495357231765e+4932, 1.189731495357231765e+4932}] */ +# define MLTK_96BIT_HIGHPADDED_INTEL_80BIT_EXTENDED 218 /* ((unsigned char)'\332') */ +# define MLTK_CSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_CINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_CLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_CFLOAT MLTK_LITTLEENDIAN_IEEE754_SINGLE +# define MLTK_CDOUBLE MLTK_LITTLEENDIAN_IEEE754_DOUBLE +# define MLTK_CLONGDOUBLE MLTK_96BIT_HIGHPADDED_INTEL_80BIT_EXTENDED +# elif defined(__GNUC__) || defined(__GNUG__) + /* no error directive here as the user may be + * using a different compiler. Some macros + * simply won't be available. + */ +# else + /* no error directive here as the user may be + * using a different compiler. Some macros + * simply won't be available. + */ +# endif + + +# else +/* syntax error */ ) +# endif + + +#elif WIN16_MATHLINK || (WIN32_MATHLINK && NEW_WIN32_NUMENV) +# if WIN16_MATHLINK +# define MATHLINK_NUMERICS_ENVIRONMENT_ID "poodle" +# elif WIN32_MATHLINK +# define MATHLINK_NUMERICS_ENVIRONMENT_ID "setter" +# endif + +# define MLTK_CSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_CLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_CFLOAT MLTK_LITTLEENDIAN_IEEE754_SINGLE +# define MLTK_CDOUBLE MLTK_LITTLEENDIAN_IEEE754_DOUBLE + +# if WIN16_MATHLINK +# define MLTK_CINT MLTK_CSHORT +# elif WIN32_MATHLINK +# define MLTK_CINT MLTK_CLONG +# endif + +# if __WATCOMC__ || __SC__ +# define MLTK_CLONGDOUBLE MLTK_LITTLEENDIAN_IEEE754_DOUBLE +# elif __BORLANDC__ || __BCPLUSPLUS__ || __TURBOC__ || __TCPLUSPLUS__ +# define MLTK_CLONGDOUBLE MLTK_INTEL_80BIT_EXTENDED +# elif _MSC_VER +# if WIN16_MATHLINK +# define MLTK_CLONGDOUBLE MLTK_INTEL_80BIT_EXTENDED +# elif WIN32_MATHLINK +# define MLTK_CLONGDOUBLE MLTK_LITTLEENDIAN_IEEE754_DOUBLE +# endif +# endif + + +# define MLTK_MLSHORT MLTK_16BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# if WIN16_MATHLINK +# define MLTK_MLINT MLTK_16BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# elif WIN32_MATHLINK +# define MLTK_MLINT MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# endif +# define MLTK_MLLONG MLTK_32BIT_SIGNED_2sCOMPLEMENT_LITTLEENDIAN_INTEGER +# define MLTK_MLFLOAT MLTK_LITTLEENDIAN_IEEE754_SINGLE +# define MLTK_MLDOUBLE MLTK_LITTLEENDIAN_IEEE754_DOUBLE +# define MLTK_MLLONGDOUBLE MLTK_INTEL_80BIT_EXTENDED + +#else + +# if WIN32_MATHLINK +# define MATHLINK_NUMERICS_ENVIRONMENT_ID "Sep 13 1996, 13:46:34" +# endif + +# define MLTK_CSHORT MLTK_CSHORT_P +# define MLTK_CINT MLTK_CINT_P +# define MLTK_CLONG MLTK_CLONG_P +# define MLTK_CFLOAT MLTK_CFLOAT_P +# define MLTK_CDOUBLE MLTK_CDOUBLE_P +# define MLTK_CLONGDOUBLE MLTK_CLONGDOUBLE_P + +# define MLTK_MLSHORT MLTK_CSHORT_P +# define MLTK_MLINT MLTK_CINT_P +# define MLTK_MLLONG MLTK_CLONG_P +# define MLTK_MLFLOAT MLTK_CFLOAT_P +# define MLTK_MLDOUBLE MLTK_CDOUBLE_P +# define MLTK_MLLONGDOUBLE MLTK_CLONGDOUBLE_P + +#endif + +/* Objects of these numeric types exist in MathLink only in the numerics + * environment and, unfortunately, in the "stack frames" of the functions that + * put atomic numbers like MLPutInteger. These C types are used by client + * programs solely for type-checked access to the BinaryNumber functions. + */ +typedef unsigned char uchar_nt; +typedef uchar_nt FAR * ucharp_nt; +typedef ucharp_nt FAR * ucharpp_nt; + +typedef short short_nt; +typedef short_nt FAR * shortp_nt; +typedef shortp_nt FAR * shortpp_nt; + +typedef int int_nt; +typedef int_nt FAR * intp_nt; +typedef intp_nt FAR * intpp_nt; + +typedef long long_nt; +typedef long_nt FAR * longp_nt; +typedef longp_nt FAR * longpp_nt; + +typedef float float_nt; +typedef float_nt FAR * floatp_nt; +typedef floatp_nt FAR * floatpp_nt; + +typedef double double_nt; +typedef double_nt FAR * doublep_nt; +typedef doublep_nt FAR * doublepp_nt; + +#ifndef CC_SUPPORTS_LONG_DOUBLE +# if defined( __STDC__) || defined(__cplusplus) || ! UNIX_MATHLINK +# define CC_SUPPORTS_LONG_DOUBLE 1 +# else +# define CC_SUPPORTS_LONG_DOUBLE MLPROTOTYPES +# endif +#endif + +struct _i87extended_nt { unsigned short w[5];}; + +#if CC_SUPPORTS_LONG_DOUBLE +# ifndef __extended_nt__ +# if WINDOWS_MATHLINK && (MLTK_CLONGDOUBLE != MLTK_MLLONGDOUBLE) /* subtle predicate that works for old and new windows numenvs */ +# define __extended_nt__ struct _i87extended_nt +# else +# define __extended_nt__ long double +# endif +# endif + typedef __extended_nt__ extended_nt; + typedef extended_nt FAR * extendedp_nt; + typedef extendedp_nt FAR * extendedpp_nt; +#endif + +#endif /* _MLNTYPES_H */ + +#ifndef _ML0TYPES_H +#define _ML0TYPES_H + + +#if USING_OLD_TYPE_NAMES +typedef charp_ct ml_charp; +typedef charpp_ct ml_charpp; +typedef charppp_ct ml_charppp; +typedef ucharp_ct ml_ucharp; +typedef longp_ct ml_longp; +typedef longpp_ct ml_longpp; +typedef ulongp_ct ml_ulongp; +typedef shortp_nt ml_shortp; +typedef shortpp_nt ml_shortpp; +typedef intp_nt ml_intp; +typedef intpp_nt ml_intpp; +typedef floatp_nt ml_floatp; +typedef floatpp_nt ml_floatpp; +typedef doublep_nt ml_doublep; +typedef doublepp_nt ml_doublepp; +#if CC_SUPPORTS_LONG_DOUBLE +typedef extended_nt ml_extended; +typedef extendedp_nt ml_extendedp; +typedef extendedpp_nt ml_extendedpp; +#endif +typedef charp_ct MLBuffer; +typedef kcharp_ct MLKBuffer; +typedef charpp_ct MLBufferArray; + +#endif + +#endif /* _ML0TYPES_H */ + +ML_EXTERN_C + +#ifndef _MLSTDDEV_H +#define _MLSTDDEV_H + + +#if WINDOWS_MATHLINK +#endif + +#if OS2_MATHLINK +# include +#endif + + + + + + +typedef void FAR * dev_world; +typedef MLINK dev_cookie; + +typedef dev_world FAR * dev_worldp; +typedef dev_cookie FAR * dev_cookiep; + +typedef MLAllocatorUPP dev_allocator; +#define call_dev_allocator CallMLAllocatorProc +#define new_dev_allocator NewMLAllocatorProc + +typedef MLDeallocatorUPP dev_deallocator; +#define call_dev_deallocator CallMLDeallocatorProc +#define new_dev_deallocator NewMLDeallocatorProc + + +typedef dev_main_type world_main_type; + +#define MLSTDWORLD_INIT 16 +#define MLSTDWORLD_DEINIT 17 +#define MLSTDWORLD_MAKE 18 +#define MLSTDDEV_CONNECT_READY 19 +#define MLSTDDEV_CONNECT 20 +#define MLSTDDEV_DESTROY 21 + +#define MLSTDDEV_SET_YIELDER 22 +#define MLSTDDEV_GET_YIELDER 23 + +#define MLSTDDEV_WRITE_MSG 24 +#define MLSTDDEV_HAS_MSG 25 +#define MLSTDDEV_READ_MSG 26 +#define MLSTDDEV_SET_HANDLER 27 +#define MLSTDDEV_GET_HANDLER 28 + + + +#define T_WORLD_INIT MLSTDWORLD_INIT +#define T_WORLD_DEINIT MLSTDWORLD_DEINIT +#define T_WORLD_MAKE MLSTDWORLD_MAKE +#define T_DEV_CONNECT_READY MLSTDDEV_CONNECT_READY +#define T_DEV_CONNECT MLSTDDEV_CONNECT +#define T_DEV_DESTROY MLSTDDEV_DESTROY + +#define T_DEV_SET_YIELDER MLSTDDEV_SET_YIELDER +#define T_DEV_GET_YIELDER MLSTDDEV_GET_YIELDER + +#define T_DEV_WRITE_MSG MLSTDDEV_WRITE_MSG +#define T_DEV_HAS_MSG MLSTDDEV_HAS_MSG +#define T_DEV_READ_MSG MLSTDDEV_READ_MSG +#define T_DEV_SET_HANDLER MLSTDDEV_SET_HANDLER +#define T_DEV_GET_HANDLER MLSTDDEV_GET_HANDLER + + + + +typedef unsigned long dev_mode; +/* edit here and in mathlink.r */ +#define NOMODE ((dev_mode)0x0000) +#define LOOPBACKBIT ((dev_mode)0x0001) +#define LISTENBIT ((dev_mode)0x0002) +#define CONNECTBIT ((dev_mode)0x0004) +#define LAUNCHBIT ((dev_mode)0x0008) +#define PARENTCONNECTBIT ((dev_mode)0x0010) +#define READBIT ((dev_mode)0x0020) +#define WRITEBIT ((dev_mode)0x0040) +#define SERVERBIT ((dev_mode)0x0080) +#define ANYMODE (~(dev_mode)0) + +typedef dev_mode FAR * dev_modep; + + + + + +typedef unsigned long dev_options; + +#define _DefaultOptions ((dev_options)0x00000000) + +#define _NetworkVisibleMask ((dev_options)0x00000003) +#define _BrowseMask ((dev_options)0x00000010) +#define _NonBlockingMask ((dev_options)0x00000020) +#define _InteractMask ((dev_options)0x00000100) +#define _YieldMask ((dev_options)0x00000200) +#define _VersionMask ((dev_options)0x0F000000) + +#define _NetworkVisible ((dev_options)0x00000000) +#define _LocallyVisible ((dev_options)0x00000001) +#define _InternetVisible ((dev_options)0x00000002) + +#define _Browse ((dev_options)0x00000000) +#define _DontBrowse ((dev_options)0x00000010) + +#define _NonBlocking ((dev_options)0x00000000) +#define _Blocking ((dev_options)0x00000020) + +#define _Interact ((dev_options)0x00000000) +#define _DontInteract ((dev_options)0x00000100) + +#define _ForceYield ((dev_options)0x00000200) + + + + +/* values returned by selector DEVICE_TYPE */ +#define UNREGISTERED_TYPE 0 +#define UNIXPIPE_TYPE 1 +#define UNIXSOCKET_TYPE 2 +#define PPC_TYPE 3 +#define MACTCP_TYPE 4 +#define LOOPBACK_TYPE 5 +#define COMMTB_TYPE 6 +#define ADSP_TYPE 7 +#define LOCAL_TYPE 8 +#define WINLOCAL_TYPE 9 +#define WINFMAP_TYPE 10 +#define WINSHM_TYPE 11 + +/* selectors */ +#define DEVICE_TYPE 0 /* long */ +#define DEVICE_NAME 1 /* char */ +#define DEVICE_WORLD_ID 5 /* char */ +#define PIPE_FD (UNIXPIPE_TYPE * 256 + 0) /* int */ +#define PIPE_CHILD_PID (UNIXPIPE_TYPE * 256 + 1) /* int */ +#define SOCKET_FD (UNIXSOCKET_TYPE * 256 + 0) /* int */ +#define SOCKET_PARTNER_ADDR (UNIXSOCKET_TYPE * 256 + 1) /* unsigned long */ +#define SOCKET_PARTNER_PORT (UNIXSOCKET_TYPE * 256 + 2) /* unsigned short */ +#define PPC_SESS_REF_NUM (PPC_TYPE * 256 + 0) /* PPCSessRefNum */ +#define PPC_PARTNER_PSN (PPC_TYPE * 256 + 1) /* ProcessSerialNumber */ +#define PPC_PARTNER_LOCATION (PPC_TYPE * 256 + 2) /* LocationNameRec */ +#define PPC_PARTNER_PORT (PPC_TYPE * 256 + 3) /* PPCPortRec */ +#define MACTCP_STREAM (MACTCP_TYPE * 256 + 0) /* StreamPtr */ +#define MACTCP_PARTNER_ADDR (MACTCP_TYPE * 256 + 1) /* ip_addr */ +#define MACTCP_PARTNER_PORT (MACTCP_TYPE * 256 + 2) /* tcp_port */ +#define MACTCP_IPDRIVER (MACTCP_TYPE * 256 + 3) /* short */ +#define MACTCP_SETSIMPLESOCKET (MACTCP_TYPE * 256 + 9) /* buf, buflen ignored */ +#define COMMTB_CONNHANDLE (COMMTB_TYPE * 256 + 0) /* ConnHandle */ +#define ADSP_CCBREFNUM (ADSP_TYPE * 256 + 0) /* short */ +#define ADSP_IOCREFNUM (ADSP_TYPE * 256 + 3) /* short */ + +#define WINDOWS_SET_NOTIFY_WINDOW 2330 /* HWND */ +#define WINDOWS_REMOVE_NOTIFY_WINDOW 2331 /* HWND */ + +/* info selectors */ +#define WORLD_THISLOCATION 1 /* char */ +#define WORLD_MODES 2 /* dev_mode */ +#define WORLD_PROTONAME 3 /* char */ +#define WORLD_STREAMCAPACITY 4 /* long */ /*this belongs in mlolddev.h*/ +#define WORLD_ID DEVICE_WORLD_ID /* char */ + + + +#ifndef MATHLINK_DEVICE_WORLD_ID +#define MATHLINK_DEVICE_WORLD_ID (__DATE__ ", " __TIME__) +#endif + + + + +#define YIELDVERSION 1 + +typedef long devyield_result; +typedef long devyield_place; +typedef long devyield_count; +typedef unsigned long devyield_sleep; + +#define INTERNAL_YIELDING 0 +#define MAKE_YIELDING 1 +#define CONNECT_YIELDING 2 +#define READ_YIELDING 3 +#define WRITE_YIELDING 4 +#define DESTROY_YIELDING 5 +#define READY_YIELDING 6 + + +typedef struct MLYieldParams FAR * MLYieldParameters; + + +#define MAX_SLEEP (600) +typedef struct MLYieldData{ + union {long l; double d; void FAR * p;} private_data[8]; +} FAR * MLYieldDataPointer; + +void MLNewYieldData P(( MLYieldDataPointer ydp /* , dev_allocator, dev_deallocator */)); +void MLFreeYieldData P(( MLYieldDataPointer ydp)); +MLYieldParameters MLResetYieldData P(( MLYieldDataPointer ydp, devyield_place func_id)); +mlapi_result MLSetYieldParameter P(( MLYieldParameters yp, unsigned long selector, void* data, unsigned long* len)); +mlapi_result MLYieldParameter P(( MLYieldParameters yp, unsigned long selector, void* data, unsigned long* len)); +devyield_sleep MLSetSleepYP P(( MLYieldParameters yp, devyield_sleep sleep)); +devyield_count MLSetCountYP P(( MLYieldParameters yp, devyield_count count)); + + +enum { MLSleepParameter = 1, MLCountParameter, MLPlaceParameter}; + + + + + +MLYPROC( devyield_result, MLYielderProcPtr, (MLINK mlp, MLYieldParameters yp)); +typedef MLYielderProcPtr MLDeviceYielderProcPtr; + +#if MACINTOSH_MATHLINK +enum { + uppMLYielderProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(devyield_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLINK))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(MLYieldParameters))), + uppMLDeviceYielderProcInfo = uppMLYielderProcInfo +}; +#endif /* MACINTOSH_MATHLINK */ + + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLYielderUPP, MLDeviceYielderUPP; +# define NewMLYielderProc(userRoutine) \ + NewRoutineDescriptor(MLYielderCast((userRoutine)), uppMLYielderProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLYielderProcPtr MLYielderUPP, MLDeviceYielderUPP; +# define NewMLYielderProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#elif WIN16_MATHLINK + typedef __MLProcPtr__ MLYielderUPP, MLDeviceYielderUPP; +# define NewMLYielderProc( userRoutine) \ + (MakeProcInstance( MLYielderCast(userRoutine), MLInstance)) +#else + typedef MLYielderProcPtr MLYielderUPP, MLDeviceYielderUPP; +# define NewMLYielderProc(userRoutine) (userRoutine) +#endif + +#define NewMLDeviceYielderProc NewMLYielderProc + +typedef MLYielderUPP MLYieldFunctionType; +typedef unsigned long MLYieldFunctionObject; /* bugcheck should I change this back to void* for 64 bit machines */ + +typedef MLYieldFunctionObject dev_yielder; +typedef dev_yielder FAR* dev_yielderp; + + + + + + + + +typedef unsigned long dev_message; +typedef dev_message FAR * dev_messagep; + + +MLMPROC( void, MLHandlerProcPtr, (MLINK mlp, dev_message m, dev_message n)); +typedef MLHandlerProcPtr MLDeviceHandlerProcPtr; + + +#if MACINTOSH_MATHLINK +enum { + uppMLHandlerProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLINK))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(dev_message))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(dev_message))), + uppMLDeviceHandlerProcInfo = uppMLHandlerProcInfo +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLHandlerUPP, MLDeviceHandlerUPP; +# define NewMLHandlerProc(userRoutine) \ + NewRoutineDescriptor(MLHandlerCast((userRoutine)), uppMLHandlerProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLHandlerProcPtr MLHandlerUPP, MLDeviceHandlerUPP; +# define NewMLHandlerProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#elif WIN16_MATHLINK + typedef __MLProcPtr__ MLHandlerUPP, MLDeviceHandlerUPP; +# define NewMLHandlerProc( userRoutine) \ + (MakeProcInstance( MLHandlerCast(userRoutine), MLInstance)) +#else + typedef MLHandlerProcPtr MLHandlerUPP, MLDeviceHandlerUPP; +# define NewMLHandlerProc(userRoutine) (userRoutine) +#endif + +#define NewMLDeviceHandlerProc NewMLHandlerProc + +typedef MLHandlerUPP MLMessageHandlerType; +typedef unsigned long MLMessageHandlerObject; + +typedef MLMessageHandlerObject dev_msghandler; +typedef dev_msghandler FAR* dev_msghandlerp; + + + +#endif /* _MLSTDDEV_H */ + + + +/* explicitly not protected by _MLSTDDEV_H in case MLDECL is redefined for multiple inclusion */ + +/*bugcheck //should the rest of YP stuff be exported? */ +MLDECL( devyield_sleep, MLSleepYP, ( MLYieldParameters yp)); +MLDECL( devyield_count, MLCountYP, ( MLYieldParameters yp)); +MLDECL( MLYieldFunctionObject, MLCreateYieldFunction, ( MLEnvironment ep, MLYieldFunctionType yf, MLPointer reserved)); /* reserved must be 0 */ +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( MLYieldFunctionObject, MLCreateYieldFunction0, ( MLEnvironment ep, MLYieldFunctionType yf, MLPointer reserved)); /* reserved must be 0 */ +#endif +MLDECL( MLYieldFunctionType, MLDestroyYieldFunction, ( MLYieldFunctionObject yfo)); +MLDECL( devyield_result, MLCallYieldFunction, ( MLYieldFunctionObject yfo, MLINK mlp, MLYieldParameters p)); +MLDECL( MLMessageHandlerObject, MLCreateMessageHandler, ( MLEnvironment ep, MLMessageHandlerType mh, MLPointer reserved)); /* reserved must be 0 */ +#if MLINTERFACE > 1 +MLDECL( MLMessageHandlerObject, MLCreateMessageHandler0, ( MLEnvironment ep, MLMessageHandlerType mh, MLPointer reserved)); /* reserved must be 0 */ +#endif +MLDECL( MLMessageHandlerType, MLDestroyMessageHandler, ( MLMessageHandlerObject mho)); +MLDECL( void, MLCallMessageHandler, ( MLMessageHandlerObject mho, MLINK mlp, dev_message m, dev_message n)); + + +/* just some type-safe casts */ +MLDECL( __MLProcPtr__, MLYielderCast, ( MLYielderProcPtr yp)); +MLDECL( __MLProcPtr__, MLHandlerCast, ( MLHandlerProcPtr mh)); + +ML_END_EXTERN_C + + + +#ifndef _MLMAKE_H +#define _MLMAKE_H + +/* --binding layer-- */ +/*************** Starting MathLink ***************/ + +#define MLPARAMETERSIZE_R1 256 +#define MLPARAMETERSIZE 256 +typedef char FAR * MLParametersPointer; +typedef char MLParameters[MLPARAMETERSIZE]; + +#define MLLoopBackOpen MLLoopbackOpen + + + +ML_EXTERN_C +MLUPROC( void, MLUserProcPtr, (MLINK)); +ML_END_EXTERN_C + +#if MACINTOSH_MATHLINK +enum { + uppMLUserFunctionProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLINK))) +}; +#endif /* MACINTOSH_MATHLINK */ + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLUserUPP; +# define NewMLUserProc(userRoutine) \ + NewRoutineDescriptor(MLUserCast((userRoutine)), uppMLUserFunctionProcInfo, GetCurrentArchitecture()) +#else /* !GENERATINGCFM */ + typedef MLUserProcPtr MLUserUPP; +# define NewMLUserProc(userRoutine) (userRoutine) +#endif /* GENERATINGCFM */ +#else /* !MACINTOSH_MATHLINK */ + typedef MLUserProcPtr MLUserUPP; +# define NewMLUserProc(userRoutine) (userRoutine) +#endif /* MACINTOSH_MATHLINK */ + +typedef MLUserUPP MLUserFunctionType; +typedef MLUserFunctionType FAR * MLUserFunctionTypePointer; + + + + + +/* The following defines are + * currently for internal use only. + */ + + +/* edit here and in mldevice.h and mathlink.r */ +#define MLNetworkVisibleMask ((unsigned long)0x00000003) +#define MLBrowseMask ((unsigned long)0x00000010) +#define MLNonBlockingMask ((unsigned long)0x00000020) +#define MLInteractMask ((unsigned long)0x00000100) +#define MLYieldMask ((unsigned long)0x00000200) +#define MLVersionMask ((unsigned long)0x0000F000) + +#define MLDefaultOptions ((unsigned long)0x00000000) +#define MLNetworkVisible ((unsigned long)0x00000000) +#define MLLocallyVisible ((unsigned long)0x00000001) +#define MLInternetVisible ((unsigned long)0x00000002) + +#define MLBrowse ((unsigned long)0x00000000) +#define MLDontBrowse ((unsigned long)0x00000010) + +#define MLNonBlocking ((unsigned long)0x00000000) +#define MLBlocking ((unsigned long)0x00000020) + +#define MLInteract ((unsigned long)0x00000000) +#define MLDontInteract ((unsigned long)0x00000100) + +#define MLForceYield ((unsigned long)0x00000200) + +#endif /* _MLMAKE_H */ + + +/* explicitly not protected by _MLMAKE_H in case MLDECL is redefined for multiple inclusion */ + + +ML_EXTERN_C +MLDECL( ulong_ct, MLNewParameters, ( MLParametersPointer p, ulong_ct rev, ulong_ct apirev)); +MLDECL( void, MLSetAllocParameter, ( MLParametersPointer p, MLAllocator allocator, MLDeallocator deallocator)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( long, MLAllocParameter, (MLParametersPointer p, MLAllocatorp allocatorp, MLDeallocatorp deallocatorp)); +MLDECL( long, MLSetResourceParameter, (MLParametersPointer p, kcharp_ct path)); +MLDECL( long, MLSetDeviceParameter, (MLParametersPointer p, kcharp_ct devspec)); +#endif +MLDECL( long, MLErrorParameter, ( MLParametersPointer p)); + +MLDECL( MLEnvironment, MLInitialize, ( MLParametersPointer p)); /* pass in NULL */ +MLDECL( void, MLDeinitialize, ( MLEnvironment env)); + +/* or, if you use MLOpenArgv, ...*/ + +MLDECL( MLEnvironment, MLBegin, ( MLParametersPointer p)); /* pass in NULL */ +MLDECL( void, MLEnd, ( MLEnvironment env)); + +#if MLNTESTPOINTS < 1 +#undef MLNTESTPOINTS +#define MLNTESTPOINTS 1 +#endif +MLDECL( long_et, MLTestPoint1, ( MLEnvironment ep, ulong_ct selector, voidp_ct p1, voidp_ct p2, longp_ct np)); + +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 + +#if MLNTESTPOINTS < 2 +#undef MLNTESTPOINTS +#define MLNTESTPOINTS 2 +#endif +MLDECL( void, MLTestPoint2, ( MLINK mlp)); + +#if MLNTESTPOINTS < 3 +#undef MLNTESTPOINTS +#define MLNTESTPOINTS 3 +#endif +MLDECL( ulong_ct, MLTestPoint3, ( MLINK mlp)); + +#if MLNTESTPOINTS < 4 +#undef MLNTESTPOINTS +#define MLNTESTPOINTS 4 +#endif +MLDECL( ulong_ct, MLTestPoint4, ( MLINK mlp)); + +MLDECL( long_et, MLNumberControl0, ( MLEnvironment ep, ulong_ct selector, voidp_ct p1, voidp_ct p2, longp_ct np)); +#else +extern long_et MLNumberControl0( MLEnvironment ep, ulong_ct selector, voidp_ct p1, voidp_ct p2, longp_ct np); +#endif + + +/*************** Connection interface ***************/ +MLDECL( MLINK, MLCreate0, ( MLEnvironment ep, dev_type dev, dev_main_type dev_main, longp_ct errp)); +MLDECL( MLINK, MLMake, ( MLPointer ep, dev_type dev, dev_main_type dev_main, longp_ct errp)); +MLDECL( void, MLDestroy, ( MLINK mlp, dev_typep devp, dev_main_typep dev_mainp)); + +MLDECL( long, MLFeatureString, ( MLINK mlp, charp_ct buf, long buffsize)); +MLDECL( charpp_ct, MLFilterArgv0, ( MLEnvironment ep, charpp_ct argv, charpp_ct argv_end)); +MLDECL( MLINK, MLOpenArgv, ( MLEnvironment ep, charpp_ct argv, charpp_ct argv_end, longp_ct errp)); +MLDECL( MLINK, MLOpenString, ( MLEnvironment ep, kcharp_ct command_line, longp_ct errp)); +MLDECL( MLINK, MLLoopbackOpen, ( MLEnvironment ep, longp_ct errp)); +MLDECL( MLINK, MLLoopbackOpen0, ( MLEnvironment ep, kcharp_ct features, longp_ct errp)); +MLDECL( int_ct, MLStringToArgv, ( kcharp_ct commandline, charp_ct buf, charpp_ct argv, int_ct len)); +MLDECL( long, MLScanString, ( charpp_ct argv, charppp_ct argv_end, charpp_ct commandline, charpp_ct buf)); +MLDECL( long, MLPrintArgv, ( charp_ct buf, charpp_ct buf_endp, charppp_ct argvp, charpp_ct argv_end)); + +MLDECL( kcharp_ct, MLErrorMessage, ( MLINK mlp)); +MLDECL( kcharp_ct, MLErrorString, ( MLEnvironment env, long err)); + +MLDECL( MLINK, MLOpen, ( int_ct argc, charpp_ct argv)); +MLDECL( MLINK, MLOpenInEnv, ( MLEnvironment env, int_ct argc, charpp_ct argv, longp_ct errp)); +MLDECL( MLINK, MLOpenS, ( kcharp_ct command_line)); + +MLDECL( MLINK, MLDuplicateLink, ( MLINK parentmlp, kcharp_ct name, longp_ct errp )); +MLDECL( mlapi_result, MLConnect, ( MLINK mlp)); +#define MLActivate MLConnect + +#ifndef __feature_setp__ +#define __feature_setp__ +typedef struct feature_set* feature_setp; +#endif +MLDECL( mlapi_result, MLEstablish, ( MLINK mlp, feature_setp features)); + +MLDECL( mlapi_result, MLEstablishString, ( MLINK mlp, kcharp_ct features)); +MLDECL( void, MLClose, ( MLINK mlp)); + +MLDECL( void, MLSetUserData, ( MLINK mlp, MLPointer data, MLUserFunctionType f)); +MLDECL( MLPointer, MLUserData, ( MLINK mlp, MLUserFunctionTypePointer fp)); +MLDECL( void, MLSetUserBlock, ( MLINK mlp, MLPointer userblock)); +MLDECL( MLPointer, MLUserBlock, ( MLINK mlp)); + +/* just a type-safe cast */ +MLDECL( __MLProcPtr__, MLUserCast, ( MLUserProcPtr f)); + + + + + +/* MLName returns a pointer to the link's name. + * Links are generally named when they are created + * and are based on information that is potentially + * useful and is available at that time. + * Do not attempt to deallocate the name's storage + * through this pointer. The storage should be + * considered in read-only memory. + */ +MLDECL( kcharp_ct, MLName, ( MLINK mlp)); +MLDECL( long, MLNumber, ( MLINK mlp)); +#if MLINTERFACE > 1 +MLDECL( long, MLToLinkID, ( MLINK mlp)); +MLDECL( MLINK, MLFromLinkID, ( MLEnvironment ep, long n)); +#else +extern MLINK MLFromLinkID( MLEnvironment ep, long n); +#endif +MLDECL( charp_ct, MLSetName, ( MLINK mlp, kcharp_ct name)); + + + +/* The following functions are + * currently for internal use only. + */ + +MLDECL( MLPointer, MLInit, ( MLallocator alloc, MLdeallocator dealloc, MLPointer enclosing_environment)); +MLDECL( void, MLDeinit, ( MLPointer env)); +MLDECL( MLPointer, MLEnclosingEnvironment, ( MLPointer ep)); +MLDECL( MLPointer, MLinkEnvironment, ( MLINK mlp)); + +/* the following two functions are for internal use only */ +MLDECL( MLYieldFunctionObject, MLDefaultYieldFunction, ( MLEnvironment env)); +MLDECL( mlapi_result, MLSetDefaultYieldFunction, ( MLEnvironment env, MLYieldFunctionObject yf)); + +ML_END_EXTERN_C + + +#ifndef _MLERRORS_H +#define _MLERRORS_H + + +/*************** MathLink errors ***************/ +/* + * When some problem is detected within MathLink, routines + * will return a simple indication of failure and store + * an error code internally. (For routines that have nothing + * else useful to return, success is indicated by returning + * non-zero and failure by returning 0.) MLerror() returns + * the current error code; MLErrorMessage returns an English + * language description of the error. + * The error MLEDEAD is irrecoverable. For the others, MLClearError() + * will reset the error code to MLEOK. + */ + + + +#ifndef _MLERRNO_H +#define _MLERRNO_H + +/* edit here and in mlerrstr.h */ + +#define MLEUNKNOWN -1 +#define MLEOK 0 +#define MLEDEAD 1 +#define MLEGBAD 2 +#define MLEGSEQ 3 +#define MLEPBTK 4 +#define MLEPSEQ 5 +#define MLEPBIG 6 +#define MLEOVFL 7 +#define MLEMEM 8 +#define MLEACCEPT 9 +#define MLECONNECT 10 +#define MLECLOSED 11 +#define MLEDEPTH 12 /* internal error */ +#define MLENODUPFCN 13 /* stream cannot be duplicated */ + +#define MLENOACK 15 /* */ +#define MLENODATA 16 /* */ +#define MLENOTDELIVERED 17 /* */ +#define MLENOMSG 18 /* */ +#define MLEFAILED 19 /* */ + +#define MLEGETENDEXPR 20 +#define MLEPUTENDPACKET 21 /* unexpected call of MLEndPacket */ + /* currently atoms aren't + * counted on the way out so this error is raised only when + * MLEndPacket is called in the midst of an atom + */ +#define MLENEXTPACKET 22 +#define MLEUNKNOWNPACKET 23 +#define MLEGETENDPACKET 24 +#define MLEABORT 25 +#define MLEMORE 26 /* internal error */ +#define MLENEWLIB 27 +#define MLEOLDLIB 28 +#define MLEBADPARAM 29 +#define MLENOTIMPLEMENTED 30 + + +#define MLEINIT 32 +#define MLEARGV 33 +#define MLEPROTOCOL 34 +#define MLEMODE 35 +#define MLELAUNCH 36 +#define MLELAUNCHAGAIN 37 +#define MLELAUNCHSPACE 38 +#define MLENOPARENT 39 +#define MLENAMETAKEN 40 +#define MLENOLISTEN 41 +#define MLEBADNAME 42 +#define MLEBADHOST 43 +#define MLERESOURCE 44 /* a required resource was missing */ +#define MLELAUNCHFAILED 45 +#define MLELAUNCHNAME 46 +#define MLELAST MLELAUNCHNAME /* for internal use only */ + +#define MLETRACEON 996 /* */ +#define MLETRACEOFF 997 /* */ +#define MLEDEBUG 998 /* */ +#define MLEASSERT 999 /* an internal assertion failed */ +#define MLEUSER 1000 /* start of user defined errors */ + + +#endif /* _MLERRNO_H */ + + +#endif /* _MLERRORS_H */ + +/* explicitly not protected by _MLERRORS_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_error, MLError, ( MLINK mlp)); +MLDECL( mlapi_result, MLClearError, ( MLINK mlp)); +MLDECL( mlapi_result, MLSetError, ( MLINK mlp, mlapi_error err)); +ML_END_EXTERN_C + + +#ifndef _MLYLDMSG_H +#define _MLYLDMSG_H + + + +enum { MLTerminateMessage = 1, MLInterruptMessage, MLAbortMessage, + MLEndPacketMessage, MLSynchronizeMessage, MLImDyingMessage, + MLWaitingAcknowledgment, MLMarkTopLevelMessage, + MLFirstUserMessage = 128, MLLastUserMessage = 255 }; + +typedef unsigned long devinfo_selector; + + +#endif /* _MLYLDMSG_H */ + +/* explicitly not protected by _MLYLDMSG_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLPutMessage, ( MLINK mlp, dev_message msg)); +MLDECL( mlapi_result, MLMessageReady, ( MLINK mlp)); +MLDECL( mlapi_result, MLGetMessage, ( MLINK mlp, dev_messagep mp, dev_messagep np)); + +MLDECL( MLMessageHandlerObject, MLMessageHandler, ( MLINK mlp)); +MLDECL( mlapi_result, MLSetMessageHandler, ( MLINK mlp, MLMessageHandlerObject h)); +MLDECL( MLYieldFunctionObject, MLYieldFunction, ( MLINK mlp)); +MLDECL( mlapi_result, MLSetYieldFunction, ( MLINK mlp, MLYieldFunctionObject yf)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLSetYieldFunction0, ( MLINK mlp, MLYieldFunctionObject yf, MLINK cookie)); +MLDECL( mlapi_result, MLSetMessageHandler0, ( MLINK mlp, MLMessageHandlerObject func, MLINK cookie)); +#endif + + +MLDECL( mlapi_result, MLDeviceInformation, ( MLINK mlp, devinfo_selector selector, MLPointer buf, longp_st buflen)); +ML_END_EXTERN_C + +/*************** Textual interface ***************/ + + +#ifndef _MLGET_H +#define _MLGET_H + + +#endif /* _MLGET_H */ + +/* explicitly not protected by _MLGET_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_token, MLGetNext, ( MLINK mlp)); +MLDECL( mlapi_token, MLGetNextRaw, ( MLINK mlp)); +MLDECL( mlapi_token, MLGetType, ( MLINK mlp)); +MLDECL( mlapi_token, MLGetRawType, ( MLINK mlp)); +MLDECL( mlapi_result, MLGetRawData, ( MLINK mlp, ucharp_ct data, long_st size, longp_st gotp)); +MLDECL( mlapi_result, MLGetData, ( MLINK mlp, charp_ct data, long_st size, longp_st gotp)); +MLDECL( mlapi_result, MLGetArgCount, ( MLINK mlp, longp_st countp)); +MLDECL( mlapi_result, MLGetRawArgCount, ( MLINK mlp, longp_st countp)); +MLDECL( mlapi_result, MLBytesToGet, ( MLINK mlp, longp_st leftp)); +MLDECL( mlapi_result, MLRawBytesToGet, ( MLINK mlp, longp_st leftp)); +MLDECL( mlapi_result, MLExpressionsToGet, ( MLINK mlp, longp_st countp)); +MLDECL( mlapi_result, MLNewPacket, ( MLINK mlp)); +MLDECL( mlapi_result, MLTakeLast, ( MLINK mlp, long_st eleft)); +MLDECL( mlapi_result, MLReady, ( MLINK mlp)); +MLDECL( mlapi_result, MLFill, ( MLINK mlp)); +ML_END_EXTERN_C + + +#ifndef _MLPUT_H +#define _MLPUT_H + + +#define MLPutExpression is obsolete, use MLPutComposite + +#endif /* _MLPUT_H */ + +/* explicitly not protected by _MLPUT_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLPutNext, ( MLINK mlp, mlapi_token tok)); +MLDECL( mlapi_result, MLPutType, ( MLINK mlp, mlapi__token tok)); +MLDECL( mlapi_result, MLPutRawSize, ( MLINK mlp, long_st size)); +MLDECL( mlapi_result, MLPutRawData, ( MLINK mlp, kucharp_ct data, long_st len)); +MLDECL( mlapi_result, MLPutArgCount, ( MLINK mlp, long_st argc)); +MLDECL( mlapi_result, MLPutComposite, ( MLINK mlp, long_st argc)); +MLDECL( mlapi_result, MLBytesToPut, ( MLINK mlp, longp_st leftp)); +MLDECL( mlapi_result, MLEndPacket, ( MLINK mlp)); +MLDECL( mlapi_result, MLFlush, ( MLINK mlp)); +ML_END_EXTERN_C + + +#ifndef _MLTK_H +#define _MLTK_H + + +#define MLTKOLDINT 'I' /* 73 Ox49 01001001 */ /* integer leaf node */ +#define MLTKOLDREAL 'R' /* 82 Ox52 01010010 */ /* real leaf node */ + + +#define MLTKFUNC 'F' /* 70 Ox46 01000110 */ /* non-leaf node */ + +#define MLTKERROR (0) /* bad token */ +#define MLTKERR (0) /* bad token */ + +/* text token bit patterns: 0010x01x --exactly 2 bits worth chosen to make things somewhat readable */ +#define MLTK__IS_TEXT( tok) ( (tok & 0x00F6) == 0x0022) + +#define MLTKSTR '"' /* 00100010 */ +#define MLTKSYM '\043' /* 00100011 */ /* octal here as hash requires a trigraph */ + +#define MLTKREAL '*' /* 00101010 */ +#define MLTKINT '+' /* 00101011 */ + + + +/* The following defines are for internal use only */ +#define MLTKPCTEND ']' /* at end of top level expression */ +#define MLTKAPCTEND '\n' /* at end of top level expression */ +#define MLTKEND '\n' +#define MLTKAEND '\r' +#define MLTKSEND ',' + +#define MLTKCONT '\\' +#define MLTKELEN ' ' + +#define MLTKNULL '.' +#define MLTKOLDSYM 'Y' /* 89 0x59 01011001 */ +#define MLTKOLDSTR 'S' /* 83 0x53 01010011 */ + + +typedef unsigned long decoder_mask; +#define MLTKPACKED 'P' /* 80 0x50 01010000 */ +#define MLTKARRAY 'A' /* 65 0x41 01000001 */ +#define MLTKDIM 'D' /* 68 0x44 01000100 */ + +#define MLLENGTH_DECODER ((decoder_mask) 1<<16) +#define MLTKPACKED_DECODER ((decoder_mask) 1<<17) +#define MLTKARRAY_DECODER ((decoder_mask) 1<<18) +#define MLTKMODERNCHARS_DECODER ((decoder_mask) 1<<19) +#if 0 +#define MLTKNULLSEQUENCE_DECODER ((decoder_mask) 1<<20) +#else +#define MLTKNULLSEQUENCE_DECODER ((decoder_mask) 0) +#endif +#define MLTKALL_DECODERS (MLLENGTH_DECODER | MLTKPACKED_DECODER | MLTKARRAY_DECODER | MLTKMODERNCHARS_DECODER | MLTKNULLSEQUENCE_DECODER) + +#define MLTK_FIRSTUSER '\x30' /* user token */ +#define MLTK_LASTUSER '\x3F' + + + +#endif /* _MLTK_H */ + +/*************** Native C types interface ***************/ + + +#ifndef _MLCGET_H +#define _MLCGET_H + + + +#define MLGetReal MLGetDouble + +#endif /* _MLCGET_H */ + + +/* explicitly not protected by _MLCGET_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLGetBinaryNumber, ( MLINK mlp, voidp_ct np, long type)); +MLDECL( mlapi_result, MLGetShortInteger, ( MLINK mlp, shortp_nt hp)); +MLDECL( mlapi_result, MLGetInteger, ( MLINK mlp, intp_nt ip)); +MLDECL( mlapi_result, MLGetLongInteger, ( MLINK mlp, longp_nt lp)); +MLDECL( mlapi_result, MLGetFloat, ( MLINK mlp, floatp_nt fp)); +MLDECL( mlapi_result, MLGetDouble, ( MLINK mlp, doublep_nt dp)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLGetLongDouble, ( MLINK mlp, extendedp_nt xp)); +#endif + +MLDECL( mlapi_result, MLGet16BitCharacters, ( MLINK mlp, longp_st chars_left, ushortp_ct buf, long_st cardof_buf, longp_st got)); +MLDECL( mlapi_result, MLGet8BitCharacters, ( MLINK mlp, longp_st chars_left, ucharp_ct buf, long_st cardof_buf, longp_st got, long missing)); +MLDECL( mlapi_result, MLGet7BitCharacters, ( MLINK mlp, longp_st chars_left, charp_ct buf, long_st cardof_buf, longp_st got)); + +MLDECL( mlapi_result, MLGetUnicodeString, ( MLINK mlp, kushortpp_ct sp, longp_st lenp)); +MLDECL( mlapi_result, MLGetByteString, ( MLINK mlp, kucharpp_ct sp, longp_st lenp, long missing)); +MLDECL( mlapi_result, MLGetString, ( MLINK mlp, kcharpp_ct sp)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLGetUnicodeString0, ( MLINK mlp, kushortpp_ct sp, longp_st lenp)); +MLDECL( mlapi_result, MLGetByteString0, ( MLINK mlp, kucharpp_ct sp, longp_st lenp, long missing)); +MLDECL( mlapi_result, MLGetString0, ( MLINK mlp, kcharpp_ct sp)); +#endif + +MLDECL( mlapi_result, MLGetUnicodeSymbol, ( MLINK mlp, kushortpp_ct sp, longp_st lenp)); +MLDECL( mlapi_result, MLGetByteSymbol, ( MLINK mlp, kucharpp_ct sp, longp_st lenp, long missing)); +MLDECL( mlapi_result, MLGetSymbol, ( MLINK mlp, kcharpp_ct sp)); + +MLDECL( void, MLDisownUnicodeString, ( MLINK mlp, kushortp_ct s, long_st len)); +MLDECL( void, MLDisownByteString, ( MLINK mlp, kucharp_ct s, long_st len)); +MLDECL( void, MLDisownString, ( MLINK mlp, kcharp_ct s)); + +MLDECL( void, MLDisownUnicodeSymbol, ( MLINK mlp, kushortp_ct s, long_st len)); +MLDECL( void, MLDisownByteSymbol, ( MLINK mlp, kucharp_ct s, long_st len)); +MLDECL( void, MLDisownSymbol, ( MLINK mlp, kcharp_ct s)); + + + +MLDECL( mlapi_result, MLCheckString, ( MLINK mlp, kcharp_ct name)); +MLDECL( mlapi_result, MLCheckSymbol, ( MLINK mlp, kcharp_ct name)); +MLDECL( mlapi_result, MLGetFunction, ( MLINK mlp, kcharpp_ct sp, longp_st countp)); +MLDECL( mlapi_result, MLCheckFunction, ( MLINK mlp, kcharp_ct s, longp_st countp)); +MLDECL( mlapi_result, MLCheckFunctionWithArgCount, ( MLINK mlp, kcharp_ct s, longp_st countp)); +ML_END_EXTERN_C + + +#ifndef _MLCPUT_H +#define _MLCPUT_H + + +#define MLPutReal MLPutDouble + +#endif /* _MLCPUT_H */ + +/* explicitly not protected by _MLCPUT_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLPutBinaryNumber, ( MLINK mlp, voidp_ct np, long type)); +MLDECL( mlapi_result, MLPutShortInteger, ( MLINK mlp, int_nt h)); +MLDECL( mlapi_result, MLPutInteger, ( MLINK mlp, int_nt i)); +MLDECL( mlapi_result, MLPutLongInteger, ( MLINK mlp, long_nt l)); +MLDECL( mlapi_result, MLPutFloat, ( MLINK mlp, double_nt f)); +MLDECL( mlapi_result, MLPutDouble, ( MLINK mlp, double_nt d)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLPutLongDouble, ( MLINK mlp, extended_nt x)); +#endif + +MLDECL( mlapi_result, MLPut16BitCharacters, ( MLINK mlp, long_st chars_left, kushortp_ct codes, long_st ncodes)); +MLDECL( mlapi_result, MLPut8BitCharacters, ( MLINK mlp, long_st chars_left, kucharp_ct bytes, long_st nbytes)); +MLDECL( mlapi_result, MLPut7BitCount, ( MLINK mlp, long_st count, long_st size)); +MLDECL( mlapi_result, MLPut7BitCharacters, ( MLINK mlp, long_st chars_left, kcharp_ct bytes, long_st nbytes, long_st nchars_now)); + +MLDECL( mlapi_result, MLPutUnicodeString, ( MLINK mlp, kushortp_ct s, long_st len)); +MLDECL( mlapi_result, MLPutByteString, ( MLINK mlp, kucharp_ct s, long_st len)); +MLDECL( mlapi_result, MLPutString, ( MLINK mlp, kcharp_ct s)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLPutRealUnicodeString0, ( MLINK mlp, ushortp_ct s)); +MLDECL( mlapi_result, MLPutRealByteString0, ( MLINK mlp, ucharp_ct s)); +#endif + +MLDECL( mlapi_result, MLPutUnicodeSymbol, ( MLINK mlp, kushortp_ct s, long_st len)); +MLDECL( mlapi_result, MLPutByteSymbol, ( MLINK mlp, kucharp_ct s, long_st len)); +MLDECL( mlapi_result, MLPutSymbol, ( MLINK mlp, kcharp_ct s)); + +MLDECL( mlapi_result, MLPutFunction, ( MLINK mlp, kcharp_ct s, long_st argc)); + + +MLDECL( mlapi_result, MLPutSize, ( MLINK mlp, long_st size)); +MLDECL( mlapi_result, MLPutData, ( MLINK mlp, kcharp_ct buff, long_st len)); +ML_END_EXTERN_C + + + +#ifndef _MLSTRING_H +#define _MLSTRING_H + + + +#define MAX_BYTES_PER_OLD_CHARACTER 3 +#define MAX_BYTES_PER_NEW_CHARACTER 6 + +#define ML_MAX_BYTES_PER_CHARACTER MAX_BYTES_PER_NEW_CHARACTER + +/* for source code compatibility with earlier versions of MathLink */ + +#if POWERMACINTOSH_MATHLINK +#pragma options align=mac68k +#endif + +typedef struct { + kcharp_ct str; + kcharp_ct end; +} MLStringPosition; + +#if POWERMACINTOSH_MATHLINK +#pragma options align=reset +#endif + +typedef MLStringPosition FAR * MLStringPositionPointer; + +#define MLStringFirstPos(s,pos) MLStringFirstPosFun( s, &(pos)) + +#define MLforString( s, pos) \ + for( MLStringFirstPos(s,pos); MLStringCharacter( (pos).str, (pos).end) >= 0; MLNextCharacter(&(pos).str, (pos).end)) + +#define MLStringChar( pos) MLStringCharacter( (pos).str, (pos).end) + +#define MLPutCharToString MLConvertCharacter + + +/* for internal use only */ + +#if POWERMACINTOSH_MATHLINK +#pragma options align=mac68k +#endif + +typedef struct { + ucharp_ct cc; + int_ct mode; + int_ct more; + ucharp_ct head; +} MLOldStringPosition; + +#if POWERMACINTOSH_MATHLINK +#pragma options align=reset +#endif + +typedef MLOldStringPosition FAR * MLOldStringPositionPointer; + + +#define MLOldforString( s, pos) \ + for ( MLOldStringFirstPos( s, pos); (pos).more; MLOldStringNextPos( pos)) + +#define MLOldStringChar(pos) \ + ( ((pos).mode <= 1) ? (uint_ct)(*(ucharp_ct)((pos).cc)) : MLOldStringCharFun( &pos) ) + + +#define MLOldStringFirstPos(s,pos) MLOldStringFirstPosFun( s, &(pos)) + +#define MLOldStringNextPos(pos) ( \ + ((pos).mode == 0) \ + ? ((*(*(pos).cc ? ++(pos).cc : (pos).cc) ? 0 : ((pos).more = 0)), (pos).cc) \ + : MLOldStringNextPosFun( &pos) ) + + + + + +#endif /* _MLSTRING_H */ + + + + +/* explicitly not protected by _MLXDATA_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +/* assumes *startp aligned on char boundary, if n == -1, returns ~(char_count) */ +MLDECL( long, MLCharacterOffset, ( kcharpp_ct startp, kcharp_ct end, long n)); +MLDECL( long, MLStringCharacter, ( kcharp_ct start, kcharp_ct end)); +MLDECL( long, MLNextCharacter, ( kcharpp_ct startp, kcharp_ct end)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( long, MLNextCharacter0, ( kcharp_ct str, longp_ct indexp, long len)); +#endif + +MLDECL( long, MLConvertNewLine, ( charpp_ct sp)); +MLDECL( long, MLConvertCharacter, ( ulong_ct ch, charpp_ct sp)); +MLDECL( long, MLConvertByteString, ( ucharp_ct codes, long len, charpp_ct strp, charp_ct str_end)); +MLDECL( long, MLConvertByteStringNL, ( ucharp_ct codes, long len, charpp_ct strp, charp_ct str_end, ulong_ct nl)); +MLDECL( long, MLConvertUnicodeString, ( ushortp_ct codes, long len, charpp_ct strp, charp_ct str_end)); +MLDECL( long, MLConvertUnicodeStringNL, ( ushortp_ct codes, long len, charpp_ct strp, charp_ct str_end, ulong_ct nl)); +MLDECL( long, MLConvertDoubleByteString, ( ucharp_ct codes, long len, charpp_ct strp, charp_ct str_end)); +MLDECL( long, MLConvertDoubleByteStringNL, ( ucharp_ct codes, long len, charpp_ct strp, charp_ct str_end, ulong_ct nl)); + + + + + + + +/* for source code compatibility with earlier versions of MathLink */ +MLDECL( kcharp_ct, MLStringFirstPosFun, ( kcharp_ct s, MLStringPositionPointer p)); + +/* for internal use only */ +MLDECL( mlapi_result, MLOldPutCharToString, ( uint_ct ch, charpp_ct sp)); +MLDECL( ucharp_ct, MLOldStringNextPosFun, ( MLOldStringPositionPointer p)); +MLDECL( ucharp_ct, MLOldStringFirstPosFun, ( charp_ct s, MLOldStringPositionPointer p)); +MLDECL( uint_ct, MLOldStringCharFun, ( MLOldStringPositionPointer p)); +MLDECL( long, MLOldConvertByteString, ( ucharp_ct codes, long len, charpp_ct strp, charp_ct str_end)); +MLDECL( long, MLOldConvertUnicodeString, ( ushortp_ct codes, long len, charpp_ct strp, charp_ct str_end)); + +ML_END_EXTERN_C + + +#ifndef _MLCAPUT_H +#define _MLCAPUT_H + +#ifndef MLINTERFACE +/* syntax error */ ) +#endif + +#ifndef __array_meterp__ +#define __array_meterp__ +typedef struct array_meter FAR * array_meterp; +typedef array_meterp FAR * array_meterpp; +#endif + + +#define MLPutRealArray MLPutDoubleArray + +#endif /* _MLCAPUT_H */ + + +/* explicitly not protected by _MLCAPUT_H in case MLDECL is redefined for multiple inclusion */ + +/*bugcheck: bugcheck need FAR here */ +ML_EXTERN_C +MLDECL( mlapi_result, MLPutArray, ( MLINK mlp, array_meterp meterp)); +MLDECL( mlapi_result, MLPutBinaryNumberArrayData, ( MLINK mlp, array_meterp meterp, voidp_ct datap, long_st count, long type)); +MLDECL( mlapi_result, MLPutByteArrayData, ( MLINK mlp, array_meterp meterp, ucharp_nt datap, long_st count)); +MLDECL( mlapi_result, MLPutShortIntegerArrayData, ( MLINK mlp, array_meterp meterp, shortp_nt datap, long_st count)); +MLDECL( mlapi_result, MLPutIntegerArrayData, ( MLINK mlp, array_meterp meterp, intp_nt datap, long_st count)); +MLDECL( mlapi_result, MLPutLongIntegerArrayData, ( MLINK mlp, array_meterp meterp, longp_nt datap, long_st count)); +MLDECL( mlapi_result, MLPutFloatArrayData, ( MLINK mlp, array_meterp meterp, floatp_nt datap, long_st count)); +MLDECL( mlapi_result, MLPutDoubleArrayData, ( MLINK mlp, array_meterp meterp, doublep_nt datap, long_st count)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLPutLongDoubleArrayData, ( MLINK mlp, array_meterp meterp, extendedp_nt datap, long_st count)); +#endif + +MLDECL( mlapi_result, MLPutBinaryNumberArray, ( MLINK mlp, voidp_ct data, longp_st dimp, charpp_ct heads, long_st depth, long type)); +MLDECL( mlapi_result, MLPutByteArray, ( MLINK mlp, ucharp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( mlapi_result, MLPutShortIntegerArray, ( MLINK mlp, shortp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( mlapi_result, MLPutIntegerArray, ( MLINK mlp, intp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( mlapi_result, MLPutLongIntegerArray, ( MLINK mlp, longp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( mlapi_result, MLPutDoubleArray, ( MLINK mlp, doublep_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( mlapi_result, MLPutFloatArray, ( MLINK mlp, floatp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLPutLongDoubleArray, ( MLINK mlp, extendedp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +#endif + +MLDECL( mlapi_result, MLPutBinaryNumberList, ( MLINK mlp, voidp_ct data, long_st count, long type)); +MLDECL( mlapi_result, MLPutIntegerList, ( MLINK mlp, intp_nt data, long_st count)); +MLDECL( mlapi_result, MLPutRealList, ( MLINK mlp, doublep_nt data, long_st count)); + +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLPutArrayType0, ( MLINK mlp, MLINK heads, long depth, array_meterpp meterpp)); +MLDECL( mlapi_result, MLPutBinaryNumberArrayData0, ( MLINK mlp, MLINK heads, array_meterp meterp, voidp_ct datap, long_st count, long type)); +MLDECL( mlapi_result, MLReleasePutArrayState0, ( MLINK mlp, MLINK heads, array_meterp meterp)); +MLDECL( mlapi_result, MLPutArrayLeaves0, ( MLINK mlp, MLINK heads, array_meterp meterp, MLINK leaves, long_st count)); +#endif + +ML_END_EXTERN_C + + +#ifndef _MLCAGET_H +#define _MLCAGET_H + +#ifndef MLINTERFACE +/* syntax error */ ) +#endif + +#ifndef __array_meterp__ +#define __array_meterp__ +typedef struct array_meter FAR * array_meterp; +typedef array_meterp FAR * array_meterpp; +#endif + + +#define MLGetRealArray MLGetDoubleArray +#define MLDisownRealArray MLDisownDoubleArray + +#endif /* _MLCAGET_H */ + + + +/* explicitly not protected by _MLCAGET_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLGetBinaryNumberList, ( MLINK mlp, voidpp_ct datap, longp_st countp, long type)); +MLDECL( mlapi_result, MLGetIntegerList, ( MLINK mlp, intpp_nt datap, longp_st countp)); +MLDECL( mlapi_result, MLGetRealList, ( MLINK mlp, doublepp_nt datap, longp_st countp)); + +MLDECL( void, MLDisownBinaryNumberList, ( MLINK mlp, voidp_ct data, long_st count, long type)); +MLDECL( void, MLDisownIntegerList, ( MLINK mlp, intp_nt data, long_st count)); +MLDECL( void, MLDisownRealList, ( MLINK mlp, doublep_nt data, long_st count)); + +MLDECL( mlapi_token, MLGetArrayType, ( MLINK mlp, array_meterp meterp)); +MLDECL( mlapi_result, MLGetArrayDimensions, ( MLINK mlp, array_meterp meterp)); + +MLDECL( mlapi_result, MLGetBinaryNumberArrayData, ( MLINK mlp, array_meterp meterp, voidp_ct datap, long_st count, long type)); +MLDECL( mlapi_result, MLGetByteArrayData, ( MLINK mlp, array_meterp meterp, ucharp_nt datap, long_st count)); +MLDECL( mlapi_result, MLGetShortIntegerArrayData, ( MLINK mlp, array_meterp meterp, shortp_nt datap, long_st count)); +MLDECL( mlapi_result, MLGetIntegerArrayData, ( MLINK mlp, array_meterp meterp, intp_nt datap, long_st count)); +MLDECL( mlapi_result, MLGetLongIntegerArrayData, ( MLINK mlp, array_meterp meterp, longp_nt datap, long_st count)); +MLDECL( mlapi_result, MLGetFloatArrayData, ( MLINK mlp, array_meterp meterp, floatp_nt datap, long_st count)); +MLDECL( mlapi_result, MLGetDoubleArrayData, ( MLINK mlp, array_meterp meterp, doublep_nt datap, long_st count)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLGetLongDoubleArrayData, ( MLINK mlp, array_meterp meterp, extendedp_nt datap, long_st count)); +#endif + +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLGetArrayType0, ( MLINK mlp, MLINK heads, array_meterpp meterpp, longp_st depthp, mlapi__tokenp leaf_tokp)); +MLDECL( mlapi_result, MLGetBinaryNumberArrayData0, ( MLINK mlp, MLINK heads, array_meterp meterp, voidp_ct datap, longp_st countp, long type)); +MLDECL( void, MLReleaseGetArrayState0, ( MLINK mlp, MLINK heads, array_meterp meterp)); + +MLDECL( mlapi_result, MLGetBinaryNumberArray0, ( MLINK mlp, voidpp_ct datap, longpp_st dimpp, charppp_ct headsp, longp_st depthp, long type, mlapi__tokenp leaf_tokp)); +#endif +MLDECL( mlapi_result, MLGetBinaryNumberArray, ( MLINK mlp, voidpp_ct datap, longpp_st dimpp, charppp_ct headsp, longp_st depthp, long type)); +MLDECL( mlapi_result, MLGetByteArray, ( MLINK mlp, ucharpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +MLDECL( mlapi_result, MLGetShortIntegerArray, ( MLINK mlp, shortpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +MLDECL( mlapi_result, MLGetIntegerArray, ( MLINK mlp, intpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +MLDECL( mlapi_result, MLGetLongIntegerArray, ( MLINK mlp, longpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +MLDECL( mlapi_result, MLGetDoubleArray, ( MLINK mlp, doublepp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +MLDECL( mlapi_result, MLGetFloatArray, ( MLINK mlp, floatpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( mlapi_result, MLGetLongDoubleArray, ( MLINK mlp, extendedpp_nt datap, longpp_st dimsp, charppp_ct headsp, longp_st depthp)); +#endif + +MLDECL( void, MLDisownBinaryNumberArray, ( MLINK mlp, voidp_ct data, longp_st dimp, charpp_ct heads, long_st len, long type)); +MLDECL( void, MLDisownByteArray, ( MLINK mlp, ucharp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( void, MLDisownShortIntegerArray, ( MLINK mlp, shortp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( void, MLDisownIntegerArray, ( MLINK mlp, intp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( void, MLDisownLongIntegerArray, ( MLINK mlp, longp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( void, MLDisownFloatArray, ( MLINK mlp, floatp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +MLDECL( void, MLDisownDoubleArray, ( MLINK mlp, doublep_nt data, longp_st dims, charpp_ct heads, long_st depth)); +#if CC_SUPPORTS_LONG_DOUBLE +MLDECL( void, MLDisownLongDoubleArray, ( MLINK mlp, extendedp_nt data, longp_st dims, charpp_ct heads, long_st depth)); +#endif +ML_END_EXTERN_C + + +/*************** seeking, transfering and synchronization ***************/ + +#ifndef _MLMARK_H +#define _MLMARK_H + + +#endif /* _MLMARK_H */ + +/* explicitly not protected by _MLMARK_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( MLINKMark, MLCreateMark, ( MLINK mlp)); +MLDECL( MLINKMark, MLSeekToMark, ( MLINK mlp, MLINKMark mark, long index)); +MLDECL( MLINKMark, MLSeekMark, ( MLINK mlp, MLINKMark mark, long index)); +MLDECL( void, MLDestroyMark, ( MLINK mlp, MLINKMark mark)); +ML_END_EXTERN_C + + +#ifndef _MLXFER_H +#define _MLXFER_H + + +#endif /* _MLXFER_H */ + +/* explicitly not protected by _MLXFER_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_result, MLTransferExpression, ( MLINK dmlp, MLINK smlp)); +MLDECL( mlapi_result, MLTransferToEndOfLoopbackLink, ( MLINK dmlp, MLINK smlp)); +#ifndef MLINTERFACE +/* syntax error */ ) +#endif +#if MLINTERFACE > 1 +MLDECL( mlapi_result, MLTransfer0, ( MLINK dmlp, MLINK smlp, ulong_ct sequence_no)); +#endif +ML_END_EXTERN_C + + +#ifndef _MLSYNC_H +#define _MLSYNC_H + + +/* export mls__wait and mls__align(mlsp) */ + +#endif /* _MLSYNC_H */ + +/* explicitly not protected by _MLSYNC_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +/* in response to a reset message */ +MLDECL( mlapi_result, MLForwardReset, ( MLINK mlp, ulong_ct marker)); +MLDECL( mlapi_result, MLAlign, ( MLINK lmlp, MLINK rmlp)); +ML_END_EXTERN_C + +/*************************************************************/ + + +#ifndef _MLPKT_H +#define _MLPKT_H + +/*************** Mathematica packet interface ***************/ + + /* MLNextPacket returns one of... */ + + +/* edit here and in mlpktstr.h */ + +#ifndef _MLPKTNO_H +#define _MLPKTNO_H + +#define ILLEGALPKT 0 + +#define CALLPKT 7 +#define EVALUATEPKT 13 +#define RETURNPKT 3 + +#define INPUTNAMEPKT 8 +#define ENTERTEXTPKT 14 +#define ENTEREXPRPKT 15 +#define OUTPUTNAMEPKT 9 +#define RETURNTEXTPKT 4 +#define RETURNEXPRPKT 16 + +#define DISPLAYPKT 11 +#define DISPLAYENDPKT 12 + +#define MESSAGEPKT 5 +#define TEXTPKT 2 + +#define INPUTPKT 1 +#define INPUTSTRPKT 21 +#define MENUPKT 6 +#define SYNTAXPKT 10 + +#define SUSPENDPKT 17 +#define RESUMEPKT 18 + +#define BEGINDLGPKT 19 +#define ENDDLGPKT 20 + +#define FIRSTUSERPKT 128 +#define LASTUSERPKT 255 + + +#endif /* _MLPKTNO_H */ + +#endif /* _MLPKT_H */ + +/* explicitly not protected by _MLPKT_H in case MLDECL is redefined for multiple inclusion */ + +ML_EXTERN_C +MLDECL( mlapi_packet, MLNextPacket, ( MLINK mlp)); +ML_END_EXTERN_C + + +#ifndef _MLALERT_H +#define _MLALERT_H + + + +ML_EXTERN_C +/*************** User interaction--for internal use only ***************/ +typedef long mldlg_result; + +MLDPROC( mldlg_result, MLAlertProcPtr, ( MLEnvironment env, kcharp_ct message)); +MLDPROC( mldlg_result, MLRequestProcPtr, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDPROC( mldlg_result, MLConfirmProcPtr, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDPROC( mldlg_result, MLRequestArgvProcPtr, ( MLEnvironment env, charpp_ct argv, long cardof_argv, charp_ct buf, long sizeof_buf)); +MLDPROC( mldlg_result, MLRequestToInteractProcPtr, ( MLEnvironment env, mldlg_result wait_for_permission)); +MLDPROC( mldlg_result, MLDialogProcPtr, ( MLEnvironment env)); + +#if MACINTOSH_MATHLINK +enum { + uppMLAlertFunctionProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(mldlg_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLEnvironment))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(kcharp_ct))), + uppMLRequestFunctionProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(mldlg_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLEnvironment))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(kcharp_ct))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(charp_ct))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long))), + uppMLConfirmFunctionProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(mldlg_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLEnvironment))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(kcharp_ct))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(mldlg_result))), + uppMLRequestArgvFunctionProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(mldlg_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLEnvironment))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(charpp_ct))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(charp_ct))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long))), + uppMLRequestToInteractFunctionProcInfo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(mldlg_result))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MLEnvironment))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(mldlg_result))) +}; +#endif /* MACINTOSH_MATHLINK */ + + +#if MACINTOSH_MATHLINK +#if GENERATINGCFM + typedef UniversalProcPtr MLDialogUPP; + typedef UniversalProcPtr MLAlertUPP; + typedef UniversalProcPtr MLRequestUPP; + typedef UniversalProcPtr MLConfirmUPP; + typedef UniversalProcPtr MLRequestArgvUPP; + typedef UniversalProcPtr MLRequestToInteractUPP; +# define NewMLAlertProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)MLAlertCast((userRoutine)), \ + uppMLAlertFunctionProcInfo, GetCurrentArchitecture()) +# define NewMLRequestProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)MLRequestCast((userRoutine)), \ + uppMLRequestFunctionProcInfo, GetCurrentArchitecture()) +# define NewMLConfirmProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)MLConfirmCast((userRoutine)), \ + uppMLConfirmFunctionProcInfo, GetCurrentArchitecture()) +# define NewMLRequestArgvProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)MLRequestArgvCast((userRoutine)), \ + uppMLRequestArgvFunctionProcInfo, GetCurrentArchitecture()) +# define NewMLRequestToInteractProc(userRoutine) \ + NewRoutineDescriptor((ProcPtr)MLRequestToInteractCast((userRoutine)), \ + uppMLRequestToInteractFunctionProcInfo, GetCurrentArchitecture()) +#else /* GENERATINGCFM */ + typedef MLDialogProcPtr MLDialogUPP; + typedef MLAlertProcPtr MLAlertUPP; + typedef MLRequestProcPtr MLRequestUPP; + typedef MLConfirmProcPtr MLConfirmUPP; + typedef MLRequestArgvProcPtr MLRequestArgvUPP; + typedef MLRequestToInteractProcPtr MLRequestToInteractUPP; +# define NewMLAlertProc(userRoutine) MLAlertCast((userRoutine)) +# define NewMLRequestProc(userRoutine) MLRequestCast((userRoutine)) +# define NewMLConfirmProc(userRoutine) MLConfirmCast((userRoutine)) +# define NewMLRequestArgvProc(userRoutine) MLRequestArgvCast((userRoutine)) +# define NewMLRequestToInteractProc(userRoutine) MLRequestToInteractCast((userRoutine)) +#endif /* GENERATINGCFM */ +#else /* !MACINTOSH_MATHLINK */ + typedef MLDialogProcPtr MLDialogUPP; + typedef MLAlertProcPtr MLAlertUPP; + typedef MLRequestProcPtr MLRequestUPP; + typedef MLConfirmProcPtr MLConfirmUPP; + typedef MLRequestArgvProcPtr MLRequestArgvUPP; + typedef MLRequestToInteractProcPtr MLRequestToInteractUPP; +# define NewMLAlertProc(userRoutine) MLAlertCast((userRoutine)) +# define NewMLRequestProc(userRoutine) MLRequestCast((userRoutine)) +# define NewMLConfirmProc(userRoutine) MLConfirmCast((userRoutine)) +# define NewMLRequestArgvProc(userRoutine) MLRequestArgvCast((userRoutine)) +# define NewMLRequestToInteractProc(userRoutine) MLRequestToInteractCast((userRoutine)) +#endif /* MACINTOSH_MATHLINK */ + +typedef MLAlertUPP MLAlertFunctionType; +typedef MLRequestUPP MLRequestFunctionType; +typedef MLConfirmUPP MLConfirmFunctionType; +typedef MLRequestArgvUPP MLRequestArgvFunctionType; +typedef MLRequestToInteractUPP MLRequestToInteractFunctionType; +typedef MLDialogUPP MLDialogFunctionType; + + + +/* + MLDDECL( mldlg_result, alert_user, ( MLEnvironment env, kcharp_ct message)); + MLDDEFN( mldlg_result, alert_user, ( MLEnvironment env, kcharp_ct message)) + { + fprintf( stderr, "%s\n", message); + } + + + ... + MLDialogFunctionType f = NewMLAlertProc(alert_user); + MLSetDialogFunction( ep, MLAlertFunction, f); + ... + or + ... + MLSetDialogFunction( ep, MLAlertFunction, NewMLAlertProc(alert_user)); + ... +*/ + + + +enum { MLAlertFunction = 1, MLRequestFunction, MLConfirmFunction, + MLRequestArgvFunction, MLRequestToInteractFunction }; + + +#define ML_DEFAULT_DIALOG ( (MLDialogFunctionType) 1) +#define ML_IGNORE_DIALOG ( (MLDialogFunctionType) 0) +#define ML_SUPPRESS_DIALOG ML_IGNORE_DIALOG + + + + +#if MACINTOSH_MATHLINK + +#ifndef _MLMAC_H +#define _MLMAC_H + + +ML_EXTERN_C + +MLDDECL( mldlg_result, MLPermit_application, ( MLEnvironment env, mldlg_result wait_for_permission)); + +MLDDECL( mldlg_result, MLAlert_application, ( MLEnvironment env, kcharp_ct message)); +MLDDECL( mldlg_result, MLAlert_tool, ( MLEnvironment env, kcharp_ct message)); +MLDDECL( mldlg_result, MLAlert_siow, ( MLEnvironment env, kcharp_ct message)); +MLDDECL( mldlg_result, MLAlert_console, ( MLEnvironment env, kcharp_ct message)); + +MLDDECL( mldlg_result, MLRequest_application, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDDECL( mldlg_result, MLRequest_console, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDDECL( mldlg_result, MLRequest_tool, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDDECL( mldlg_result, MLRequest_siow, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); + +MLDDECL( mldlg_result, MLConfirm_application, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLConfirm_tool, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLConfirm_siow, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLConfirm_console, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); + +ML_END_EXTERN_C + +#endif /* _MLMAC_H */ +#define MLALERT MLAlert_application +#define MLREQUEST MLRequest_application +#define MLCONFIRM MLConfirm_application +#define MLPERMIT MLPermit_application +#define MLREQUESTARGV default_request_argv +#endif + +#if WINDOWS_MATHLINK + +#ifndef _MLWIN_H +#define _MLWIN_H + + + +ML_EXTERN_C +MLDDECL( mldlg_result, MLAlert_win, ( MLEnvironment ep, kcharp_ct alertstr)); +MLDDECL( mldlg_result, MLRequest_win, ( MLEnvironment ep, kcharp_ct prompt, charp_ct response, long n)); +MLDDECL( mldlg_result, MLConfirm_win, ( MLEnvironment ep, kcharp_ct okcancelquest, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLPermit_win, ( MLEnvironment ep, mldlg_result wait)); +ML_END_EXTERN_C + +/* edit here and in mlwin.rc -- in both places because of command-line length limitations in dos */ +#define DLG_LINKNAME 101 +#define DLG_TEXT 102 +#define RIDOK 1 +#define RIDCANCEL 104 + +#endif /* _MLWIN_H */ +#define MLALERT MLAlert_win +#define MLREQUEST MLRequest_win +#define MLCONFIRM MLConfirm_win +#define MLPERMIT MLPermit_win +#define MLREQUESTARGV default_request_argv +#endif + +#if UNIX_MATHLINK +#if DARWIN_MATHLINK && defined (__CONDITIONALMACROS__) + +#ifndef _MLDARWIN_H +#define _MLDARWIN_H + + +ML_EXTERN_C + +MLDDECL( mldlg_result, MLAlert_darwin, ( MLEnvironment env, kcharp_ct message)); +MLDDECL( mldlg_result, MLRequest_darwin, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDDECL( mldlg_result, MLConfirm_darwin, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLPermit_darwin, ( MLEnvironment env, mldlg_result wait_for_permission)); +MLDDEFN( mldlg_result, MLDontPermit_darwin, ( MLEnvironment ep, mldlg_result wait_for_permission)); + +ML_END_EXTERN_C + +#endif /* _MLDARWIN_H */ +#define MLALERT MLAlert_darwin +#define MLREQUEST MLRequest_darwin +#define MLCONFIRM MLConfirm_darwin +#define MLPERMIT MLPermit_darwin +#define MLREQUESTARGV default_request_argv +#else /* !(DARWIN_MATHLINK && defined (__CONDITIONALMACROS__)) */ + +#ifndef _MLUNIX_H +#define _MLUNIX_H + + +ML_EXTERN_C + +MLDDECL( mldlg_result, MLAlert_unix, ( MLEnvironment env, kcharp_ct message)); +MLDDECL( mldlg_result, MLRequest_unix, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); +MLDDECL( mldlg_result, MLConfirm_unix, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLPermit_unix, ( MLEnvironment env, mldlg_result wait_for_permission)); + +ML_END_EXTERN_C + +#endif /* _MLUNIX_H */ +#define MLALERT MLAlert_unix +#define MLREQUEST MLRequest_unix +#define MLCONFIRM MLConfirm_unix +#define MLPERMIT MLPermit_unix +#define MLREQUESTARGV default_request_argv +#endif /* DARWIN_MATHLINK && defined (__CONDITIONALMACROS__) */ +#endif + +#if OS2_MATHLINK + +#ifndef _MLOS2_H +#define _MLOS2_H + + + +ML_EXTERN_C +MLDDECL( mldlg_result, MLAlert_os2, ( MLEnvironment ep, kcharp_ct alertstr)); +MLDDECL( mldlg_result, MLRequest_os2, ( MLEnvironment ep, kcharp_ct prompt, charp_ct response, long n)); +MLDDECL( mldlg_result, MLConfirm_os2, ( MLEnvironment ep, kcharp_ct okcancelquest, mldlg_result default_answer)); +MLDDECL( mldlg_result, MLPermit_os2, ( MLEnvironment ep, mldlg_result wait)); +ML_END_EXTERN_C + +#endif /* _MLOS2_H */ +#define MLALERT MLAlert_os2 +#define MLREQUEST MLRequest_os2 +#define MLCONFIRM MLConfirm_os2 +#define MLPERMIT MLPermit_os2 +#define MLREQUESTARGV default_request_argv +#endif + +MLDDECL( mldlg_result, default_request_argv, ( MLEnvironment ep, charpp_ct argv, long len, charp_ct buff, long size)); +ML_END_EXTERN_C + +#endif /* _MLALERT_H */ + + +/* explicitly not protected by _MLXDATA_H in case MLDECL is redefined for multiple inclusion */ +ML_EXTERN_C +MLDECL( mldlg_result, MLAlert, ( MLEnvironment env, kcharp_ct message)); +MLDECL( mldlg_result, MLRequest, ( MLEnvironment env, kcharp_ct prompt, charp_ct response, long sizeof_response)); /* initialize response with default*/ +MLDECL( mldlg_result, MLConfirm, ( MLEnvironment env, kcharp_ct question, mldlg_result default_answer)); +MLDECL( mldlg_result, MLRequestArgv, ( MLEnvironment env, charpp_ct argv, long cardof_argv, charp_ct buff, long size)); +MLDECL( mldlg_result, MLRequestToInteract, ( MLEnvironment env, mldlg_result wait_for_permission)); +MLDECL( mlapi_result, MLSetDialogFunction, ( MLEnvironment env, long funcnum, MLDialogFunctionType func)); + +/* just some type-safe casts */ +MLDECL( MLDialogProcPtr, MLAlertCast, ( MLAlertProcPtr f)); +MLDECL( MLDialogProcPtr, MLRequestCast, ( MLRequestProcPtr f)); +MLDECL( MLDialogProcPtr, MLConfirmCast, ( MLConfirmProcPtr f)); +MLDECL( MLDialogProcPtr, MLRequestArgvCast, ( MLRequestArgvProcPtr f)); +MLDECL( MLDialogProcPtr, MLRequestToInteractCast, ( MLRequestToInteractProcPtr f)); +ML_END_EXTERN_C + +/*************************************************************/ + +#ifdef __CFM68K__ +#pragma import off +#endif + + +#ifndef _MLTM_H +#define _MLTM_H + + +/*************** Template interface ***************/ + +/* The following are useful only when using template files as + * their definitions are produced by mprep. + */ + +extern MLINK stdlink; +extern MLEnvironment stdenv; +extern MLYieldFunctionObject stdyielder; +extern MLMessageHandlerObject stdhandler; +extern int MLMain P((int, charpp_ct)); /* pass in argc and argv */ +extern int MLMainString P(( charp_ct commandline)); +extern int MLMainArgv P(( char** argv, char** argv_end)); /* note not FAR pointers */ + +extern int MLInstall P((MLINK)); +extern mlapi_packet MLAnswer P((MLINK)); +extern int MLDoCallPacket P((MLINK)); +extern int MLEvaluate P(( MLINK, charp_ct)); +extern int MLEvaluateString P(( MLINK, charp_ct)); +MLMDECL( void, MLDefaultHandler, ( MLINK, unsigned long, unsigned long)); +MLYDECL( devyield_result, MLDefaultYielder, ( MLINK, MLYieldParameters)); + +#if WINDOWS_MATHLINK +extern HWND MLInitializeIcon P(( HINSTANCE hinstCurrent, int nCmdShow)); +extern HANDLE MLInstance; +extern HWND MLIconWindow; +#endif +extern int MLAbort, MLDone; +extern long MLSpecialCharacter; + +#endif /* _MLTM_H */ + + + +#endif /* _MATHLINK_H */ diff --git a/femm/probdlg.cpp b/femm/probdlg.cpp new file mode 100644 index 0000000..7da9136 --- /dev/null +++ b/femm/probdlg.cpp @@ -0,0 +1,110 @@ +// probdlg.cpp : implementation file +// + +#include "stdafx.h" +#include "femm.h" +#include "probdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// probdlg dialog + + +probdlg::probdlg(CWnd* pParent /*=NULL*/) + : CDialog(probdlg::IDD, pParent) + , m_prevsoln(_T("")) +{ + //{{AFX_DATA_INIT(probdlg) + m_frequency = 0.0; + m_problem_note = _T(""); + m_precision = 1.e-8; + m_depth = 1.0; + m_minangle = DEFAULT_MINIMUM_ANGLE; + m_prevsoln = _T(""); + //}}AFX_DATA_INIT +} + + +void probdlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(probdlg) + DDX_Control(pDX, IDC_SOLVER, m_solver); + DDX_Control(pDX, IDC_LENGTH_UNITS, m_length_units); + DDX_Control(pDX, IDC_BSMART, m_bsmart); + DDX_Control(pDX, IDC_PROBTYPE, m_probtype); + DDX_Control(pDX, IDC_PREVTYPE, m_prevtype); + DDX_Text(pDX, IDC_EDIT_FREQ, m_frequency); + DDX_Text(pDX, IDC_PROBNOTE, m_problem_note); + DDX_Text(pDX, IDC_PRC, m_precision); + DDV_MinMaxDouble(pDX, m_precision, 1.e-016, 1.e-008); + DDX_Text(pDX, IDC_MINANG, m_minangle); + DDV_MinMaxDouble(pDX, m_minangle, 1., MINANGLE_MAX); + DDX_Text(pDX, IDC_EDIT_DEPTH, m_depth); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_EDIT_FREQ, m_IDC_frequency); + DDX_Control(pDX, IDC_EDIT_DEPTH, m_IDC_depth); + DDX_Control(pDX, IDC_PROBNOTE, m_IDC_problem_note); + DDX_Control(pDX, IDC_PRC, m_IDC_precision); + DDX_Control(pDX, IDC_MINANG, m_IDC_minangle); + DDX_Text(pDX, IDC_PREVSOLN, m_prevsoln); +} + + +BEGIN_MESSAGE_MAP(probdlg, CDialog) + //{{AFX_MSG_MAP(probdlg) + ON_CBN_SELCHANGE(IDC_LENGTH_UNITS, OnSelchangeLengthUnits) + ON_CBN_SELCHANGE(IDC_PROBTYPE, OnSelchangeProbtype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// probdlg message handlers + +BOOL probdlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_probtype.SetCurSel(probtype); + if(probtype) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); + + m_length_units.SetCurSel(lengthunits); + m_bsmart.SetCurSel(bsmart); + m_solver.SetCurSel(solver); + m_prevtype.SetCurSel(prevtype); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void probdlg::OnOK() +{ + if (UpdateData()==FALSE) return; + probtype=m_probtype.GetCurSel(); + if(probtype) m_depth=1; + m_frequency=fabs(m_frequency); + UpdateData(FALSE); + lengthunits=m_length_units.GetCurSel(); + bsmart=m_bsmart.GetCurSel(); + solver=m_solver.GetCurSel(); + prevtype = m_prevtype.GetCurSel(); + CDialog::OnOK(); +} + +void probdlg::OnSelchangeLengthUnits() +{ + +} + +void probdlg::OnSelchangeProbtype() +{ + if(m_probtype.GetCurSel()) m_IDC_depth.EnableWindow(FALSE); + else m_IDC_depth.EnableWindow(TRUE); +} diff --git a/femm/probdlg.h b/femm/probdlg.h new file mode 100644 index 0000000..a2a70b9 --- /dev/null +++ b/femm/probdlg.h @@ -0,0 +1,57 @@ +// probdlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// probdlg dialog + +class probdlg : public CDialog +{ +// Construction +public: + probdlg(CWnd* pParent = NULL); // standard constructor + + BOOL probtype; // variable denoting problem type + // so list entry can be correctly set + int lengthunits; // contains units of length; + int bsmart; + int prevtype; // contains previous solution type for incremental/frozen perm problems + int solver; // contains the solver type to be used in AC problems. + +// Dialog Data + //{{AFX_DATA(probdlg) + enum { IDD = IDD_PROBDLG }; + CComboBox m_solver; + CComboBox m_length_units; + CComboBox m_bsmart; + CComboBox m_probtype; + CComboBox m_prevtype; + double m_frequency; + CString m_problem_note; + double m_precision; + double m_minangle; + double m_depth; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(probdlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(probdlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnSelchangeLengthUnits(); + afx_msg void OnSelchangeProbtype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_frequency, m_IDC_problem_note, m_IDC_precision, m_IDC_depth, m_IDC_minangle; + CString m_prevsoln; +}; diff --git a/femm/res/Toolbar.bmp b/femm/res/Toolbar.bmp new file mode 100644 index 0000000..d501723 Binary files /dev/null and b/femm/res/Toolbar.bmp differ diff --git a/femm/res/bitmap1.bmp b/femm/res/bitmap1.bmp new file mode 100644 index 0000000..8edf93f Binary files /dev/null and b/femm/res/bitmap1.bmp differ diff --git a/femm/res/bmp00001.bmp b/femm/res/bmp00001.bmp new file mode 100644 index 0000000..1588347 Binary files /dev/null and b/femm/res/bmp00001.bmp differ diff --git a/femm/res/bmp00002.bmp b/femm/res/bmp00002.bmp new file mode 100644 index 0000000..9a39a84 Binary files /dev/null and b/femm/res/bmp00002.bmp differ diff --git a/femm/res/bmp00003.bmp b/femm/res/bmp00003.bmp new file mode 100644 index 0000000..397001d Binary files /dev/null and b/femm/res/bmp00003.bmp differ diff --git a/femm/res/bmp00004.bmp b/femm/res/bmp00004.bmp new file mode 100644 index 0000000..c149697 Binary files /dev/null and b/femm/res/bmp00004.bmp differ diff --git a/femm/res/bmp00005.bmp b/femm/res/bmp00005.bmp new file mode 100644 index 0000000..1d3b106 Binary files /dev/null and b/femm/res/bmp00005.bmp differ diff --git a/femm/res/bmp00006.bmp b/femm/res/bmp00006.bmp new file mode 100644 index 0000000..0284b7a Binary files /dev/null and b/femm/res/bmp00006.bmp differ diff --git a/femm/res/bmp00007.bmp b/femm/res/bmp00007.bmp new file mode 100644 index 0000000..f376b34 Binary files /dev/null and b/femm/res/bmp00007.bmp differ diff --git a/femm/res/bmp00013.bmp b/femm/res/bmp00013.bmp new file mode 100644 index 0000000..4c57104 Binary files /dev/null and b/femm/res/bmp00013.bmp differ diff --git a/femm/res/cdrawtyp.bmp b/femm/res/cdrawtyp.bmp new file mode 100644 index 0000000..38dbb15 Binary files /dev/null and b/femm/res/cdrawtyp.bmp differ diff --git a/femm/res/cviewtyp.bmp b/femm/res/cviewtyp.bmp new file mode 100644 index 0000000..6dc197b Binary files /dev/null and b/femm/res/cviewtyp.bmp differ diff --git a/femm/res/femmetyp.bmp b/femm/res/femmetyp.bmp new file mode 100644 index 0000000..dea562d Binary files /dev/null and b/femm/res/femmetyp.bmp differ diff --git a/femm/res/femmtype.bmp b/femm/res/femmtype.bmp new file mode 100644 index 0000000..2fa71ae Binary files /dev/null and b/femm/res/femmtype.bmp differ diff --git a/femm/res/femmview.bmp b/femm/res/femmview.bmp new file mode 100644 index 0000000..706f631 Binary files /dev/null and b/femm/res/femmview.bmp differ diff --git a/femm/res/hdrawtyp.bmp b/femm/res/hdrawtyp.bmp new file mode 100644 index 0000000..4c4781d Binary files /dev/null and b/femm/res/hdrawtyp.bmp differ diff --git a/femm/res/hviewtyp.bmp b/femm/res/hviewtyp.bmp new file mode 100644 index 0000000..6dc197b Binary files /dev/null and b/femm/res/hviewtyp.bmp differ diff --git a/femm/res/idr_beladrawtype.ico b/femm/res/idr_beladrawtype.ico new file mode 100644 index 0000000..79ac675 Binary files /dev/null and b/femm/res/idr_beladrawtype.ico differ diff --git a/femm/res/idr_belaviewtype.ico b/femm/res/idr_belaviewtype.ico new file mode 100644 index 0000000..ded1181 Binary files /dev/null and b/femm/res/idr_belaviewtype.ico differ diff --git a/femm/res/idr_cdrawtype.ico b/femm/res/idr_cdrawtype.ico new file mode 100644 index 0000000..0748519 Binary files /dev/null and b/femm/res/idr_cdrawtype.ico differ diff --git a/femm/res/idr_cviewtype.ico b/femm/res/idr_cviewtype.ico new file mode 100644 index 0000000..0b03a20 Binary files /dev/null and b/femm/res/idr_cviewtype.ico differ diff --git a/femm/res/idr_femmetype.ico b/femm/res/idr_femmetype.ico new file mode 100644 index 0000000..186acbe Binary files /dev/null and b/femm/res/idr_femmetype.ico differ diff --git a/femm/res/idr_femmplottype.ico b/femm/res/idr_femmplottype.ico new file mode 100644 index 0000000..c9b9d12 Binary files /dev/null and b/femm/res/idr_femmplottype.ico differ diff --git a/femm/res/idr_femmviewtype.ico b/femm/res/idr_femmviewtype.ico new file mode 100644 index 0000000..0c67f0c Binary files /dev/null and b/femm/res/idr_femmviewtype.ico differ diff --git a/femm/res/idr_hdrawtype.ico b/femm/res/idr_hdrawtype.ico new file mode 100644 index 0000000..91f6386 Binary files /dev/null and b/femm/res/idr_hdrawtype.ico differ diff --git a/femm/res/idr_hviewtype.ico b/femm/res/idr_hviewtype.ico new file mode 100644 index 0000000..c52522c Binary files /dev/null and b/femm/res/idr_hviewtype.ico differ diff --git a/femm/res/idr_mainframe.ico b/femm/res/idr_mainframe.ico new file mode 100644 index 0000000..cf7b56c Binary files /dev/null and b/femm/res/idr_mainframe.ico differ diff --git a/femm/res/left1.bmp b/femm/res/left1.bmp new file mode 100644 index 0000000..2fa71ae Binary files /dev/null and b/femm/res/left1.bmp differ diff --git a/femm/res/left2.bmp b/femm/res/left2.bmp new file mode 100644 index 0000000..2fa71ae Binary files /dev/null and b/femm/res/left2.bmp differ diff --git a/femm/res/main1.bmp b/femm/res/main1.bmp new file mode 100644 index 0000000..2240d0c Binary files /dev/null and b/femm/res/main1.bmp differ diff --git a/femm/res/main2.bmp b/femm/res/main2.bmp new file mode 100644 index 0000000..a984bda Binary files /dev/null and b/femm/res/main2.bmp differ diff --git a/femm/res/toolbar1.bmp b/femm/res/toolbar1.bmp new file mode 100644 index 0000000..5dd7bde Binary files /dev/null and b/femm/res/toolbar1.bmp differ diff --git a/femm/res/tree.bmp b/femm/res/tree.bmp new file mode 100644 index 0000000..f56bb41 Binary files /dev/null and b/femm/res/tree.bmp differ diff --git a/femm/res/viewtool.bmp b/femm/res/viewtool.bmp new file mode 100644 index 0000000..f3efe9d Binary files /dev/null and b/femm/res/viewtool.bmp differ diff --git a/femm/spars.cpp b/femm/spars.cpp new file mode 100644 index 0000000..04cd9d8 --- /dev/null +++ b/femm/spars.cpp @@ -0,0 +1,370 @@ +#include "stdafx.h" +#include +#include +#include +#include "spars.h" + +CEntry::CEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigLinProb::CBigLinProb() +{ + n=0; + Precision=1.e-8; // default solver precision + bar=NULL; +} + +CBigLinProb::~CBigLinProb() +{ + if (n==0) return; + + int i; + CEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + + free(M); +} + +int CBigLinProb::Create(int d, int bw) +{ + int i; + + bdw=bw; + b=(double *)calloc(d,sizeof(double)); + V=(double *)calloc(d,sizeof(double)); + P=(double *)calloc(d,sizeof(double)); + R=(double *)calloc(d,sizeof(double)); + U=(double *)calloc(d,sizeof(double)); + Z=(double *)calloc(d,sizeof(double)); + M=(CEntry **)calloc(d,sizeof(CEntry *)); + n=d; + + for(i=0;ic = i; + } + + return 1; +} + +void CBigLinProb::Put(double v, int p, int q) +{ + CEntry *e,*l; + int i; + + if(qc < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CEntry *m = new CEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + return; +} + +double CBigLinProb::Get(int p, int q) +{ + CEntry *e; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) return e->x; + + return 0; +} + +void CBigLinProb::MultA(double *X, double *Y) +{ + int i; + CEntry *e; + + for(i=0;ix*X[i]; + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=e->x*X[e->c]; + Y[e->c]+=e->x*X[i]; + e=e->next; + } + } +} + +double CBigLinProb::Dot(double *X, double *Y) +{ + int i; + double z; + + for(i=0,z=0;ix; + + // SSOR preconditioner: + int i; + double c; + CEntry *e; + + c= Lambda*(2-Lambda); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * Lambda; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * Lambda; + e=e->next; + } + Y[i]/= M[i]->x; + } +} + +int CBigLinProb::PCGSolve(int flag) +{ + int i; + double res,res_o,res_new; + double er,del,rho,pAp; + + // quick check for most obvious sign of singularity; + for(i=0;ix==0){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // initialize progress bar; + if(bar!=NULL){ + bar->SetPos(0); + Pump(); + } + int prg1=0; + int prg2; + + // Best guess for relaxation parameter + Lambda=1.5; + + // residual with V=0 + MultPC(b,Z); + res_o=Dot(Z,b); + if(res_o==0) return 1; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + if (bar!=NULL) bar->SetPos(prg2); + Pump(); + } + + } while(er>Precision); + + return 1; +} + +void CBigLinProb::SetValue(int i, double x) +{ + int k,fst,lst; + double z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>n) lst=n; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigLinProb::Periodicity(int i, int j) +{ + int k; + double v1,v2,c; + + for(k=0;k10)&&(i<23)) for(k=11;k<23;k++) cclist[k-11]=clist[k]; + if(i>22) for(k=23;k<35;k++) cclist[k-23]=clist[k]; + + dlg.m_cc.lpCustColors=cclist; + dlg.m_cc.rgbResult=clist[i]; + dlg.m_cc.Flags=dlg.m_cc.Flags | CC_FULLOPEN | CC_RGBINIT; + + if(dlg.DoModal()==IDOK){ + clist[i]=dlg.GetColor(); + } + +} + +BOOL CViewPref::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ScanPrefs(); + + m_d_color.SetCurSel(0); + m_d_dplotlist.SetCurSel(m_d_DensityPlot); + m_d_editlist.SetCurSel(m_d_EditAction); + m_d_vplotlist.SetCurSel(m_d_VectorPlot); + m_d_wstlist.SetCurSel(m_d_WeightingScheme); + + UpdateData(FALSE); + + return TRUE; +} + +void CViewPref::OnResetColors() +{ + if(AfxMessageBox("Reset all color preferences?",MB_OKCANCEL)==IDOK) + { + int i=0; + clist[i++]=dSelColor; + clist[i++]=dBackColor; + clist[i++]=dMeshColor; + clist[i++]=dBlockColor; + clist[i++]=dLineColor; + clist[i++]=dGridColor; + clist[i++]=dNodeColor; + clist[i++]=dRegionColor; + clist[i++]=dTextColor; + clist[i++]=dRealFluxLineColor; + clist[i++]=dImagFluxLineColor; + clist[i++]=dMaskLineColor; + clist[i++]=dNameColor; + clist[i++]=dRealVectorColor; + clist[i++]=dImagVectorColor; + clist[i++]=dColor00; + clist[i++]=dColor01; + clist[i++]=dColor02; + clist[i++]=dColor03; + clist[i++]=dColor04; + clist[i++]=dColor05; + clist[i++]=dColor06; + clist[i++]=dColor07; + clist[i++]=dColor08; + clist[i++]=dColor09; + clist[i++]=dColor10; + clist[i++]=dColor11; + clist[i++]=dColor12; + clist[i++]=dColor13; + clist[i++]=dColor14; + clist[i++]=dColor15; + clist[i++]=dColor16; + clist[i++]=dColor17; + clist[i++]=dColor18; + clist[i++]=dColor19; + clist[i++]=dGrey00; + clist[i++]=dGrey01; + clist[i++]=dGrey02; + clist[i++]=dGrey03; + clist[i++]=dGrey04; + clist[i++]=dGrey05; + clist[i++]=dGrey06; + clist[i++]=dGrey07; + clist[i++]=dGrey08; + clist[i++]=dGrey09; + clist[i++]=dGrey10; + clist[i++]=dGrey11; + clist[i++]=dGrey12; + clist[i++]=dGrey13; + clist[i++]=dGrey14; + clist[i++]=dGrey15; + clist[i++]=dGrey16; + clist[i++]=dGrey17; + clist[i++]=dGrey18; + clist[i++]=dGrey19; + } +} + +BOOL CViewPref::PreTranslateMessage(MSG* pMsg) +{ + // Pressing ENTER should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_RETURN, 0); + // Message needs no further processing + return TRUE; + } + + // Pressing ESC should reroute message to parent + if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE) ) + { + GetParent()->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0); + // Message needs no further processing + return TRUE; + } + + // Allow default handler otherwise + return CDialog::PreTranslateMessage(pMsg); +} + + +char* StripKey(char *c); + +void CViewPref::ScanPrefs() +{ + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "femmview.cfg"; + + fp=fopen(fname,"rt"); + if (fp!=NULL) + { + BOOL flag=FALSE; + char s[1024]; + char q[1024]; + char *v; + int cr,cg,cb; + + // parse the file + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + if( _strnicmp(q,"",20)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LineIntegralPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShiftH); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + SelColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MeshColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BlockColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NodeColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + NameColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + BackColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + TextColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagFluxLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + MaskLineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RealVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + ImagVectorColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + LineColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + RegionColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + GridColor=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Color19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey00=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey01=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey02=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey03=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey04=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey05=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey06=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey07=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey08=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey09=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey10=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey11=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey12=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey13=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey14=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey15=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey16=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey17=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey18=RGB(cr,cg,cb); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i %i %i",&cr,&cg,&cb); + Grey19=RGB(cr,cg,cb); + q[0]=NULL; + } + + + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_EditAction); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_DensityPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_VectorPlot); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GridFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_SnapFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_MeshFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_LegendFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",13)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_NumContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAr); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowAi); + q[0]=NULL; + } + + if( _strnicmp(q,"",10)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ShowMask); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_GreyContours); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PtsFlag); + q[0]=NULL; + } + + if( _strnicmp(q,"",8)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_Smooth); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_PlotPoints); + q[0]=NULL; + } + + if( _strnicmp(q,"",17)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_WeightingScheme); + q[0]=NULL; + } + + if( _strnicmp(q,"",15)==0) + { + v=StripKey(s); + sscanf(v,"%i",&m_d_ResetOnReload); + q[0]=NULL; + } + } + fclose(fp); + } + +} + +void WriteColor(char *cname, COLORREF c,FILE *fp); + +void CViewPref::WritePrefs() +{ + UpdateData(); + m_d_DensityPlot=m_d_dplotlist.GetCurSel(); + m_d_EditAction=m_d_editlist.GetCurSel(); + m_d_VectorPlot=m_d_vplotlist.GetCurSel(); + m_d_WeightingScheme=m_d_wstlist.GetCurSel(); + + FILE *fp; + CString fname = ((CFemmApp *)AfxGetApp())->GetExecutablePath() + "femmview.cfg"; + + fp=fopen(fname,"wt"); + if (fp!=NULL) + { + WriteColor("SelColor",SelColor,fp); + WriteColor("BkgndColor",BackColor,fp); + WriteColor("MeshColor",MeshColor,fp); + WriteColor("BlockColor",BlockColor,fp); + WriteColor("LineColor",LineColor,fp); + WriteColor("GridColor",GridColor,fp); + WriteColor("NodeColor",NodeColor,fp); + WriteColor("RegionColor",RegionColor,fp); + WriteColor("TextColor",TextColor,fp); + WriteColor("FluxRColor",RealFluxLineColor,fp); + WriteColor("FluxIColor",ImagFluxLineColor,fp); + WriteColor("MaskColor", MaskLineColor,fp); + WriteColor("VectorRColor", RealVectorColor,fp); + WriteColor("VectorIColor", ImagVectorColor,fp); + WriteColor("NameColor", NameColor,fp); + WriteColor("Color00",Color00,fp); + WriteColor("Color01",Color01,fp); + WriteColor("Color02",Color02,fp); + WriteColor("Color03",Color03,fp); + WriteColor("Color04",Color04,fp); + WriteColor("Color05",Color05,fp); + WriteColor("Color06",Color06,fp); + WriteColor("Color07",Color07,fp); + WriteColor("Color08",Color08,fp); + WriteColor("Color09",Color09,fp); + WriteColor("Color10",Color10,fp); + WriteColor("Color11",Color11,fp); + WriteColor("Color12",Color12,fp); + WriteColor("Color13",Color13,fp); + WriteColor("Color14",Color14,fp); + WriteColor("Color15",Color15,fp); + WriteColor("Color16",Color16,fp); + WriteColor("Color17",Color17,fp); + WriteColor("Color18",Color18,fp); + WriteColor("Color19",Color19,fp); + WriteColor("Grey00",Grey00,fp); + WriteColor("Grey01",Grey01,fp); + WriteColor("Grey02",Grey02,fp); + WriteColor("Grey03",Grey03,fp); + WriteColor("Grey04",Grey04,fp); + WriteColor("Grey05",Grey05,fp); + WriteColor("Grey06",Grey06,fp); + WriteColor("Grey07",Grey07,fp); + WriteColor("Grey08",Grey08,fp); + WriteColor("Grey09",Grey09,fp); + WriteColor("Grey10",Grey10,fp); + WriteColor("Grey11",Grey11,fp); + WriteColor("Grey12",Grey12,fp); + WriteColor("Grey13",Grey13,fp); + WriteColor("Grey14",Grey14,fp); + WriteColor("Grey15",Grey15,fp); + WriteColor("Grey16",Grey16,fp); + WriteColor("Grey17",Grey17,fp); + WriteColor("Grey18",Grey18,fp); + WriteColor("Grey19",Grey19,fp); + + fprintf(fp," = %i\n",m_d_EditAction); + fprintf(fp," = %i\n",m_d_DensityPlot); + fprintf(fp," = %i\n",m_d_VectorPlot); + fprintf(fp," = %i\n",m_d_GridFlag); + fprintf(fp," = %i\n",m_d_SnapFlag); + fprintf(fp," = %i\n",m_d_MeshFlag); + fprintf(fp," = %i\n",m_d_LegendFlag); + fprintf(fp," = %i\n",m_d_NumContours); + fprintf(fp," = %i\n",m_d_ShowAr); + fprintf(fp," = %i\n",m_d_ShowAi); + fprintf(fp," = %i\n",m_d_ShowMask); + fprintf(fp," = %i\n",m_d_GreyContours); + fprintf(fp," = %i\n",m_d_PtsFlag); + fprintf(fp," = %i\n",m_d_ResetOnReload); + fprintf(fp," = %i\n",m_d_Smooth); + fprintf(fp," = %i\n",m_d_PlotPoints); + fprintf(fp," = %i\n",m_d_LineIntegralPoints); + fprintf(fp," = %i\n",m_d_ShiftH); + fprintf(fp," = %i\n",m_d_WeightingScheme); + + fclose(fp); + } +} diff --git a/femm/viewpref.h b/femm/viewpref.h new file mode 100644 index 0000000..340fa97 --- /dev/null +++ b/femm/viewpref.h @@ -0,0 +1,72 @@ +// Pref.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +//CViewPref dialog + +class CViewPref : public CDialog +{ +// Construction +public: + CViewPref(CWnd* pParent = NULL); // standard constructor + ~CViewPref(); + + COLORREF *clist; + int m_d_EditAction; + int m_d_DensityPlot; + int m_d_VectorPlot; + int m_d_WeightingScheme; + + void ScanPrefs(); + void WritePrefs(); + +// Dialog Data + //{{AFX_DATA(CViewPref) + enum { IDD = IDD_VIEWPREF }; + CComboBox m_d_vplotlist; + CComboBox m_d_wstlist; + CComboBox m_d_dplotlist; + CComboBox m_d_editlist; + CComboBox m_d_color; + BOOL m_d_GreyContours; + BOOL m_d_LegendFlag; + int m_d_NumContours; + BOOL m_d_ResetOnReload; + BOOL m_d_GridFlag; + BOOL m_d_ShowAi; + BOOL m_d_ShowAr; + BOOL m_d_PtsFlag; + BOOL m_d_MeshFlag; + BOOL m_d_SnapFlag; + BOOL m_d_Smooth; + BOOL m_d_ShiftH; + int m_d_LineIntegralPoints; + int m_d_PlotPoints; + BOOL m_d_ShowMask; + BOOL m_d_shownames; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CViewPref) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CViewPref) + afx_msg void OnModBtn(); + virtual BOOL OnInitDialog(); + afx_msg void OnResetColors(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLuaEdit m_IDC_d_NumContours, m_IDC_d_LineIntegralPoints; + CLuaEdit m_IDC_d_PlotPoints; + +}; diff --git a/femm/writepoly.cpp b/femm/writepoly.cpp new file mode 100644 index 0000000..beb8c47 --- /dev/null +++ b/femm/writepoly.cpp @@ -0,0 +1,1805 @@ +// implementation of various incarnations of calls +// to triangle from the CFemmeDoc class + +#include "stdafx.h" +#include "femm.h" +#include "femmeDoc.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 "process.h" + +extern BOOL bLinehook; +extern lua_State *lua; +extern HANDLE hProc; + +#define toDegrees(x) ((Im(x)>=0) ? arg(x) : (arg(x) + 2.*PI))*(180./PI) + +double CFemmeDoc::LineLength(int i) +{ + return abs(nodelist[linelist[i].n0].CC()- + nodelist[linelist[i].n1].CC()); +} + + +BOOL CFemmeDoc::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) || + (lineproplist[k].BdryFormat==6) || + (lineproplist[k].BdryFormat==7)) + { + 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 CFemmeDoc::OnWritePoly() +{ + // if incremental permeability solution, we crib mesh from the previous problem. + // we can just bail out in that case. + if ((PrevSoln.GetLength()>0) && (PrevType>0)) return TRUE; + + 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",(int) 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 CFemmeDoc::FunnyOnWritePoly() +{ + // if incremental permeability solution, we crib mesh from the previous problem. + // we can just bail out in that case. + if ((PrevSoln.GetLength()>0) && (Frequency>0)) return TRUE; + + 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< CAirGapElement, CAirGapElement&> agelst; + CArray< CCommonPoint, CCommonPoint& >ptlst; + CNode node; + CSegment segm; + CPeriodicBoundary pbc; + CAirGapElement age; + CCommonPoint pt; + int bSmartMesh=theApp.session_SmartMesh; + if (bSmartMesh<0) bSmartMesh=SmartMesh; + + nodelst.RemoveAll(); + linelst.RemoveAll(); + pbclst.RemoveAll(); + agelst.RemoveAll(); + ptlst.RemoveAll(); + + UpdateUndo(); + + // calculate length used to kludge fine meshing near input node points + for (i=0,z=0;i") || (blocklist[i].BlockType=="")) j++; + fprintf(fp,"%i\n",j); + for(i=0,k=0;i") || (blocklist[i].BlockType=="")) + { + 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",(int) 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;j1) + { + age.BdryName=lineproplist[i].BdryName; + age.BdryFormat=lineproplist[i].BdryFormat-6; // 0 for pbc, 1 for apbc + age.InnerAngle=lineproplist[i].InnerAngle; + age.OuterAngle=lineproplist[i].OuterAngle; + agelst.Add(age); + } + } + } + + // make sure all Air Gap Element arcs have the same discretization + // for each arc associated with a particular Air Gap Element... + + // find out the total arc length and arc elements + // corresponding ot each lineproplist entry + for(i=0;iagelst[j].ro) agelst[j].ro=R; + if (R0) // if the AGE is actually in play + { + char kludge[32]; + double myMaxSideLength,altMaxSideLength; + + myMaxSideLength=agelst[i].totalArcLength/agelst[i].totalArcElements; + agelst[i].totalArcLength/=2; // this is now the angle spanned by the AGE + + // however, don't want long, skinny air gap elements. Impose some limits + // based on the inner and outer radii; + altMaxSideLength=(360./PI)*(agelst[i].ro-agelst[i].ri)/(agelst[i].ro+agelst[i].ri); + if (altMaxSideLength0) && (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 myVector; + myVector.RemoveAll(); + + z = (agelst[n].ro + agelst[n].ri)/2.; + + for(i=0;iz) // on outer radius + myVector.Add(arclist[i].n0); + else // on inner radius + myVector.InsertAt(0,arclist[i].n0); + + if(k==1){ + segm.n0=arclist[i].n0; + segm.n1=arclist[i].n1; + linelst.Add(segm); + } + else for(j=0;jz) // on outer radius + myVector.Add(l); + else // on inner radius + myVector.InsertAt(0,l); + } + 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); + + // insert newly created node + if (R>z) // on outer radius + myVector.Add(l); + else // on inner radius + myVector.InsertAt(0,l); + + } + } + } + + agelst[n].node=(int *)calloc(myVector.GetSize()+1,sizeof(int)); + agelst[n].node[0]=(int) myVector.GetSize(); + for(k=0;k") 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",(int) blocklist.GetSize()-j); + for(i=0,k=0;i0) && (blocklist[i].MaxArea InnerRing; + CArray OuterRing; + InnerRing.RemoveAll(); + OuterRing.RemoveAll(); + + n=agelst[k].node[0]/2; + dtta = agelst[k].totalArcLength/n; + n0=(int) round(360./dtta); // total elements in a 360deg annular ring; + n1=(int) round(360./agelst[k].totalArcLength); // number of copied segments + + // Should do some consistency checking here; + // totalArcLength*n1 should equal 360 + // no*dtta should equal 360 + // if antiperiodic, n1 should be an even number + // otherwise, throw error message, clean up, and return + + InnerRing.SetSize(n0); + OuterRing.SetSize(n0); + + // map each bdry point onto points on the ring; + int kk; + for(j=0,kk=0;j InnerRing[jj+1].w0) + { + qq=InnerRing[jj]; + InnerRing[jj]=InnerRing[jj+1]; + InnerRing[jj+1]=qq; + bDone=0; + } + } + if (bDone) break; + } + + for(int ii=0;ii OuterRing[jj+1].w0) + { + qq=OuterRing[jj]; + OuterRing[jj]=OuterRing[jj+1]; + OuterRing[jj+1]=qq; + bDone=0; + } + } + if (bDone) break; + } + + // print out AGE definition + fprintf(fp,"\"%s\"\n",agelst[k].BdryName); + fprintf(fp,"%i %.17g %.17g %.17g %.17g %.17g %.17g %.17g %i %.17g %.17g\n", + agelst[k].BdryFormat,agelst[k].InnerAngle,agelst[k].OuterAngle, + agelst[k].ri,agelst[k].ro,agelst[k].totalArcLength, + Re(agelst[k].agc),Im(agelst[k].agc),n, + InnerRing[0].w0,OuterRing[0].w0); + + for(i=0;i<=n;i++) + { + int p0,p1; + + p1=i; if(p1==n0) p1=0; + p0=p1-1; if(p0<0) p0=n0+p0; + + // ring points that bracket points in the annulus mesh + // and their sign, for the purposes of periodicity/antiperiodicity + fprintf(fp,"%i %g %i %g %i %g %i %g\n", + InnerRing[p0].n0, InnerRing[p0].w1, + InnerRing[p1].n0, InnerRing[p1].w1, + OuterRing[p0].n0, OuterRing[p0].w1, + OuterRing[p1].n0, OuterRing[p1].w1); + } + +/* + fprintf(fp,"%s\n",agelst[k].BdryName); + fprintf(fp,"%i %.17g %.17g %.17g %.17g %.17g %.17g %.17g %i\n", + agelst[k].BdryFormat,agelst[k].InnerAngle,agelst[k].OuterAngle, + agelst[k].ri,agelst[k].ro,agelst[k].totalArcLength, + Re(agelst[k].agc),Im(agelst[k].agc),n); + for(i=1;i<=n;i++) + fprintf(fp,"%i %i\n",agelst[k].node[i],agelst[k].node[n+i]); */ + + + + + } + + 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", + (const char *) BinDir,__min(MinAngle+MINANGLE_BUMP,MINANGLE_MAX), (const char *) rootname); + + StartupInfo.cb = sizeof(STARTUPINFO); + StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK; + StartupInfo.wShowWindow = SW_SHOWMINNOACTIVE; + 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 // MFC core and standard components +#include // MFC extensions +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows 95 Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#define MsgBox(s) AfxMessageBox(s) \ No newline at end of file diff --git a/femmplot/femmplot.cpp b/femmplot/femmplot.cpp new file mode 100644 index 0000000..3dce353 --- /dev/null +++ b/femmplot/femmplot.cpp @@ -0,0 +1,148 @@ +// femmplot.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "femmplot.h" + +#include "MainFrm.h" +#include "femmplotDoc.h" +#include "femmplotView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotApp + +BEGIN_MESSAGE_MAP(CFemmplotApp, CWinApp) + //{{AFX_MSG_MAP(CFemmplotApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotApp construction + +CFemmplotApp::CFemmplotApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CFemmplotApp object + +CFemmplotApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotApp initialization + +BOOL CFemmplotApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + LoadStdProfileSettings(0); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CFemmplotDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CFemmplotView)); + AddDocTemplate(pDocTemplate); + + // Enable DDE Execute open + EnableShellOpen(); + RegisterShellFileTypes(TRUE); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // Enable drag/drop open + m_pMainWnd->DragAcceptFiles(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CFemmplotApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotApp commands diff --git a/femmplot/femmplot.h b/femmplot/femmplot.h new file mode 100644 index 0000000..de714c7 --- /dev/null +++ b/femmplot/femmplot.h @@ -0,0 +1,38 @@ +// femmplot.h : main header file for the FEMMPLOT application +// + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotApp: +// See femmplot.cpp for the implementation of this class +// + +class CFemmplotApp : public CWinApp +{ +public: + CFemmplotApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmplotApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CFemmplotApp) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// diff --git a/femmplot/femmplotDoc.cpp b/femmplot/femmplotDoc.cpp new file mode 100644 index 0000000..1959b7a --- /dev/null +++ b/femmplot/femmplotDoc.cpp @@ -0,0 +1,168 @@ +// femmplotDoc.cpp : implementation of the CFemmplotDoc class +// + +#include "stdafx.h" +#include "femmplot.h" + +#include "femmplotDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc + +IMPLEMENT_DYNCREATE(CFemmplotDoc, CDocument) + +BEGIN_MESSAGE_MAP(CFemmplotDoc, CDocument) + //{{AFX_MSG_MAP(CFemmplotDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc construction/destruction + +CFemmplotDoc::CFemmplotDoc() +{ + // TODO: add one-time construction code here + hMetaPlot=NULL; + HasBoundingBox=FALSE; +} + +CFemmplotDoc::~CFemmplotDoc() +{ + DeleteEnhMetaFile(hMetaPlot); +} + +BOOL CFemmplotDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // clear out any old metafile; + DeleteEnhMetaFile(hMetaPlot); + HasBoundingBox=FALSE; + + // grab a new metafile from the clipboard; + GrabMetafile(); + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc serialization + +void CFemmplotDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc diagnostics + +#ifdef _DEBUG +void CFemmplotDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CFemmplotDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotDoc commands + +BOOL CFemmplotDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + if (!CDocument::OnOpenDocument(lpszPathName)) + return FALSE; + + // clear out any old metafile; + DeleteEnhMetaFile(hMetaPlot); + HasBoundingBox=FALSE; + HENHMETAFILE hMetaPlotFile = GetEnhMetaFile(lpszPathName); + if (hMetaPlotFile!=NULL){ + DWORD len =(DWORD) GetEnhMetaFileBits(hMetaPlotFile,NULL,NULL); + unsigned char *buff=(unsigned char *) malloc(len); + if(GetEnhMetaFileBits(hMetaPlotFile,len,buff)==0) + MsgBox("MetaFile not copied"); + hMetaPlot=SetEnhMetaFileBits(len,buff); + } + else MsgBox("Problem opening specified file"); + + DeleteEnhMetaFile(hMetaPlotFile); + + // TODO: Add your specialized creation code here + + return TRUE; +} + +BOOL CFemmplotDoc::OnSaveDocument(LPCTSTR lpszPathName) +{ + // TODO: Add your specialized code here and/or call the base class + BOOL flag=TRUE; + + HENHMETAFILE hMetaCopy=CopyEnhMetaFile(hMetaPlot,lpszPathName); + if (hMetaCopy==NULL){ + MsgBox("Problem writing file to disk"); + flag=FALSE; + } + DeleteEnhMetaFile(hMetaCopy); + + return flag; // CDocument::OnSaveDocument(lpszPathName); +} + +BOOL CFemmplotDoc::GrabMetafile() +{ + if (IsClipboardFormatAvailable(CF_ENHMETAFILE)==FALSE){ + hMetaPlot=NULL; + return FALSE; + + } + if (OpenClipboard(NULL)==FALSE) + MsgBox("Cannot access the Clipboard"); + else{ + HENHMETAFILE hMetaClip = (HENHMETAFILE) GetClipboardData(CF_ENHMETAFILE); + HGLOBAL hBound = (HGLOBAL) GetClipboardData(CF_TEXT); + if(hMetaClip==NULL) + { + MsgBox("Couldn't GetClipboardData"); + } + else{ + DWORD len =(DWORD) GetEnhMetaFileBits(hMetaClip,NULL,NULL); + unsigned char *buff=(unsigned char *) malloc(len); + if(GetEnhMetaFileBits(hMetaClip,len,buff)==0) + MsgBox("MetaFile not copied"); + hMetaPlot=SetEnhMetaFileBits(len,buff); + if(hBound!=NULL){ + sscanf((char *) hBound,"%lf %lf %lf %lf", + &bb_left,&bb_bottom,&bb_right,&bb_top); + HasBoundingBox=TRUE; + } + EmptyClipboard(); + } + + CloseClipboard(); + } + + return TRUE; +} + diff --git a/femmplot/femmplotDoc.h b/femmplot/femmplotDoc.h new file mode 100644 index 0000000..e1b100a --- /dev/null +++ b/femmplot/femmplotDoc.h @@ -0,0 +1,51 @@ +// femmplotDoc.h : interface of the CFemmplotDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CFemmplotDoc : public CDocument +{ +protected: // create from serialization only + CFemmplotDoc(); + DECLARE_DYNCREATE(CFemmplotDoc) + +// Attributes +public: + HENHMETAFILE hMetaPlot; + double bb_top,bb_bottom,bb_left,bb_right; + BOOL HasBoundingBox; + +// Operations +public: + + BOOL CFemmplotDoc::GrabMetafile(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmplotDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmplotDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmplotDoc) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/femmplot/femmplotView.cpp b/femmplot/femmplotView.cpp new file mode 100644 index 0000000..0ee5c0f --- /dev/null +++ b/femmplot/femmplotView.cpp @@ -0,0 +1,216 @@ +// femmplotView.cpp : implementation of the CFemmplotView class +// + +#include "stdafx.h" +#include "femmplot.h" +#include + +#include "femmplotDoc.h" +#include "femmplotView.h" +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView + +IMPLEMENT_DYNCREATE(CFemmplotView, CView) + +BEGIN_MESSAGE_MAP(CFemmplotView, CView) + //{{AFX_MSG_MAP(CFemmplotView) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_WM_MOUSEMOVE() + ON_COMMAND(ID_EDIT_COPY_AS_METAFILE, OnEditCopyAsMetafile) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView construction/destruction + +CFemmplotView::CFemmplotView() +{ + // TODO: add construction code here + +} + +CFemmplotView::~CFemmplotView() +{ +} + +BOOL CFemmplotView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView drawing + +void CFemmplotView::OnDraw(CDC* pDC) +{ + CFemmplotDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + RECT r; + GetClientRect(&r); + + if (pDC->IsPrinting()!=FALSE){ + CSize sz; + RECT cr; + int wd=pDC->GetDeviceCaps( HORZRES ); + int hd=pDC->GetDeviceCaps( VERTRES ); + int ww=r.right-r.left; + int hw=r.bottom-r.top; + int x=wd/ww; + int y=hd/hw; + if (ySetMapMode(MM_ISOTROPIC); + sz.cx=ww; sz.cy=hw; + pDC->SetWindowExt(sz); + sz.cx=x*ww; sz.cy=x*hw; + pDC->SetViewportExt(sz); + pDC->GetClipBox(&cr); + pDC->IntersectClipRect(&r); + } + + r.bottom--; + r.right--; + pDC->PlayMetaFile(pDoc->hMetaPlot,&r); + + + // TODO: add draw code for native data here +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView printing + +BOOL CFemmplotView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CFemmplotView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CFemmplotView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView diagnostics + +#ifdef _DEBUG +void CFemmplotView::AssertValid() const +{ + CView::AssertValid(); +} + +void CFemmplotView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CFemmplotDoc* CFemmplotView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFemmplotDoc))); + return (CFemmplotDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CFemmplotView message handlers + +void CFemmplotView::OnEditCopyAsMetafile() +{ + // puts a metafile drawing of the screen on the clipboard + CMetaFileDC Meta; + RECT r; + CRgn R; + + Meta.CreateEnhanced(NULL,NULL,NULL,NULL); + GetClientRect(&r); + R.CreateRectRgnIndirect(&r); + Meta.SelectClipRgn(&R); + OnDraw(&Meta); + HENHMETAFILE hMeta=Meta.CloseEnhanced(); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE,hMeta); + CloseClipboard(); + +} + +void CFemmplotView::OnEditCopy() +{ + // puts a bitmap of the screen on the clipboard + RECT r; + CDC tempDC; + CBitmap bitmap; + CDC *pDC=GetDC(); + + GetClientRect(&r); + tempDC.CreateCompatibleDC(pDC); + bitmap.CreateCompatibleBitmap(pDC, r.right, r.bottom); + tempDC.SelectObject(&bitmap); + + tempDC.BitBlt(0, 0, r.right, r.bottom, pDC, 0, 0, SRCCOPY); + + OpenClipboard(); + EmptyClipboard(); + SetClipboardData(CF_BITMAP, HBITMAP(bitmap)); + CloseClipboard(); +} +void CFemmplotView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + // Grab pointer to the Status Bar + CMainFrame *MFrm; + MFrm=(CMainFrame *)GetParentFrame(); + if (MFrm==NULL) MsgBox("Null GetParentFrame"); + else StatBar=(CStatusBar *)MFrm->GetMessageBar(); + +} + +void CFemmplotView::OnMouseMove(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + static char statmsg[256]; + double x,y,ww,wh,pw,ph,ox,oy; + RECT r; + CFemmplotDoc *pDoc=GetDocument(); + + if(pDoc->HasBoundingBox==FALSE) return; + + // get size of current client area and convert mouse position into + // position on the actual drawing. + GetClientRect(&r); + ww=fabs((double) (r.right-r.left))+1.; + wh=fabs((double) (r.top-r.bottom))+1.; + pw=pDoc->bb_right-pDoc->bb_left; + ph=pDoc->bb_top-pDoc->bb_bottom; + ox=pDoc->bb_left; + oy=pDoc->bb_bottom; + + x=((double) point.x)*pw/ww + ox; + y=((double) (r.bottom-point.y-1))*ph/wh+oy; + + sprintf(statmsg,"(x=%g,y=%g)",x,y); + StatBar->SetPaneText(0,statmsg,TRUE); + + CView::OnMouseMove(nFlags, point); +} diff --git a/femmplot/femmplotView.h b/femmplot/femmplotView.h new file mode 100644 index 0000000..738fc4d --- /dev/null +++ b/femmplot/femmplotView.h @@ -0,0 +1,57 @@ +// femmplotView.h : interface of the CFemmplotView class +// +///////////////////////////////////////////////////////////////////////////// + +class CFemmplotView : public CView +{ +protected: // create from serialization only + CFemmplotView(); + DECLARE_DYNCREATE(CFemmplotView) + +// Attributes +public: + CStatusBar *StatBar; + CFemmplotDoc* GetDocument(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFemmplotView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFemmplotView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CFemmplotView) + afx_msg void OnEditCopy(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnEditCopyAsMetafile(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in femmplotView.cpp +inline CFemmplotDoc* CFemmplotView::GetDocument() + { return (CFemmplotDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/femmplot/res/femmplot.ico b/femmplot/res/femmplot.ico new file mode 100644 index 0000000..5c6c8b0 Binary files /dev/null and b/femmplot/res/femmplot.ico differ diff --git a/femmplot/res/femmplotDoc.ico b/femmplot/res/femmplotDoc.ico new file mode 100644 index 0000000..d7238b2 Binary files /dev/null and b/femmplot/res/femmplotDoc.ico differ diff --git a/fkn/StdAfx.h b/fkn/StdAfx.h new file mode 100644 index 0000000..3fb652a --- /dev/null +++ b/fkn/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h: portable shim pulling in compat/afx.h for BOOL, CString, and stdlib basics. +#pragma once + +#define _CRT_SECURE_NO_WARNINGS +#include + +int MsgBox(const char* sz, ...); +int MsgBox(const std::string& s); diff --git a/fkn/complex.cpp b/fkn/complex.cpp new file mode 100644 index 0000000..ad16ec6 --- /dev/null +++ b/fkn/complex.cpp @@ -0,0 +1,624 @@ +#include +#include "math.h" +#include "stdio.h" +#include "complex.h" + +CComplex::CComplex(double x) +{ + re=x; im=0.; +} + +CComplex::CComplex(int x) +{ + re=(double) x; + im=0.; +} + +CComplex::CComplex() +{ + re=0.; im=0.; +} + +CComplex::CComplex(double x, double y) +{ + re=x; im=y; +} + +CComplex CComplex::Sqrt() +{ + double w,z; + CComplex y; + + if((re==0) && (im==0)) w=0; + else if(fabs(re)>fabs(im)){ + z=im/re; + w=sqrt(fabs(re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=re/im; + w=sqrt(fabs(im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(re>=0){ + y.re=w; + y.im=im/(2.*w); + return y; + } + + if(im>=0){ + y.re=fabs(im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(im)/(2.*w); + y.im= (-w); + return y; +} + +CComplex CComplex::Conj() +{ + return CComplex(re,-im); +} + +double CComplex::Abs() +{ + if ((re==0) && (im==0)) return 0.; + + if (fabs(re)>fabs(im)) + return fabs(re)*sqrt(1.+(im/re)*(im/re)); + else + return fabs(im)*sqrt(1.+(re/im)*(re/im)); +} + +double CComplex::Arg() +{ + if ((re==0) && (im==0)) return 0.; + + return atan2(im,re); +} + +CComplex CComplex::Inv() +{ + double c; + CComplex z; + + if(fabs(re)>fabs(im)) + { + c=im/re; + z.re=1./(re*(1.+c*c)); + z.im=(-c)*z.re; + } + else{ + c=re/im; + z.im=(-1.)/(im*(1.+c*c)); + z.re=(-c)*z.im; + } + + return z; +} + +double CComplex::Re() +{ + return re; +} + +double CComplex::Im() +{ + return im; +} + +void CComplex::Set(double x, double y) +{ + re=x; im=y; +} + +char* CComplex::ToString(char *s) +{ + if (im<0) + sprintf(s,"%.3e - j %.3e",re,fabs(im)); + else + sprintf(s,"%.3e + j %.3e",re,im); + return s; +} + +//******* Addition *************************************************** + +CComplex CComplex::operator+( const CComplex& z ) +{ + return CComplex(re+z.re,im+z.im); +}; + +CComplex CComplex::operator+( int z ) +{ + return CComplex(re+((double) z),im); +}; + +CComplex CComplex::operator+( double z ) +{ + return CComplex(re+z,im); +}; + +void CComplex::operator+=( const CComplex& z) +{ + re+=z.re; + im+=z.im; +}; + +void CComplex::operator+=( double z ) +{ + re+=z; +}; + +void CComplex::operator+=( int z ) +{ + re+=(double) z; +}; + +CComplex operator+( int x, const CComplex& y ) +{ + return CComplex( ((double) x) + y.re, y.im ); +} + +CComplex operator+( double x, const CComplex& y ) +{ + return CComplex( x + y.re, y.im ); +} + +CComplex operator+( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re + y.re, x.im + y.im ); +} + + +//******* Subtraction *************************************************** +CComplex CComplex::operator-() +{ + return CComplex(-re,-im); +} + +CComplex CComplex::operator-( const CComplex& z) +{ + return CComplex(re-z.re,im-z.im); +}; + +CComplex CComplex::operator-( int z ) +{ + return CComplex(re-((double) z),im); +}; + +CComplex CComplex::operator-( double z ) +{ + return CComplex(re-z,im); +}; + +void CComplex::operator-=( const CComplex& z) +{ + re-=z.re; + im-=z.im; +}; + +void CComplex::operator-=( double z ) +{ + re-=z; +}; + +void CComplex::operator-=( int z ) +{ + re-=(double) z; +}; + +CComplex operator-( int x, const CComplex& y ) +{ + return CComplex( ((double) x) - y.re, - y.im ); +} + +CComplex operator-( double x, const CComplex& y ) +{ + return CComplex( x - y.re, - y.im ); +} + +CComplex operator-( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re - y.re, x.im - y.im ); +} + +CComplex operator-( const CComplex& y ) +{ + return CComplex( -y.re,-y.im ); +} +//******* Multiplication *************************************************** + +CComplex CComplex::operator*( const CComplex& z) +{ + return CComplex(re*z.re - im*z.im,re*z.im + im*z.re); +}; + +CComplex CComplex::operator*( int z ) +{ + return CComplex( re*((double) z),im*((double) z) ); +}; + +CComplex CComplex::operator*( double z ) +{ + return CComplex(re*z,im*z); +}; + +void CComplex::operator*=( const CComplex& z) +{ + CComplex x(re*z.re - im*z.im,re*z.im + im*z.re); + re=x.re; im=x.im; +}; + +void CComplex::operator*=( double z ) +{ + re*=z; im*=z; +}; + +void CComplex::operator*=( int z ) +{ + re*=(double) z; + im*=(double) z; +}; + +CComplex operator*( int x, const CComplex& y ) +{ + return CComplex( ((double) x) * y.re, ((double) x)*y.im ); +} + +CComplex operator*( double x, const CComplex& y ) +{ + return CComplex( x*y.re, x*y.im ); +} + +CComplex operator*( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re*y.re-x.im*y.im, x.re*y.im+x.im*y.re ); +} + +//******* Division *************************************************** + +CComplex CComplex::operator/( const CComplex& z) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return *this * y; +}; + + +CComplex CComplex::operator/( int z ) +{ + return CComplex(re/((double) z),im/((double) z)); +}; + +CComplex CComplex::operator/( double z ) +{ + return CComplex(re/z,im/z); +}; + +void CComplex::operator/=( const CComplex& z) +{ + *this=*this/z; +}; + +void CComplex::operator/=( double z ) +{ + re/=z; + im/=z; +}; + +void CComplex::operator/=( int z ) +{ + re/=(double) z; + im/=(double) z; +}; + +CComplex operator/( int x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*=(double) x; + y.im*=(double) x; + + return y; +} + +CComplex operator/( double x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*= x; + y.im*= x; + + return y; +} + +CComplex operator/( const CComplex& x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return x*y; +} + +//****** Equals definitions ******************************** + +void CComplex::operator=(double z) +{ + re=z; + im=0; +} + +void CComplex::operator=(int z) +{ + re=(double) z; + im=0; + +} + +//***** Tests *********************************************** +bool CComplex::operator==( const CComplex& z){ + if ((z.im==im) && (z.re==re)) return true; + return false; +} + +bool CComplex::operator==(double z){ + if ((z==re) && (im==0)) return true; + return false; +} + +bool CComplex::operator==(int z){ + if ((re==(double) z) && (im==0)) return true; + return false; +} + +bool CComplex::operator!=( const CComplex& z){ + if ((z.re==re) && (z.im==im)) return false; + return true; +} + +bool CComplex::operator!=(double z){ + if ((re!=z) || (im!=0)) return true; + return false; +} + +bool CComplex::operator!=(int z){ + if ((re!=(double) z) || (im!=0)) return true; + return false; +} + +//***** Useful functions ************************************ + +CComplex conj( const CComplex& x) +{ + return CComplex(x.re,-x.im); +} + +CComplex exp( const CComplex& x) +{ + CComplex y; + + y.re=cos(x.im)*exp(x.re); + y.im=sin(x.im)*exp(x.re); + + return y; +} + +CComplex sqrt( const CComplex& x) +{ + double w,z; + CComplex y; + + if((x.re==0) && (x.im==0)) w=0; + else if(fabs(x.re)>fabs(x.im)){ + z=x.im/x.re; + w=sqrt(fabs(x.re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=x.re/x.im; + w=sqrt(fabs(x.im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(x.re>=0){ + y.re=w; + y.im=x.im/(2.*w); + return y; + } + + if(x.im>=0){ + y.re=fabs(x.im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(x.im)/(2.*w); + y.im= (-w); + + return y; +} + +CComplex tanh( const CComplex& x) +{ + CComplex y; + + if (x.re>0){ + y=(1-exp(-2*x))/(1+exp(-2*x)); + } + else{ + y=(exp(2*x)-1)/(exp(2*x)+1); + } + + return y; +} + +CComplex sinh( const CComplex& x) +{ + return (exp(x)-exp(-x))/2; +} + +CComplex cosh( const CComplex& x) +{ + return (exp(x)+exp(-x))/2; +} + + +CComplex cos( const CComplex& x) +{ + return (exp(I*x)+exp(-I*x))/2; +} + +CComplex acos( const CComplex& x) +{ + return PI/2. - arg(I*x + sqrt(1 - x*x)) + I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex sin( const CComplex& x) +{ + return (exp(I*x)-exp(-I*x))/(2*I); +} + +CComplex asin( const CComplex& x) +{ + return arg(I*x + sqrt(1 - x*x)) - I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex tan( const CComplex& x) +{ + return sin(x)/cos(x); +} + +CComplex atan( const CComplex& x) +{ + return (arg(1+I*x) - arg(1-I*x) - I*(log(abs(1+I*x)/abs(1-I*x))))/ 2; +} + +double abs( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + if (fabs(x.re)>fabs(x.im)) + return fabs(x.re)*sqrt(1.+(x.im/x.re)*(x.im/x.re)); + else + return fabs(x.im)*sqrt(1.+(x.re/x.im)*(x.re/x.im)); +} + +double arg( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + return atan2(x.im,x.re); +} + +CComplex log( const CComplex& x) +{ + CComplex y; + + y.im=arg(x); + y.re=log(abs(x)); + + return y; +} + +CComplex pow( const CComplex& x, double y) +{ + return exp(y*log(x)); +} + +CComplex pow( const CComplex& x, int y) +{ + if (y==0) return CComplex(1,0); + + int i; + CComplex z; + + if (y>0){ + z=x; + for(i=1;i( const CComplex& z); + bool operator>( double z); + bool operator>( int z); + + bool operator>=( const CComplex& z); + bool operator>=( double z); + bool operator>=( int z); + + + private: + +}; + +// useful functions... +#define I CComplex(0,1) +double Re( const CComplex& a); +double Im( const CComplex& a); +double abs( const CComplex& x ); +double absq( const CComplex& x ); +double arg( const CComplex& x ); +CComplex conj( const CComplex& x); +CComplex exp( const CComplex& x ); +CComplex sqrt( const CComplex& x ); +CComplex tanh( const CComplex& x ); +CComplex sinh( const CComplex& x ); +CComplex cosh( const CComplex& x ); +CComplex cos( const CComplex& x ); +CComplex acos( const CComplex& x ); +CComplex sin( const CComplex& x ); +CComplex asin( const CComplex& x ); +CComplex tan( const CComplex& x ); +CComplex atan( const CComplex& x ); +CComplex atan2( const CComplex& y, const CComplex& x); +CComplex log( const CComplex& x ); +CComplex pow( const CComplex& x, int y); +CComplex pow( const CComplex& x, double y); +CComplex pow( const CComplex& x, const CComplex& y); +CComplex Chop( const CComplex& a, double tol=1.e-12); + + + + +#endif // CCOMPLEX check \ No newline at end of file diff --git a/fkn/cspars.cpp b/fkn/cspars.cpp new file mode 100644 index 0000000..561de88 --- /dev/null +++ b/fkn/cspars.cpp @@ -0,0 +1,950 @@ +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "spars.h" + +#define MAXITER 1000000 +#define KLUDGE +#define nrm(X) sqrt(Re(ConjDot(X,X))) + +CComplexEntry::CComplexEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigComplexLinProb::CBigComplexLinProb() +{ + n=0; +} + +CBigComplexLinProb::~CBigComplexLinProb() +{ + if (n==0) return; + + int i; + CComplexEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + free(uu); free(vv); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + free(M); + + if (bNewton) + { + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + free(Mh); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + free(Ma); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + free(Ms); + } +} + +int CBigComplexLinProb::Create(int d, int bw, int nodes) +{ + int i; + + bdw=bw; + NumNodes=nodes; + b=(CComplex *)calloc(d,sizeof(CComplex)); + V=(CComplex *)calloc(d,sizeof(CComplex)); + P=(CComplex *)calloc(d,sizeof(CComplex)); + R=(CComplex *)calloc(d,sizeof(CComplex)); + U=(CComplex *)calloc(d,sizeof(CComplex)); + Z=(CComplex *)calloc(d,sizeof(CComplex)); + uu=(CComplex *)calloc(d,sizeof(CComplex)); + vv=(CComplex *)calloc(d,sizeof(CComplex)); + n=d; + + M=(CComplexEntry **)calloc(d,sizeof(CComplexEntry *)); + for(i=0;ic = i; + } + + bNewton=FALSE; + + return 1; +} + +void CBigComplexLinProb::Put(CComplex v, int p, int q, int k) +{ + CComplexEntry *e,*l; + int i; + + if(q0) && (bNewton==FALSE)) + { + bNewton=TRUE; + + Mh=(CComplexEntry **)calloc(n,sizeof(CComplexEntry *)); + for(i=0;ic = i; + } + + Ma=(CComplexEntry **)calloc(n,sizeof(CComplexEntry *)); + for(i=0;ic = i; + } + + Ms=(CComplexEntry **)calloc(n,sizeof(CComplexEntry *)); + for(i=0;ic = i; + } + } + + switch(k) + { + case 1: + e=Mh[p]; + break; + case 2: + e=Ms[p]; + break; + case 3: + e=Ma[p]; + break; + default: + e=M[p]; + break; + } + + while((e->c < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CComplexEntry *m = new CComplexEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + + return; +} + +CComplex CBigComplexLinProb::Get(int p, int q, int k) +{ + CComplexEntry *e; + BOOL flip=FALSE; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) + { + if(flip) + { + if(k==1) return conj(e->x); // case where matrix is hermitian... + if(k==3) return -conj(e->x); // case where matrix is anti-hermitian... + } + + return e->x; + } + + // if no entry in the list, this entry must be zero... + return CComplex(0,0); +} + +void CBigComplexLinProb::AddTo(CComplex v, int p, int q) +{ + Put(Get(p,q)+v,p,q); +} + +void CBigComplexLinProb::MultA(CComplex *X, CComplex *Y, int k) +{ + int i; + CComplexEntry *e; + + for(i=0;ix*X[i]); + e=Mh[i]->next; + break; + case 2: + Y[i]+=(Ms[i]->x*X[i]); + e=Ms[i]->next; + break; + case 3: + Y[i]+=(Ma[i]->x*X[i]); + e=Ma[i]->next; + break; + default: + Y[i]+=(M[i]->x*X[i]); + e=M[i]->next; + break; + } + + while(e!=NULL) + { + Y[i]+=(e->x*X[e->c]); + if (k==1) + Y[e->c]+=(conj(e->x)*X[i]); // case in which the matrix is hermitian + else if (k==3) + Y[e->c]+=(-conj(e->x)*X[i]); // case in which the matrix is antihermitian + else + Y[e->c]+=(e->x*X[i]); // case in which the matrix is complex-symmetric + e=e->next; + } + } +} + +void CBigComplexLinProb::MultConjA(CComplex *X, CComplex *Y, int k) +{ + int i; + CComplexEntry *e; + + for(i=0;ix.Conj()*X[i]); + e=Mh[i]->next; + break; + case 2: + Y[i]+=(Ms[i]->x.Conj()*X[i]); + e=Ms[i]->next; + break; + case 3: + Y[i]+=(Ma[i]->x.Conj()*X[i]); + e=Ma[i]->next; + break; + default: + Y[i]+=(M[i]->x.Conj()*X[i]); + e=M[i]->next; + break; + } + while(e!=NULL) + { + Y[i]+=(e->x.Conj()*X[e->c]); + if (k==1) + Y[e->c]+=(e->x*X[i]); // case in which the matrix is hermitian + if (k==3) + Y[e->c]+=(-e->x*X[i]); // case in which the matrix is antihermitian + else + Y[e->c]+=(e->x.Conj()*X[i]); // case in which the matrix is complex-symmetric + e=e->next; + } + } +} + +void CBigComplexLinProb::MultAPPA(CComplex *X, CComplex *Y) +{ + int i; + MultA(X,Z); + MultPC(Z,Y); + for(i=0;ix; return; + + + // SSOR preconditioner + CComplex c; + CComplexEntry *e; + + c= LAMBDA*(2.-LAMBDA); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * LAMBDA; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * LAMBDA; + e=e->next; + } + Y[i]/= M[i]->x; + } + +} + +void CBigComplexLinProb::SetValue(int i, CComplex x) +{ + int k,fst,lst; + CComplex z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>NumNodes) lst=NumNodes; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } + + if (!bNewton) return; + + for(i=0;ix=0; + e=e->next; + } while(e!=NULL); + } + + for(i=0;ix=0; + e=e->next; + } while(e!=NULL); + } + + for(i=0;ix=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigComplexLinProb::AntiPeriodicity(int i, int j) +{ + int k,fst,lst,h; + CComplex v1,v2,c; + +#ifdef KLUDGE + int tmpbdw=bdw; + bdw=0; +#endif + + if (jNumNodes-1) lst=NumNodes-1; + } + + // contribution to A0 matrix + for(k=fst;kNumNodes-1) lst=NumNodes-1; + } + + for(k=fst;kx.re==0) && (M[i]->x.im==0)){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // Operate on RHS to scale for squared problem + MultPC(b,Z); + for(i=0;im_prog1.SetPos(5*prg1); + TheView->SetDlgItemText(IDC_FRAME1,"BiConjugate Gradient Solver"); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + + // form initial search direction; + MultPC(R,Z); + for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>Precision); + + return 1; +} + +// BiCGSTAB for solving N-R iterations +int CBigComplexLinProb::BiCGSTAB(int flag) +{ + double er,normb; + CComplex om,alf,rho1,rho2,bta; + CComplex *P2,*R2,*Z2,*t; + int i,j,k; + CString out; + + P2=(CComplex *)calloc(n,sizeof(CComplex)); + Z2=(CComplex *)calloc(n,sizeof(CComplex)); + R2=(CComplex *)calloc(n,sizeof(CComplex)); + t =(CComplex *)calloc(n,sizeof(CComplex)); + + // initialize progress bar; + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + TheView->SetDlgItemText(IDC_FRAME1,"BiCGSTAB Solver"); + + if (flag==FALSE) for(i=0;iSetDlgItemText(IDC_FRAME1,out); + } + prg2=(int) (20.*log10(er)/(log10(Precision))); + if(prg2>prg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + if (erSetDlgItemText(IDC_FRAME1,"Initializing Solver"); + if (PCGSQStart()==0) return 0; + } + + + // call the complex-symmetric solver + return PBCGSolve(2); +} diff --git a/fkn/cuthill.cpp b/fkn/cuthill.cpp new file mode 100644 index 0000000..ce19729 --- /dev/null +++ b/fkn/cuthill.cpp @@ -0,0 +1,279 @@ +// does Cuthill-McKee algorithm as described in Hoole; + +#include +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +#define muo 1.2566370614359173e-6 + +BOOL CFemmeDocCore::SortElements() +{ + // Comb Sort -- see http://en.wikipedia.org/wiki/Comb_sort + int *Score; + int i,j,k,gap; + CElement e; + + Score=(int*)calloc(NumEls,sizeof(int)); + + for(k=0;k 1) + { + gap=(gap*10)/13; + if ((gap==10) || (gap==9)) gap=11; + + } + + //a single "comb" over the input list + for(j=0,i=0;(j+gap)Score[j+gap]) + { + k=j+gap; + i=Score[k];Score[k]=Score[j];Score[j]=i; + e=meshele[k];meshele[k]=meshele[j];meshele[j]=e; + i=1; + } + } + }while((gap>1)&&(i>0)); + + + free(Score); + return TRUE; +} + +BOOL CFemmeDocCore::Cuthill() +{ + + FILE *fp; + int i,j,k,n0,n1,n; + int newwide,*newnum,**ocon; + int *numcon,*nxtnum; + CNode swap; + char infile[256]; + + // allocate storage + nxtnum=(int *)calloc(NumNodes,sizeof(int)); + newnum=(int *)calloc(NumNodes,sizeof(int)); + numcon=(int *)calloc(NumNodes,sizeof(int)); + ocon=(int **)calloc(NumNodes,sizeof(int *)); + // initialize node array; + for(i=0;inewwide) + { + newwide=abs(newnum[n0]-ocon[n0][i]); + } + } + + BandWidth=newwide+1; + // } + + // free up the variables that we needed during the routine.... + free(numcon); + free(nxtnum); + free(ocon[0]); + free(ocon); + + // new mapping remains in newnum; + // apply this mapping to elements first. + for(i=0;i +#include +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +///////////////////////////////////////////////////////////////////////////// +// CFemmeDocCore construction/destruction + +CFemmeDocCore::CFemmeDocCore() +{ + TheView = NULL; + Frequency = NULL; + Precision = NULL; + Relax = NULL; + LengthUnits = NULL; + ProblemType = NULL; + Coords = NULL; + BandWidth = NULL; + NumNodes = NULL; + NumEls = NULL; + NumBlockProps = NULL; + NumPBCs = NULL; + NumLineProps = NULL; + NumPointProps = NULL; + NumCircProps = NULL; + NumBlockLabels = NULL; + NumCircPropsOrig = NULL; + NumAGEs = NULL; + + meshnode = NULL; + meshele = NULL; + blockproplist = NULL; + lineproplist = NULL; + nodeproplist = NULL; + circproplist = NULL; + labellist = NULL; + pbclist = NULL; + PathName = NULL; + Aprev = NULL; + PrevType = 0; + extRo = extRi = extZo = NULL; + agelist = NULL; +} + +CFemmeDocCore::~CFemmeDocCore() +{ + // This space for rent. +} + +void CFemmeDocCore::CleanUp() +{ + int k; + + if (meshnode!=NULL) free(meshnode); + if (meshele!=NULL) free(meshele); + if (blockproplist!=NULL){ + for(k=0;kMid(n1+1,n2-n1-1); + + return (t+n2+1); +} + +BOOL CFemmeDocCore::LoadPrevA(CString myFile, double *V) +{ + // _Just_ load Aprev. This is needed for the case where we are restarting + // from an old solution. However, rotor angle might be slightly different + // in this case, so we need to reload all the mesh info to get the right + // mapping for any AGEs. Only Aprev needs to be reloaded then. + if (myFile.GetLength()==0) return FALSE; + + FILE *fp; + int i,k; + char s[1024],q[256]; + char *v; + double prevFreq=0; + int prevNumNodes; + + if ((fp=fopen(myFile,"rt"))==NULL){ +// MsgBox("Couldn't read from specified previous solution\n"); + return FALSE; + } + + // parse the file + k=0; + while (fgets(s,1024,fp)!=NULL) + { + sscanf(s,"%s",q); + + // Frequency of the problem + if( _strnicmp(q,"[frequency]",11)==0){ + v=StripKey(s); + sscanf(v,"%lf",&prevFreq); + q[0]=NULL; + } + + sscanf(s,"%s",q); + if( _strnicmp(q,"[solution]",11)==0){ + k=1; + break; + } + } + + // case where the solution is never found. + if (k==0) + { + fclose(fp); +// MsgBox("Couldn't read from specified previous solution\n"); + return FALSE; + } + + // case were previous solution is an AC problem. + // only DC previous solutions are presently supported + if (prevFreq!=0) + { + fclose(fp); +// MsgBox("Only DC previous solutions are presently supported\n"); + return FALSE; + } + + //////////////////////////// + // read in the previous solution!!! + /////////////////////////// + + // read in nodes + fgets(s,1024,fp); + sscanf(s,"%i",&prevNumNodes); + if (prevNumNodes!=NumNodes) + { + fclose(fp); +// MsgBox("%i != %i\n",NumNodes,prevNumNodes); + return FALSE; + } + + CNode node; + double c=PI*4.e-05; + for(i=0;i0) for(i=k-1;i>=0;i--){ + if(v[i]=='\"'){ + v[i]=0; + i=-1; + } + } + + PrevSoln=v; + q[0]=NULL; + } + + // Previous solution type + if (_strnicmp(q, "[prevtype]", 10) == 0) { + v = StripKey(s); + sscanf(v, "%i", &PrevType); + q[0] = NULL; + // 0 == None + // 1 == Incremental + // 2 == Frozen + // 3 == Restart + } + + // Point Properties + if( _strnicmp(q,"[pointprops]",12)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) nodeproplist=(CPointProp *)calloc(k,sizeof(CPointProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + PProp.Jr=0.; + PProp.Ji=0.; + PProp.Ar=0.; + PProp.Ai=0.; + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Ar); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Ai); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Jr); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.Ji); + q[0]=NULL; + } + + if( _strnicmp(q,"",9)==0){ + nodeproplist[NumPointProps]=PProp; + NumPointProps++; + q[0]=NULL; + } + + // Boundary Properties; + if( _strnicmp(q,"[bdryprops]",11)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) lineproplist=(CBoundaryProp *)calloc(k,sizeof(CBoundaryProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + 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.; + 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[NumLineProps]=BProp; + NumLineProps++; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"[blockprops]",12)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) blockproplist=(CMaterialProp *)calloc(k,sizeof(CMaterialProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0){ + MProp.mu_x=1.; + MProp.mu_y=1.; // permeabilities, relative + MProp.H_c=0.; // magnetization, A/m + MProp.Jr=0.; + MProp.Ji=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.; // hysteresis angle, degrees + MProp.Theta_hy=0.; // hysteresis angle, degrees + MProp.Theta_m=0.; // magnetization direction, degrees; + MProp.LamFill=1.; // lamination fill factor; + MProp.LamType=0; // type of lamination; + MProp.NStrands=0; + MProp.WireD=0; + MProp.BHpoints=0; + MProp.Bdata=NULL; + MProp.Hdata=NULL; + 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,"",10)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Theta_m); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Jr); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Ji); + 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); + q[0]=NULL; + } + + + if( _strnicmp(q,"",7)==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,"",7)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.WireD); + 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,"",10)==0){ + v=StripKey(s); + sscanf(v,"%i",&MProp.BHpoints); + if (MProp.BHpoints>0) + { + MProp.Hdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); + MProp.Bdata=(double *) calloc(MProp.BHpoints,sizeof(double)); + for(j=0;j",9)==0) + { + if (MProp.BHpoints>0) + { + if((PrevSoln.GetLength()>0) && (Frequency>0) && (PrevType>0)) + { + // first time through was just to get MuMax from AC curve... + CComplex *tmpHdata=(CComplex *)calloc(MProp.BHpoints,sizeof(CComplex)); + double *tmpBdata=(double *)calloc(MProp.BHpoints,sizeof(double)); + for(i=0;i0) circproplist=(CCircuit *)calloc(k,sizeof(CCircuit)); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0){ + CProp.dVolts_re=0.; + CProp.dVolts_im=0.; + CProp.Amps_re=0.; + CProp.Amps_im=0.; + CProp.CircType=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",17)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.dVolts_re); + q[0]=NULL; + } + + if( _strnicmp(q,"",17)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.dVolts_im); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.Amps_re); + q[0]=NULL; + } + + if( _strnicmp(q,"",14)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.Amps_im); + 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[NumCircProps]=CProp; + NumCircProps++; + q[0]=NULL; + } + + + // read in regional attributes + if(_strnicmp(q,"[numblocklabels]",13)==0){ + int i; + CString str; + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) labellist=(CBlockLabel *)calloc(k, sizeof(CBlockLabel)); + NumBlockLabels=k; + for(i=0;i0) + { + blk.MagDirFctn=(char *)calloc(str.GetLength()+1,sizeof(char)); + strcpy(blk.MagDirFctn,str); + } + blk.BlockType--; + blk.InCircuit--; + labellist[i]=blk; + } + q[0]=NULL; + } + } + + // need to set these so that valid BH data doesn't get wiped + // by the destructor of MProp + MProp.BHpoints=0; + MProp.Bdata=NULL; + MProp.Hdata=NULL; + + fclose(fp); + + if (NumCircProps==0) return TRUE; + + // Process circuits for serial connections. + // The program deals with serial "circuits" by making a separate + // circuit property for each block in the serial circuit. Then, + // each of this larger number of circuits can be processed using + // the previous approach which considered all circuits to be + // parallel connected. + + // first, make enough space for all possible circuits; + CCircuit *temp=(CCircuit *)calloc(NumCircProps+NumBlockLabels,sizeof(CCircuit)); + for(k=0;k=0){ + ic=labellist[k].InCircuit; + if(circproplist[ic].CircType==1) + { + ncirc=circproplist[ic]; + ncirc.OrigCirc=ic; + ncirc.Amps_im*=labellist[k].Turns; + ncirc.Amps_re*=labellist[k].Turns; + circproplist[NumCircProps]=ncirc; + labellist[k].InCircuit=NumCircProps; + NumCircProps++; + } + } + + // now, all "circuits" look like parallel circuits, so + for(k=0;k0) && (PrevType>0)) + { + // clear out mesh files + sprintf(infile,"%s.ele",PathName); DeleteFile(infile); + sprintf(infile,"%s.node",PathName); DeleteFile(infile); + sprintf(infile,"%s.pbc",PathName); DeleteFile(infile); + sprintf(infile,"%s.poly",PathName); DeleteFile(infile); + sprintf(infile,"%s.edge",PathName); DeleteFile(infile); + + return LoadPrev(); + } + + //read meshnodes; + sprintf(infile,"%s.node",PathName); + if((fp=fopen(infile,"rt"))==NULL){ + return FALSE; + } + fgets(s,1024,fp); + sscanf(s,"%i",&k); NumNodes=k; + + meshnode=(CNode *)calloc(k,sizeof(CNode)); + CNode node; + for(i=0;i1) j=j-2; else j=-1; + node.bc=j; + + // convert all lengths to centimeters (better conditioning this way...) + node.x*=c[LengthUnits]; + node.y*=c[LengthUnits]; + + meshnode[i]=node; + } + fclose(fp); + + //read in periodic boundary conditions; + sprintf(infile,"%s.pbc",PathName); + if((fp=fopen(infile,"rt"))==NULL){ + return FALSE; + } + fgets(s,1024,fp); + sscanf(s,"%i",&k); NumPBCs=k; + + if (k!=0) pbclist=(CCommonPoint *)calloc(k,sizeof(CCommonPoint)); + CCommonPoint pbc; + for(i=0;iTurns)>1) || (blockproplist[labellist[lbl].BlockType].LamType>2)) + bl->bIsWound=TRUE; + else + bl->bIsWound=FALSE; + + if ((Frequency==0) || (blockproplist[labellist[lbl].BlockType].LamType<3)) + { + bl->ProximityMu=1.; + return; + } + + // compute total area of associated block + for(i=0,atot=0;iCduct==0) + { + bl->ProximityMu=1; + return; + } + + wiretype=bp->LamType-3; + // wiretype = 0 for magnet wire + // wiretype = 1 for stranded but non-litz wire + // wiretype = 2 for litz wire + // wiretype = 3 for rectangular wire + // wiretype = 4 for 10% CCA + // wiretype = 5 for 15% CCA + + if(wiretype==3) // rectangular wire + { + W=2.*PI*Frequency; + d=bp->WireD*0.001; + fill=fabs(d*d*((double) bl->Turns)/atot); + dd=d/sqrt(fill); // foil pitch + fill=d/dd; // fill for purposes of equivalent foil analysis + o=bp->Cduct*(d/dd)*1.e6; // effective foil conductivity in S/m + + // effective permeability for the equivalent foil + ufd=muo*tanh(sqrt(I*W*o*muo)*d/2.)/(sqrt(I*W*o*muo)*d/2.); + bl->ProximityMu=(fill*ufd+(1.-fill)*muo)/muo; + return; + } + + // procedure for round wires; + switch (wiretype) + { + // wiretype = 1 for stranded but non-litz wire + case 1: + R=bp->WireD*0.0005*sqrt((double) bp->NStrands); + awire=PI*R*R*((double) bl->Turns); + break; + + // magnet wire, litz wire, 10% CCA, 15%CCA + default: + R=bp->WireD*0.0005; + awire=PI*R*R*((double) bp->NStrands)*((double) bl->Turns); + break; + } + fill=fabs(awire/atot); + + // preliminary definitions + o=bp->Cduct*1.e6; // conductivity in S/m + W=2.*PI*Frequency*o*muo*R*R/2.; // non-dimensionalized frequency + + // fit for frequency-dependent permeability... + switch (wiretype) + { + case 0: // magnet wire + case 1: // plain stranded + case 2: // litz + c1=0.7756067409818643 + fill*(0.6873854335408803 + fill*(0.06841584481674128 -0.07143732702512284*fill)); + c2=1.5*fill/c1; + break; + + case 4: // 10% CCA + c1=0.7270741505617485 + 0.8902950067721367*fill + 0.11894736885885195*fill*fill - 0.12247276254503957*fill*fill*fill; + c2=0.006784920229549677 + 1.8942880489198526*fill - 1.3631438759519217*fill*fill + 0.504431701685587*fill*fill*fill; + break; + + case 5: // 15% CCA + c1=0.7486913529860821 + 0.9042845510838825*fill + 0.1361040321433224*fill*fill - 0.10652380745682069*fill*fill*fill; + c2=0.006790468527313965 + 1.8945509985370095*fill - 1.3643501010185972*fill*fill + 0.5036765577982594*fill*fill*fill; + break; + } + + ufd=c2*(tanh(sqrt(c1*I*W))/sqrt(c1*I*W))+(1.-c2); // relative frequency-dependent permeability + bl->ProximityMu=ufd; + + +} +/* +void CFemmeDocCore::GetFillFactor(int lbl) +{ + // Get the fill factor associated with a stranded and + // current-carrying region. For AC problems, also compute + // the apparent conductivity and permeability for use in + // post-processing the voltage. + + CMaterialProp* bp= &blockproplist[labellist[lbl].BlockType]; + CBlockLabel* bl= &labellist[lbl]; + double atot,awire,r,FillFactor; + int i,wiretype; + CComplex ufd; + double W=2.*PI*Frequency; + + if ((Frequency==0) || (blockproplist[labellist[lbl].BlockType].LamType<3)) + { + bl->ProximityMu=0; + return; + } + + wiretype=bp->LamType-3; + // wiretype = 0 for magnet wire + // wiretype = 1 for stranded but non-litz wire + // wiretype = 2 for litz wire + // wiretype = 3 for rectangular wire + r=bp->WireD*0.0005; + + for(i=0,atot=0;iNStrands); + awire*=((double) bl->Turns); + + if (atot==0) return; + FillFactor=fabs(awire/atot); + + double w,d,h,o,fill,dd; + + // if stranded but non-litz, use an effective wire radius that + // gives the same cross-section as total stranded area + if (wiretype==1) r*=sqrt((double) bp->NStrands); + + if (wiretype!=3){ + d=r*sqrt(3.); + h=PI/sqrt(3.)*r; + w=r*sqrt(PI/(2.*sqrt(3.)*FillFactor)); + dd=sqrt(3.)*w; + } + else{ + d=2.*r; + h=2.*r; + w=r/sqrt(FillFactor); + dd=2.*w; + } + o=bp->Cduct*(h/w)*5.e5; // conductivity in S/m + fill=d/dd; //fill for purposes of equivalent foil analysis + + // At this point, sanity-check the fill factor; + if (fill>1) + { + CString mymsg; + mymsg.Format("Block label at (%g,%g) has a fill factor",bl->x,bl->y); + mymsg += "greater than the theoretical maximum. Couldn't solve the problem."; + MsgBox(mymsg); + exit(5); + } + + // effective permeability for the equivalent foil. Note that this is + // the same equation as effective permeability of a lamination... + if (o!=0) ufd=muo*tanh(sqrt(I*W*o*muo)*d/2.)/(sqrt(I*W*o*muo)*d/2.); + else ufd=0; + + // relative complex permeability + bl->ProximityMu=(fill*ufd+(1.-fill)*muo)/muo; +} +*/ + +double CFemmeDocCore::ElmArea(int i) +{ + // returns element cross-section area in meter^2 + int j,n[3]; + double b0,b1,c0,c1; + + for(j=0;j<3;j++) n[j]=meshele[i].p[j]; + + b0=meshnode[n[1]].y - meshnode[n[2]].y; + b1=meshnode[n[2]].y - meshnode[n[0]].y; + c0=meshnode[n[2]].x - meshnode[n[1]].x; + c1=meshnode[n[0]].x - meshnode[n[2]].x; + return 0.0001*(b0*c1-b1*c0)/2.; + +} diff --git a/fkn/femmedoccore.h b/fkn/femmedoccore.h new file mode 100644 index 0000000..91518fc --- /dev/null +++ b/fkn/femmedoccore.h @@ -0,0 +1,92 @@ +// femmeDoc.h : interface of the CFemmeDoc class +// +///////////////////////////////////////////////////////////////////////////// +#define muo 1.2566370614359173e-6 +#define Golden 0.3819660112501051517954131656 + +class CFemmeDocCore +{ + + + +// Attributes +public: + + CFemmeDocCore(); + ~CFemmeDocCore(); + + // General problem attributes + double Frequency; + double Precision; + double Relax; + int LengthUnits; + int ACSolver; + BOOL ProblemType; + BOOL Coords; + CString PrevSoln; + int PrevType; + + // Vector containing previous solution for incremental permeability analysis + double *Aprev; + + // axisymmetric external region parameters + double extRo,extRi,extZo; + + CFknDlg *TheView; + + // CArrays containing the mesh information + int BandWidth; + CNode *meshnode; + CElement *meshele; + + int NumNodes; + int NumEls; + + // lists of properties + int NumBlockProps; + int NumPBCs; + int NumLineProps; + int NumPointProps; + int NumCircProps; + int NumBlockLabels; + int NumCircPropsOrig; + int NumAGEs; + + CMaterialProp *blockproplist; + CBoundaryProp *lineproplist; + CPointProp *nodeproplist; + CCircuit *circproplist; + CBlockLabel *labellist; + CCommonPoint *pbclist; + CAirGapElement *agelist; + // stuff usually kept track of by CDocument + char *PathName; + + +// Operations +public: + + BOOL LoadPrev(); + BOOL LoadPrevA(CString myFile, double *V); + BOOL LoadMesh(); + BOOL OnOpenDocument(); + BOOL Cuthill(); + BOOL SortElements(); + BOOL Static2D(CBigLinProb &L); + BOOL WriteStatic2D(CBigLinProb &L); + BOOL Harmonic2D(CBigComplexLinProb &L); + BOOL WriteHarmonic2D(CBigComplexLinProb &L); + BOOL StaticAxisymmetric(CBigLinProb &L); + BOOL HarmonicAxisymmetric(CBigComplexLinProb &L); + void GetPrevAxiB(int k, double &B1p, double &B2p); + void GetPrev2DB(int k, double &B1p, double &B2p); + void GetFillFactor(int lbl); + double ElmArea(int i); + void CleanUp(); + +}; + +///////////////////////////////////////////////////////////////////////////// + +double GetNewMu(double mu,int BHpoints, CComplex *BHdata,double muc,double B); +double Power(double x, int n); diff --git a/fkn/fkn.cpp b/fkn/fkn.cpp new file mode 100644 index 0000000..44863ee --- /dev/null +++ b/fkn/fkn.cpp @@ -0,0 +1,93 @@ +// fkn.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "fkn.h" +#include "fknDlg.h" +#include +#include "lua.h" + +extern void lua_baselibopen (lua_State *L); +extern void lua_iolibopen (lua_State *L); +extern void lua_strlibopen (lua_State *L); +extern void lua_mathlibopen (lua_State *L); +extern void lua_dblibopen (lua_State *L); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFknApp + +BEGIN_MESSAGE_MAP(CFknApp, CWinApp) + //{{AFX_MSG_MAP(CFknApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFknApp construction + +CFknApp::CFknApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CFknApp object + +CFknApp theApp; +lua_State *lua; // the main lua object + +///////////////////////////////////////////////////////////////////////////// +// CFknApp initialization + +BOOL CFknApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CFknDlg dlg; + m_pMainWnd = &dlg; + + // Initialize Lua + lua=lua_open(4096); + lua_baselibopen(lua); + lua_strlibopen(lua); + lua_mathlibopen(lua); + lua_iolibopen(lua); + + dlg.ComLine=m_lpCmdLine; + _beginthread( old_main, 0, (void *) &dlg ); + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + lua_close(lua); + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/fkn/fkn.h b/fkn/fkn.h new file mode 100644 index 0000000..44d9ea2 --- /dev/null +++ b/fkn/fkn.h @@ -0,0 +1,4 @@ +// solver entry point. +#pragma once + +void old_main(void *inptr); diff --git a/fkn/fknDlg.cpp b/fkn/fknDlg.cpp new file mode 100644 index 0000000..4449211 --- /dev/null +++ b/fkn/fknDlg.cpp @@ -0,0 +1,98 @@ +// fknDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "fkn.h" +#include "fknDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFknDlg dialog + +CFknDlg::CFknDlg(CWnd* pParent /*=NULL*/) + : CDialog(CFknDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFknDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CFknDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFknDlg) + DDX_Control(pDX, IDC_PROGRESS2, m_prog2); + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CFknDlg, CDialog) + //{{AFX_MSG_MAP(CFknDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFknDlg message handlers + +BOOL CFknDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + return FALSE; // return TRUE unless you set the focus to a control +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CFknDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CFknDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CFknDlg::OnOK() +{ +} + diff --git a/fkn/fknDlg.h b/fkn/fknDlg.h new file mode 100644 index 0000000..c61e49c --- /dev/null +++ b/fkn/fknDlg.h @@ -0,0 +1,20 @@ +// MFC-free CFknDlg with empty progress, label, and window-update calls. +#pragma once + +#include + +struct CProgressStub { void SetPos(int) {} }; + +class CFknDlg { +public: + CProgressStub m_prog1; + CProgressStub m_prog2; + void* m_hWnd = nullptr; + std::string ComLine; + void SetDlgItemText(int, const char*) {} + void SetWindowText(const char*) {} + void UpdateWindow() {} + int InvalidateRect(void* = nullptr, int = 1) { return 1; } +}; + +extern CFknDlg* TheView; diff --git a/fkn/fullmatrix.cpp b/fkn/fullmatrix.cpp new file mode 100644 index 0000000..37ca1d1 --- /dev/null +++ b/fkn/fullmatrix.cpp @@ -0,0 +1,96 @@ +#include +#include +#include"complex.h" +#include"fullmatrix.h" + +CFullMatrix::CFullMatrix() +{ + n=0; + M=NULL; + b=NULL; +} + +CFullMatrix::CFullMatrix(int d) +{ + n=0; + M=NULL; + b=NULL; + Create(d); +} + +CFullMatrix::~CFullMatrix() +{ + if(n==0) return; + + int i; + for(i=0;iabs(max)) + { + max=M[j][i]; + q=j; + } + if(max==0) return FALSE; + z=M[i];M[i]=M[q];M[q]=z; + f=b[i];b[i]=b[q];b[q]=f; + for(j=i+1;j=0;i--) + { + for(j=n-1,f=0;j>i;j--) + f+=M[i][j]*b[j]; + b[i]=(b[i]-f)/M[i][i]; + } + return TRUE; +} + diff --git a/fkn/fullmatrix.h b/fkn/fullmatrix.h new file mode 100644 index 0000000..33b999e --- /dev/null +++ b/fkn/fullmatrix.h @@ -0,0 +1,21 @@ + +class CFullMatrix{ + + public: + + // data members + CComplex **M; // Matrix on LHS + CComplex *b; // vector on RHS + int n; // dimension of the matrix + + // member functions + CFullMatrix(); + CFullMatrix(int d); + ~CFullMatrix(); + void Wipe(); + BOOL Create(int d); + BOOL GaussSolve(); + + private: + +}; diff --git a/fkn/lua.h b/fkn/lua.h new file mode 100644 index 0000000..6a841e1 --- /dev/null +++ b/fkn/lua.h @@ -0,0 +1,249 @@ +/* +** $Id: lua.h,v 1.79 2000/10/31 12:44:07 roberto Exp $ +** Lua - An Extensible Extension Language +** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil +** e-mail: lua@tecgraf.puc-rio.br +** www: http://www.tecgraf.puc-rio.br/lua/ +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include "complex.h" + +/* definition of `size_t' */ +#include + + +/* mark for all API functions */ +#ifndef LUA_API +#define LUA_API extern +#endif + + +#define LUA_VERSION "Lua 4.0" +#define LUA_COPYRIGHT "Copyright (C) 1994-2000 TeCGraf, PUC-Rio" +#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" + + +/* name of global variable with error handler */ +#define LUA_ERRORMESSAGE "_ERRORMESSAGE" + + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) +#define LUA_REFREGISTRY 0 + +/* pre-defined tags */ +#define LUA_ANYTAG (-1) +#define LUA_NOTAG (-2) + + +/* option for multiple returns in lua_call */ +#define LUA_MULTRET (-1) + + +/* minimum stack available for a C function */ +#define LUA_MINSTACK 20 + + +/* error codes for lua_do* */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + +/* +** types returned by `lua_type' +*/ +#define LUA_TNONE (-1) + +#define LUA_TUSERDATA 0 +#define LUA_TNIL 1 +#define LUA_TNUMBER 2 +#define LUA_TSTRING 3 +#define LUA_TTABLE 4 +#define LUA_TFUNCTION 5 + + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (int stacksize); +LUA_API void lua_close (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int index); +LUA_API void lua_pushvalue (lua_State *L, int index); +LUA_API void lua_remove (lua_State *L, int index); +LUA_API void lua_insert (lua_State *L, int index); +LUA_API int lua_stackspace (lua_State *L); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_type (lua_State *L, int index); +LUA_API const char *lua_typename (lua_State *L, int t); +LUA_API int lua_isnumber (lua_State *L, int index); +LUA_API int lua_isstring (lua_State *L, int index); +LUA_API int lua_iscfunction (lua_State *L, int index); +LUA_API int lua_tag (lua_State *L, int index); + +LUA_API int lua_equal (lua_State *L, int index1, int index2); +LUA_API int lua_lessthan (lua_State *L, int index1, int index2); + +LUA_API CComplex lua_tonumber (lua_State *L, int index); +LUA_API const char *lua_tostring (lua_State *L, int index); +LUA_API size_t lua_strlen (lua_State *L, int index); +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); +LUA_API void *lua_touserdata (lua_State *L, int index); +LUA_API const void *lua_topointer (lua_State *L, int index); + + +/* +** push functions (C -> stack) +*/ +LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushnumber (lua_State *L, CComplex n); +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); +LUA_API void lua_pushstring (lua_State *L, const char *s); +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushusertag (lua_State *L, void *u, int tag); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_getglobal (lua_State *L, const char *name); +LUA_API void lua_gettable (lua_State *L, int index); +LUA_API void lua_rawget (lua_State *L, int index); +LUA_API void lua_rawgeti (lua_State *L, int index, int n); +LUA_API void lua_getglobals (lua_State *L); +LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_getref (lua_State *L, int ref); +LUA_API void lua_newtable (lua_State *L); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_setglobal (lua_State *L, const char *name); +LUA_API void lua_settable (lua_State *L, int index); +LUA_API void lua_rawset (lua_State *L, int index); +LUA_API void lua_rawseti (lua_State *L, int index, int n); +LUA_API void lua_setglobals (lua_State *L); +LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_ref (lua_State *L, int lock); + + +/* +** "do" functions (run Lua code) +*/ +LUA_API int lua_call (lua_State *L, int nargs, int nresults); +LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults); +LUA_API int lua_dofile (lua_State *L, const char *filename); +LUA_API int lua_dostring (lua_State *L, const char *str); +LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name); + +/* +** Garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ +LUA_API int lua_newtag (lua_State *L); +LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); +LUA_API void lua_settag (lua_State *L, int tag); + +LUA_API void lua_error (lua_State *L, const char *s); + +LUA_API void lua_unref (lua_State *L, int ref); + +LUA_API int lua_next (lua_State *L, int index); +LUA_API int lua_getn (lua_State *L, int index); + +LUA_API void lua_concat (lua_State *L, int n); + +LUA_API void *lua_newuserdata (lua_State *L, size_t size); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) +#define lua_pushuserdata(L,u) lua_pushusertag(L, u, 0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) +#define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) + +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) + +#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) + +#endif + + + +/****************************************************************************** +* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, without written agreement and without license +* or royalty fees, to use, copy, modify, and distribute this software and its +* documentation for any purpose, including commercial applications, subject to +* the following conditions: +* +* - The above copyright notice and this permission notice shall appear in all +* copies or substantial portions of this software. +* +* - The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software in a +* product, an acknowledgment in the product documentation would be greatly +* appreciated (but it is not required). +* +* - Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* +* The authors specifically disclaim any warranties, including, but not limited +* to, the implied warranties of merchantability and fitness for a particular +* purpose. The software provided hereunder is on an "as is" basis, and the +* authors have no obligation to provide maintenance, support, updates, +* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the +* authors be held liable to any party for direct, indirect, special, +* incidental, or consequential damages arising out of the use of this software +* and its documentation. +* +* The Lua language and this implementation have been entirely designed and +* written by Waldemar Celes Filho, Roberto Ierusalimschy and +* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. +* +* This implementation contains no third-party code. +******************************************************************************/ + diff --git a/fkn/main.cpp b/fkn/main.cpp new file mode 100644 index 0000000..146f2d3 --- /dev/null +++ b/fkn/main.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "spars.h" +#include "mesh.h" +#include "FemmeDocCore.h" + +void old_main(void *inptr) +{ + CFknDlg *TheView; + CFemmeDocCore Doc; + char PathName[256]; + CFileDialog *fname_dia; + char outstr[1024]; + int i; + + TheView=(CFknDlg *) inptr; + + if (__argc<2){ + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "FEMM datafile (*.fem) | *.fem; *.FEM | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + MsgBox("No file name!"); + return; + } + + CString fname=fname_dia->GetPathName(); + fname=fname.Left(fname.GetLength()-4); + strcpy(PathName,fname); + delete[] fname_dia; + } + else strcpy(PathName,__argv[1]); + + Doc.PathName=PathName; + Doc.TheView=TheView; + + if (Doc.OnOpenDocument()!=TRUE){ + MsgBox("problem loading .fem file"); + exit(7); + } + + // load mesh + if (Doc.LoadMesh()!=TRUE){ + if (Doc.PrevSoln.GetLength()>0) MsgBox("problem loading mesh from previous solution"); + else MsgBox("problem loading mesh"); + exit(2); + } + + // label the dialog to report which problem is being solved + char PaneText[256]; + char *ProbName; + ProbName=PathName; + for(i=0;i< (int) strlen(PathName);i++) + if(PathName[i]=='\\') ProbName=PathName+i; + if (strlen(PathName)>0){ + ProbName++; + sprintf(PaneText,"%s - fkern",ProbName); + } + + while(!IsWindow(TheView->m_hWnd)) Sleep(1); + TheView->SetWindowText(PaneText); + + // renumber using Cuthill-McKee + // (renumbering not needed if using previous solution mesh) + if (Doc.PrevType==0) + { + TheView->SetDlgItemText(IDC_STATUSWINDOW,"renumbering nodes"); + if (Doc.Cuthill()!=TRUE){ + MsgBox("problem renumbering node points"); + exit(3); + } + } + + TheView->SetDlgItemText(IDC_STATUSWINDOW,"solving..."); + sprintf(outstr,"Problem Statistics:\n%i nodes\n%i elements\nPrecision: %3.2e\n", + Doc.NumNodes,Doc.NumEls,Doc.Precision); + TheView->SetDlgItemText(IDC_PROBSTATS,outstr); + + double mr=(8.*((double) Doc.NumNodes)*((double) Doc.BandWidth))/ 1.e06; + + if(Doc.Frequency==0){ + CBigLinProb L; + L.TheView=TheView; + L.Precision=Doc.Precision; + // initialize the problem, allocating the space required to solve it. + if (L.Create(Doc.NumNodes,Doc.BandWidth)==FALSE){ + MsgBox("couldn't allocate enough space for matrices"); + exit(4); + } + + // Create element matrices and solve the problem; + if (Doc.ProblemType==FALSE){ + if (Doc.Static2D(L)==FALSE){ + MsgBox("Couldn't solve the problem"); + exit(5); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Static 2-D problem solved"); + } + else{ + if (Doc.StaticAxisymmetric(L)==FALSE){ + MsgBox("Couldn't solve the problem"); + exit(5); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Static axisymmetric problem solved"); + } + + if (Doc.WriteStatic2D(L)==FALSE) + { + MsgBox("couldn't write results to disk"); + exit(6); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"results written to disk"); + } + + else{ + CBigComplexLinProb L; + L.TheView=TheView; + L.Precision=Doc.Precision; + + // initialize the problem, allocating the space required to solve it. + if (L.Create(Doc.NumNodes+Doc.NumCircProps,Doc.BandWidth,Doc.NumNodes)==FALSE){ + MsgBox("couldn't allocate enough space for matrices"); + exit(4); + } + + // Create element matrices and solve the problem; + if (Doc.ProblemType==FALSE){ + if (Doc.Harmonic2D(L)==FALSE){ + MsgBox("Couldn't solve the problem"); + exit(5); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Harmonic 2-D problem solved"); + } + else{ + if (Doc.HarmonicAxisymmetric(L)==FALSE){ + MsgBox("Couldn't solve the problem"); + exit(5); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Harmonic axisymmetric problem solved"); + } + + + if (Doc.WriteHarmonic2D(L)==FALSE) + { + MsgBox("couldn't write results to disk"); + exit(6); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"results written to disk."); + } + + Doc.CleanUp(); + + exit(0); +} diff --git a/fkn/matprop.cpp b/fkn/matprop.cpp new file mode 100644 index 0000000..e4e54bb --- /dev/null +++ b/fkn/matprop.cpp @@ -0,0 +1,587 @@ +#include +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "fullmatrix.h" +#include "FemmeDocCore.h" + +#define ElementsPerSkinDepth 10 + +CMaterialProp::~CMaterialProp() +{ + if (Bdata!=NULL) free(Bdata); + if (Hdata!=NULL) free(Hdata); + if (slope!=NULL) free(slope); +} + +CMaterialProp::CMaterialProp() +{ + slope=NULL; + Bdata=NULL; + Hdata=NULL; +} + +void CMaterialProp::GetSlopes() +{ + GetSlopes(0); +} + +void CMaterialProp::GetSlopes(double omega) +{ + if (BHpoints==0) return; // catch trivial case; + if (slope!=NULL) return; // already have computed the slopes; + + int i,k; + BOOL CurveOK=FALSE; + BOOL ProcessedLams=FALSE; + CFullMatrix L; + double l1,l2; + CComplex *hn; + double *bn; + CComplex mu; + + L.Create(BHpoints); + bn =(double *) calloc(BHpoints,sizeof(double)); + hn =(CComplex *)calloc(BHpoints,sizeof(CComplex)); + slope=(CComplex *)calloc(BHpoints,sizeof(CComplex)); + + + // strip off some info that we can use during the first + // nonlinear iteration; + mu_x = Bdata[1]/(muo*abs(Hdata[1])); + mu_y = mu_x; + Theta_hx=Theta_hn; + Theta_hy=Theta_hn; + + // first, we need to doctor the curve if the problem is + // being evaluated at a nonzero frequency. + if(omega>0) + { + // Make an effective B-H curve for harmonic problems. + // this one convolves B(H) where H is sinusoidal with + // a sine at the same frequency to get the effective + // amplitude of B + double munow,mumax=0; + for(i=1;imumax) mumax=munow; + } + + // apply complex permeability to approximate the + // effects of hysteresis. We will follow a kludge + // suggested by O'Kelly where hysteresis angle + // is proportional to permeability. This implies + // that loss goes with B^2 + for(i=1;i0) + { + u0=sqrt(u0); + X0=-(c1 + u0)/(2.*c2); + X1=(-c1 + u0)/(2.*c2); + } + + //now, see if we've struck gold! + if (((X0>=0.)&&(X0<=L))||((X1>=0.)&&(X1<=L))) + CurveOK=FALSE; + } + + if(CurveOK!=TRUE) //remedial action + { + // Smooth out input points + // to get rid of rapid transitions; + // Uses a 3-point moving average + for(i=1;i0) && (Lam_d!=0) && (Cduct!=0)) + { + // Calculate a new apparent b and h for each point on the + // curve to account for the laminations. + for(i=1;iBdata[BHpoints-1]) + return (Hdata[BHpoints-1] + slope[BHpoints-1]*(b-Bdata[BHpoints-1])); + + for(i=0;i=Bdata[i]) && (b<=Bdata[i+1])){ + l=(Bdata[i+1]-Bdata[i]); + z=(b-Bdata[i])/l; + z2=z*z; + h=(1.-3.*z2+2.*z2*z)*Hdata[i] + + z*(1.-2.*z+z2)*l*slope[i] + + z2*(3.-2.*z)*Hdata[i+1] + + z2*(z-1.)*l*slope[i+1]; + return h; + } + + return CComplex(0); +} + +CComplex CMaterialProp::GetdHdB(double B) +{ + double b,z,l; + CComplex h; + int i; + + b=fabs(B); + + if(BHpoints==0) return CComplex(b/(mu_x*muo)); + + if(b>Bdata[BHpoints-1]) + return slope[BHpoints-1]; + + for(i=0;i=Bdata[i]) && (b<=Bdata[i+1])){ + l=(Bdata[i+1]-Bdata[i]); + z=(b-Bdata[i])/l; + h=6.*z*(z-1.)*Hdata[i]/l + + (1.-4.*z+3.*z*z)*slope[i] + + 6.*z*(1.-z)*Hdata[i+1]/l + + z*(3.*z-2.)*slope[i+1]; + return h; + } + + return CComplex(0); +} + +CComplex CMaterialProp::Get_v(double B) +{ + if (B==0) return slope[0]; + + return (GetH(B)/B); +} + +CComplex CMaterialProp::Get_dvB2(double B) +{ + if (B==0) return 0; + + return 0.5*(GetdHdB(B)/(B*B) - GetH(B)/(B*B*B)); +} + +void CMaterialProp::GetBHProps(double B, double &v, double &dv) +{ + // version to use in the magnetostatic case in + // which we know that v and dv ought to be real-valued. + CComplex vc,dvc; + + GetBHProps(B,vc,dvc); + v =Re(vc); + dv=Re(dvc); +} + +void CMaterialProp::GetBHProps(double B, CComplex &v, CComplex &dv) +{ + double b,z,z2,l; + CComplex h,dh; + int i; + + b=fabs(B); + + if(BHpoints==0){ + v=mu_x; + dv=0; + return; + } + + if(b==0){ + v=slope[0]; + dv=0; + return; + } + + if(b>Bdata[BHpoints-1]){ + h=(Hdata[BHpoints-1] + slope[BHpoints-1]*(b-Bdata[BHpoints-1])); + dh=slope[BHpoints-1]; + v=h/b; + dv=0.5*(dh/(b*b) - h/(b*b*b)); + return; + } + + for(i=0;i=Bdata[i]) && (b<=Bdata[i+1])){ + l=(Bdata[i+1]-Bdata[i]); + z=(b-Bdata[i])/l; + z2=z*z; + h=(1.-3.*z2+2.*z2*z)*Hdata[i] + + z*(1.-2.*z+z2)*l*slope[i] + + z2*(3.-2.*z)*Hdata[i+1] + + z2*(z-1.)*l*slope[i+1]; + dh=6.*z*(z-1.)*Hdata[i]/l + + (1.-4.*z+3.*z*z)*slope[i] + + 6.*z*(1.-z)*Hdata[i+1]/l + + z*(3.*z-2.)*slope[i+1]; + v=h/b; + dv=0.5*(dh/(b*b) - h/(b*b*b)); + return; + } +} + +CComplex CMaterialProp::LaminatedBH(double w, int i) +{ + int k,n,iter=0; + CComplex *m0,*m1,*b,*x; + double L,o,d,ds,B,lastres,res; + double Relax=1; + CComplex mu,vo,vi,c,H; + CComplex Md,Mo; + BOOL Converged=FALSE; + res=0; + + // Base the required element spacing on the skin depth + // at the surface of the material + mu=Bdata[i]/Hdata[i]; + o=Cduct*1.e6; + d=(Lam_d*0.001)/2.; + ds=sqrt(2/(w*o*abs(mu))); + n= ElementsPerSkinDepth * ((int) ceil(d/ds)); + L=d/((double) n); + + x =(CComplex *)calloc(n+1,sizeof(CComplex)); + b =(CComplex *)calloc(n+1,sizeof(CComplex)); + m0=(CComplex *)calloc(n+1,sizeof(CComplex)); + m1=(CComplex *)calloc(n+1,sizeof(CComplex)); + + do{ + // make sure that the old stuff is wiped out; + for(k=0;k<=n;k++) + { + m0[k]=0; + m1[k]=0; + b[k] =0; + } + + // build matrix + for(k=0;k= 0; k--) + b[k] = (b[k] - m1[k]*b[k + 1])/m0[k]; + + iter++; + + lastres=res; + res=abs(b[n]-x[n])/d; + + if (res<1.e-8) Converged=TRUE; + + // Do the same relaxation scheme as is implemented + // in the solver to make sure that this effective + // lamination permeability calculation converges + if(iter>5) + { + if ((res>lastres) && (Relax>0.1)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + } + + for(k=0;k<=n;k++) x[k]=Relax*b[k]+(1.0-Relax)*x[k]; + + }while(Converged!=TRUE); + + mu = x[n]/(Hdata[i]*d); + + free(x ); + free(b ); + free(m0); + free(m1); + + return mu; +} + +// get incremental permeability of a nonlinear material for use in +// incremental permeability formulation about DC offset +void CMaterialProp::IncrementalPermeability(double B, double w, CComplex &mu1, CComplex &mu2) +{ + // B == flux density in Tesla + // w == frequency in rad/s + + double muinc,murel; + CComplex k; + double mu; + + // get incremental permeability of the DC material + // (i.e. incremental permeability at the offset) + muinc=1./(muo*Re(GetdHdB(B))); + murel=1./(muo*Re(Get_v(B))); + + // if material is not laminated, just apply hysteresis lag... + if ((Lam_d==0) || (LamFill==0)) + { + mu1=muinc*exp(-I*Theta_hn*DEG*muinc/MuMax); + mu2=murel*exp(-I*Theta_hn*DEG*murel/MuMax); + return; + } + + // crap. Need to make an equivalent permeability that rolls in the effects of laminated + // eddy currents, using the incremental permeability as the basis for creating the impedance. + // this can get annoying because we need to back out the iron portion of the permeability + // in the lamfill<1 case... + + + if (Cduct!=0) + { + CComplex deg45; deg45=1+I; + CComplex K,halflag; + double ds; + + // incremental permeability direction + mu = (muinc - (1.-LamFill))/LamFill; + halflag=exp(-I*Theta_hn*DEG*mu/(2.*MuMax)); + ds=sqrt(2./(0.4*PI*w*Cduct*mu)); + K=halflag*deg45*Lam_d*0.001/(2.*ds); + mu1=(LamFill*mu*tanh(K)/K + (1.- LamFill)); + + // normal permeability direction + mu = (murel - (1.-LamFill))/LamFill; + halflag=exp(-I*Theta_hn*DEG*mu/(2.*MuMax)); + ds=sqrt(2./(0.4*PI*w*Cduct*mu)); + K=halflag*deg45*Lam_d*0.001/(2.*ds); + mu2=(LamFill*mu*tanh(K)/K + (1.- LamFill)); + return; + } + else{ + // incremental permeability direction + mu = (muinc - (1.-LamFill))/LamFill; + mu1=(mu*exp(-I*Theta_hn*DEG*mu/MuMax)*LamFill + (1.-LamFill)); + + // normal permeability direction + mu = (murel - (1.-LamFill))/LamFill; + mu2=(mu*exp(-I*Theta_hn*DEG*mu/MuMax)*LamFill + (1.-LamFill)); + return; + } +} + +void CMaterialProp::IncrementalPermeability(double B, double &mu1, double &mu2) +{ + // B == flux density in Tesla + + double muinc, murel; + + // get incremental permeability of the DC material + // (i.e. incremental permeability at the offset) + muinc = 1. / (muo*Re(GetdHdB(B))); + murel = 1. / (muo*Re(Get_v(B))); + + // if material is not laminated, just return + if ((Lam_d == 0) || (LamFill == 0)){ + mu1 = muinc; + mu2 = murel; + return; + } + + // incremental permeability direction + mu1 = (muinc*LamFill + (1. - LamFill)); + + // normal permeability direction + mu2 = (murel*LamFill + (1. - LamFill)); + + return; +} + diff --git a/fkn/mesh.h b/fkn/mesh.h new file mode 100644 index 0000000..2722bb1 --- /dev/null +++ b/fkn/mesh.h @@ -0,0 +1,194 @@ +///////////////////////////////////////////////////////////////////////////// +// CNode -- structure that holds information about each mesh point. + +class CNode +{ + public: + + double x,y; + int bc; + + private: + +}; + +class CMeshline +{ + public: + + int n0,n1; + + private: +}; + +class CElement +{ + public: + + int p[3]; + int e[3]; + CComplex mu1,mu2,v12; + int blk; + int lbl; + double Jprev; + + private: +}; + +class CBlockLabel +{ + public: + + double x,y; + double MaxArea; + double MagDir; + int BlockType; + int InCircuit; + int InMask; + int InGroup; + int Turns; + BOOL IsExternal; + BOOL IsDefault; + char *MagDirFctn; + + // used for proximity effect regions only. + CComplex ProximityMu; + BOOL bIsWound; + + private: + +}; + +class CCommonPoint +{ + public: + int x,y,t; + + private: +}; +///////////////////////////////////////////////////////////////////////////// +// Classes that hold property data: CMaterialProp, CBoundaryProp, CPointProp +class CMaterialProp +{ + public: + + double mu_x,mu_y; // permeabilities, relative + int BHpoints; + double *Bdata; + CComplex *Hdata; + CComplex *slope; + double H_c; // magnetization, A/m + double Theta_m; // orientation of magnetization, degrees + double Jr,Ji; // applied current density, MA/m^2 + double Cduct; // conductivity of the material, MS/m + double Lam_d; // lamination thickness, mm + double Theta_hn; // hysteresis angle, degrees + double Theta_hx; // hysteresis angle, degrees + double Theta_hy; // hysteresis angle, degrees + int LamType; // lamination type/orientation + double LamFill; // lamination fill factor; + double WireD; // strand diameter, mm + int NStrands; // number of strands per wire + double MuMax; // maximum permeability for AC problems + CMaterialProp(); + ~CMaterialProp(); + void GetSlopes(); + void GetSlopes(double omega); + CComplex GetH(double B); + CComplex GetdHdB(double B); + CComplex Get_dvB2(double B); + CComplex Get_v(double B); + void GetBHProps(double B, CComplex &v, CComplex &dv); + void GetBHProps(double B, double &v, double &dv); + CComplex LaminatedBH(double omega, int i); + void IncrementalPermeability(double B, double w, CComplex &mu1, CComplex &mu2); + void IncrementalPermeability(double B, double &mu1, double &mu2); + + private: +}; + +class CBoundaryProp +{ + public: + + int BdryFormat; // type of boundary condition we are applying + // 0 = constant value of A + // 1 = Small skin depth eddy current BC + // 2 = Mixed BC + // 3 = SDI boundary (deprecated) + // 4 = Periodic + // 5 = Antiperiodic + // 6 = Periodic AGE + // 7 = Antiperiodic AGE + + double A0,A1,A2,phi; // set value of A for BdryFormat=0; + + double Mu,Sig; // material properties necessary to apply + // eddy current BC + + CComplex c0,c1; // coefficients for mixed BC + + double InnerAngle; // parameters needed to build air gap element + double OuterAngle; + + // TO DO: ``flux pipe?'' and ''line currents'' + // Line currents might be redundant, since we already have magnetization. + + private: +}; + +class CPointProp +{ + public: + + double Jr,Ji; // applied point current, A + double Ar,Ai; // prescribed nodal value; + + private: +}; + +class CCircuit +{ + public: + + double dVolts_re, dVolts_im; + double Amps_re, Amps_im; + int CircType; + int OrigCirc; + + // some member variables used to store some results + CComplex J; + CComplex dV; + int Case; + + private: +}; + +class CQuadPoint +{ + public: + int n0,n1,n2,n3; + double w0,w1,w2,w3; +}; + +class CAirGapElement +{ + public: + + char BdryName[80]; + int BdryFormat; // 0 = Periodic + // 1 = Antiperiodic + + int totalArcElements; // total elements in the initial meshing + double totalArcLength; // sum of the angles of all constituent arcs + double ri,ro; // inner and outer radii of the air gap element + double InnerAngle; // Angle in degrees through which the inner ring (rotor) is turned + double OuterAngle; // Angle in degrees through which the inner ring (stator) is turned + double InnerShift; // fraction of an element that inner mesh is shifted relative to annular mesh + double OuterShift; // fraction of an element that outer mesh is shifted relative to annular mesh + CComplex agc; // center of the air gap element + + CQuadPoint *node; // mapping of mesh nodes onto an annular ring + + private: +}; \ No newline at end of file diff --git a/fkn/prob1big.cpp b/fkn/prob1big.cpp new file mode 100644 index 0000000..04d9597 --- /dev/null +++ b/fkn/prob1big.cpp @@ -0,0 +1,882 @@ +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" +#include "lua.h" + +extern lua_State *lua; + +double Power(double x, int y) +{ + return pow(x,(double) y); +} + +BOOL CFemmeDocCore::Static2D(CBigLinProb &L) +{ + int i,j,k,w,s; + double Me[3][3],be[3]; // element matrices; + double Mx[3][3],My[3][3],Mxy[3][3],Mn[3][3]; + double l[3],p[3],q[3]; // element shape parameters; + int n[3]; // numbers of nodes for a particular element; + double a,K,Ki,r,t,x,y,B,B1,B2,mu,v[3],u[3],dv,res,lastres,Cduct; + double *V_old,*CircInt1,*CircInt2,*CircInt3; + double c=PI*4.e-05; + double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + int Iter=0,pctr; + BOOL LinearFlag=TRUE; + BOOL bIncremental = FALSE; + BOOL bRestart = FALSE; + double murel, muinc; + + if (PrevSoln.GetLength() > 0) bIncremental = PrevType; + res=0; + + CElement *El; + V_old=(double *) calloc(NumNodes,sizeof(double)); + + for(i=0;i0) + { + CircInt1=(double *)calloc(NumCircProps,sizeof(double)); + CircInt2=(double *)calloc(NumCircProps,sizeof(double)); + CircInt3=(double *)calloc(NumCircProps,sizeof(double)); + for(i=0;i=0) + if(labellist[meshele[i].lbl].InCircuit!=-1){ + El=&meshele[i]; + + // get element area; + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + a=(p[0]*q[1]-p[1]*q[0])/2.; + // r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // if coils are wound, they act like they have + // a zero "bulk" conductivity... + Cduct=blockproplist[El->blk].Cduct; + if (labellist[El->lbl].bIsWound) Cduct=0; + + // evaluate integrals; + CircInt1[labellist[El->lbl].InCircuit]+=a; + CircInt2[labellist[El->lbl].InCircuit]+= + a*Cduct; + CircInt3[labellist[El->lbl].InCircuit]+= + blockproplist[El->blk].Jr*a*100.; + } + } + + for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); + TheView->m_prog1.SetPos(0); + pctr=0; + + if(Iter>0) L.Wipe(); + else{ + + // could be starting from a previous solution; load up the initial guess from Aprev + if (bIncremental==1) + { + // try to restart from a previous file of the same name + // to cut down on the time to solve the incremental problem + CString myFile; + myFile.Format("%s.ans",PathName); + if (LoadPrevA(myFile,L.V)) bRestart = 2; + } + else if ((bIncremental==0) && (PrevSoln.GetLength()>0)) + { + // load initial guess from the explicitly specified previous solution + bRestart = LoadPrevA(PrevSoln,L.V); + } + } + + // first, tack in air gap element contributions + for(i=0;ico) + { + ci=ci-co; + co=0; + } + else{ + ci=1-co+ci; + co=1; + } + + // build the element matrix for each quad element in the annulus (same for each element) + // matrix for quad element derived from serendipity element + MG[0][0] = (5*Power (-1 + ci,2)*Power (ci,4)*(K + Ki))/48.; + MG[0][1] = -((-1 + ci)*Power (ci,3)*(5*(-1 + ci*(-5 + 4*ci))*K + (-5 + ci*(-19 + 14*ci))*Ki))/48.; + MG[0][2] = ((-1 + ci)*Power (ci,2)*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; + MG[0][3] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-2 + ci*(-3 + 4*ci))*K + (2 + ci*(-3 + 2*ci))*Ki))/48.; + MG[0][4] = (Power (-1 + ci,3)*Power (ci,3)*(5*K - Ki))/48.; + MG[0][5] = ((-1 + ci)*Power (ci,2)*(-1 + co)*Power (co,2)*(K - 5*Ki))/48.; + MG[0][6] = -((-1 + ci)*Power (ci,2)*co*((-1 + co*(-5 + 4*co))*K + (5 + (19 - 14*co)*co)*Ki))/48.; + MG[0][7] = ((-1 + ci)*Power (ci,2)*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; + MG[0][8] = -((-1 + ci)*Power (ci,2)*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (-2 + (3 - 2*co)*co)*Ki))/48.; + MG[0][9] = ((-1 + ci)*Power (ci,2)*Power (-1 + co,2)*co*(K + Ki))/48.; + MG[1][1] = (Power (ci,2)*(5*Power (1 + (5 - 4*ci)*ci,2)*K + (5 + ci*(38 + ci*(49 + 4*ci*(-29 + 11*ci))))*Ki))/48.; + MG[1][2] = (-5*ci*(-1 + 2*ci)*(-2 + 3*(-1 + ci)*ci)*(-1 + ci*(-5 + 4*ci))*K + ci*(10 + ci*(39 - ci*(50 + ci*(85 + 6*ci*(-23 + 8*ci)))))*Ki)/48.; + MG[1][3] = ((-1 + ci)*ci*(5*(2 + ci*(13 + ci*(3 + 16*(-2 + ci)*ci)))*K + (-2 + 5*ci*(1 + ci*(3 + 4*(-2 + ci)*ci)))*Ki))/48.; + MG[1][4] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-1 + ci*(-5 + 4*ci))*K + Ki + ci*(-1 + 2*ci)*Ki))/48.; + MG[1][5] = -(ci*(-1 + co)*Power (co,2)*((-1 + ci*(-5 + 4*ci))*K + (5 + (19 - 14*ci)*ci)*Ki))/48.; + MG[1][6] = (ci*co*((-1 + ci*(-5 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (-5 + ci*(-19 + 14*ci) - 19*co + ci*(-77 + 58*ci)*co + 2*(7 + (29 - 22*ci)*ci)*Power (co,2))*Ki))/48.; + MG[1][7] = (-(ci*(-1 + ci*(-5 + 4*ci))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + ci*(-10 + co*(-1 + 3*(7 - 4*co)*co) + ci*(-38 + co + 99*Power (co,2) - 60*Power (co,3)) + Power (ci,2)*(28 + 2*co*(-1 + 3*co*(-13 + 8*co))))*Ki)/48.; + MG[1][8] = (ci*(-1 + co)*((-1 + ci*(-5 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co) + Power (ci,2)*(4 + 2*(9 - 10*co)*co) + ci*(-2 + co*(-21 + 22*co)))*Ki))/48.; + MG[1][9] = -(ci*Power (-1 + co,2)*co*((-1 + ci*(-5 + 4*ci))*K + (-1 + ci - 2*Power (ci,2))*Ki))/48.; + MG[2][2] = (5*Power (-2 + ci + 9*Power (ci,2) - 6*Power (ci,3),2)*K + (20 + (-1 + ci)*ci*(-4 + 3*(-1 + ci)*ci*(-25 + 24*(-1 + ci)*ci)))*Ki)/48.; + MG[2][3] = (-5*(4 + Power (ci,2)*(-33 + ci*(18 + ci*(65 + 6*ci*(-13 + 4*ci)))))*K + (4 + Power (ci,2)*(39 - ci*(30 + ci*(115 + 6*ci*(-25 + 8*ci)))))*Ki)/48.; + MG[2][4] = (Power (-1 + ci,2)*ci*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (-2 + ci*(-5 + 3*ci*(-5 + 4*ci)))*Ki))/48.; + MG[2][5] = ((-1 + co)*Power (co,2)*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K - (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; + MG[2][6] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*co*(-1 + co*(-5 + 4*co))*K) + co*(-10 - 38*co + 28*Power (co,2) + Power (ci,2)*(21 + 99*co - 78*Power (co,2)) + ci*(-1 + co - 2*Power (co,2)) + 12*Power (ci,3)*(-1 + co*(-5 + 4*co)))*Ki)/48.; + MG[2][7] = ((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (2*(10 + co) + 6*Power (co,2)*(-7 + 4*co) + 3*Power (ci,2)*(-14 + co*(5 + (55 - 36*co)*co)) + ci*(2 + co*(5 + 3*(5 - 4*co)*co)) + 12*Power (ci,3)*(2 + co*(-1 - 9*co + 6*Power (co,2))))*Ki)/48.; + MG[2][8] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co - 7*Power (co,2) + 4*Power (co,3))*K) + (-1 + co)*(4 + 2*ci*(5 + 3*(5 - 4*ci)*ci) + 3*(-2 + ci*(3 + (17 - 12*ci)*ci))*co + 2*(2 + ci*(-7 + 3*ci*(-11 + 8*ci)))*Power (co,2))*Ki)/48.; + MG[2][9] = (Power (-1 + co,2)*co*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (2 + ci*(5 + 3*(5 - 4*ci)*ci))*Ki))/48.; + MG[3][3] = (Power (-1 + ci,2)*(5*Power (2 + (3 - 4*ci)*ci,2)*K + (20 + ci*(36 + ci*(-35 - 60*ci + 44*Power (ci,2))))*Ki))/48.; + MG[3][4] = -(Power (-1 + ci,3)*ci*(5*(-2 + ci*(-3 + 4*ci))*K + (-10 + ci*(-9 + 14*ci))*Ki))/48.; + MG[3][5] = -((-1 + ci)*(-1 + co)*Power (co,2)*((-2 + ci*(-3 + 4*ci))*K + (-2 + (3 - 2*ci)*ci)*Ki))/48.; + MG[3][6] = ((-1 + ci)*co*((-2 + ci*(-3 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (2 + ci*(-3 + 2*ci) - 2*co + ci*(-21 + 22*ci)*co + 2*(2 + (9 - 10*ci)*ci)*Power (co,2))*Ki))/48.; + MG[3][7] = (-((2 + ci - 7*Power (ci,2) + 4*Power (ci,3))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + (-1 + ci)*(4 + 2*co*(5 + 3*(5 - 4*co)*co) + ci*(-6 + 3*co*(3 + (17 - 12*co)*co)) + 2*Power (ci,2)*(2 + co*(-7 + 3*co*(-11 + 8*co))))*Ki)/48.; + MG[3][8] = ((-1 + ci)*(-1 + co)*((-2 + ci*(-3 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (-20 + 3*ci*(1 + 2*co)*(-6 + 5*co) + 2*co*(-9 + 14*co) + Power (ci,2)*(28 + 30*co - 44*Power (co,2)))*Ki))/48.; + MG[3][9] = -((-1 + ci)*Power (-1 + co,2)*co*((-2 + ci*(-3 + 4*ci))*K + (10 + (9 - 14*ci)*ci)*Ki))/48.; + MG[4][4] = (5*Power (-1 + ci,4)*Power (ci,2)*(K + Ki))/48.; + MG[4][5] = (Power (-1 + ci,2)*ci*(-1 + co)*Power (co,2)*(K + Ki))/48.; + MG[4][6] = -(Power (-1 + ci,2)*ci*co*((-1 + co*(-5 + 4*co))*K + (-1 + co - 2*Power (co,2))*Ki))/48.; + MG[4][7] = (Power (-1 + ci,2)*ci*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (2 + co*(5 + 3*(5 - 4*co)*co))*Ki))/48.; + MG[4][8] = -(Power (-1 + ci,2)*ci*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (10 + (9 - 14*co)*co)*Ki))/48.; + MG[4][9] = (Power (-1 + ci,2)*ci*Power (-1 + co,2)*co*(K - 5*Ki))/48.; + MG[5][5] = (5*Power (-1 + co,2)*Power (co,4)*(K + Ki))/48.; + MG[5][6] = -((-1 + co)*Power (co,3)*(5*(-1 + co*(-5 + 4*co))*K + (-5 + co*(-19 + 14*co))*Ki))/48.; + MG[5][7] = ((-1 + co)*Power (co,2)*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; + MG[5][8] = -(Power (-1 + co,2)*Power (co,2)*(5*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co))*Ki))/48.; + MG[5][9] = (Power (-1 + co,3)*Power (co,3)*(5*K - Ki))/48.; + MG[6][6] = (Power (co,2)*(5*Power (1 + (5 - 4*co)*co,2)*K + (5 + co*(38 + co*(49 + 4*co*(-29 + 11*co))))*Ki))/48.; + MG[6][7] = (-5*co*(-1 + 2*co)*(-2 + 3*(-1 + co)*co)*(-1 + co*(-5 + 4*co))*K + co*(10 + co*(39 - co*(50 + co*(85 + 6*co*(-23 + 8*co)))))*Ki)/48.; + MG[6][8] = ((-1 + co)*co*(5*(2 + co*(13 + co*(3 + 16*(-2 + co)*co)))*K + (-2 + 5*co*(1 + co*(3 + 4*(-2 + co)*co)))*Ki))/48.; + MG[6][9] = -(Power (-1 + co,2)*Power (co,2)*(5*(-1 + co*(-5 + 4*co))*K + Ki + co*(-1 + 2*co)*Ki))/48.; + MG[7][7] = (5*Power (-2 + co + 9*Power (co,2) - 6*Power (co,3),2)*K + (20 + (-1 + co)*co*(-4 + 3*(-1 + co)*co*(-25 + 24*(-1 + co)*co)))*Ki)/48.; + MG[7][8] = (-5*(4 + Power (co,2)*(-33 + co*(18 + co*(65 + 6*co*(-13 + 4*co)))))*K + (4 + Power (co,2)*(39 - co*(30 + co*(115 + 6*co*(-25 + 8*co)))))*Ki)/48.; + MG[7][9] = (Power (-1 + co,2)*co*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (-2 + co*(-5 + 3*co*(-5 + 4*co)))*Ki))/48.; + MG[8][8] = (Power (-1 + co,2)*(5*Power (2 + (3 - 4*co)*co,2)*K + (20 + co*(36 + co*(-35 - 60*co + 44*Power (co,2))))*Ki))/48.; + MG[8][9] = -(Power (-1 + co,3)*co*(5*(-2 + co*(-3 + 4*co))*K + (-10 + co*(-9 + 14*co))*Ki))/48.; + MG[9][9] = (5*Power (-1 + co,4)*Power (co,2)*(K + Ki))/48.; + + // Add each annulus element to the global stiffness matrix + for(k=0;kagelist[i].totalArcElements){ + nn[4]=agelist[i].node[1].n1; + ww[4]=agelist[i].node[1].w1; + } + else{ + nn[4]=agelist[i].node[k+2].n1; + ww[4]=agelist[i].node[k+2].w1; + } + + // outer nodes + if ((k-1)<0){ + nn[5]=agelist[i].node[agelist[i].totalArcElements-1].n2; + ww[5]=agelist[i].node[agelist[i].totalArcElements-1].w2; + } + else{ + nn[5]=agelist[i].node[k-1].n2; + ww[5]=agelist[i].node[k-1].w2; + } + + nn[6]=agelist[i].node[k].n2; + nn[7]=agelist[i].node[k].n3; + nn[8]=agelist[i].node[k+1].n3; + ww[6]=agelist[i].node[k].w2; + ww[7]=agelist[i].node[k].w3; + ww[8]=agelist[i].node[k+1].w3; + + if((k+2)>agelist[i].totalArcElements){ + nn[9]=agelist[i].node[1].n3; + ww[9]=agelist[i].node[1].w3; + } + else{ + nn[9]=agelist[i].node[k+2].n3; + ww[9]=agelist[i].node[k+2].w3; + } + + // fix antiperiodic weights... + if ((k==0) && (agelist[i].BdryFormat==1)) + { + ww[0]=-ww[0]; + ww[5]=-ww[5]; + } + if (((k+1)==agelist[i].totalArcElements) && (agelist[i].BdryFormat==1)) + { + ww[4]=-ww[4]; + ww[9]=-ww[9]; + } + + // scale by weight to get periodic/antiperiodic right and tack into mesh + for(int ii=0;ii<10;ii++) + for(int jj=ii;jj<10;jj++) + L.AddTo(MG[ii][jj]*ww[ii]*ww[jj],nn[ii],nn[jj]); + } + + } + + for(i=0;ipctr){ + j=pctr*5; if (j>100) j=100; + TheView->m_prog1.SetPos(j); + pctr++; + } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + Me[j][k]=0.; + Mx[j][k]=0.; + My[j][k]=0.; + Mn[j][k]=0.; + Mxy[j][k] = 0.; + } + be[j]=0.; + } + + // Determine shape parameters. + // l == element side lengths; + // p corresponds to the `b' parameter in Allaire + // q corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // x-contribution; only need to do main diagonal and above; + K = (-1. / (4.*a)); + for (j = 0; j < 3; j++) + for (k = j; k < 3; k++) + { + Mx[j][k] += K*p[j] * p[k]; + if (j != k) Mx[k][j] += K*p[j] * p[k]; + } + + // y-contribution; only need to do main diagonal and above; + K = (-1. / (4.*a)); + for (j = 0; j < 3; j++) + for (k = j; k < 3; k++) + { + My[j][k] += K*q[j] * q[k]; + if (j != k) My[k][j] += K*q[j] * q[k]; + } + + // xy-contribution; + K = (-1. / (4.*a)); + for (j = 0; j < 3; j++) + for (k = j; k < 3; k++) + { + Mxy[j][k] += K*(p[j] * q[k] + p[k] * q[j]); + if (j != k) Mxy[k][j] += K*(p[j] * q[k] + p[k] * q[j]); + } + + // contributions to Me, be from derivative boundary conditions; + for(j=0;j<3;j++){ + if (El->e[j] >= 0) + if (lineproplist[El->e[j]].BdryFormat==2) + { + // conversion factor is 10^(-4) (I think...) + K=-0.0001*c*lineproplist[ El->e[j] ].c0.re*l[j]/6.; + k=j+1; if(k==3) k=0; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K=(lineproplist[ El->e[j] ].c1.re*l[j]/2.)*0.0001; + be[j]+=K; + be[k]+=K; + } + } + + // contribution to be from current density in the block + for(j=0,El->Jprev=0;j<3;j++){ + if(labellist[El->lbl].InCircuit>=0) + { + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==1) t=circproplist[k].J.Re(); + if(circproplist[k].Case==0) + t=-circproplist[k].dV.Re()*blockproplist[El->blk].Cduct; + } + else t=0; + K=-(blockproplist[El->blk].Jr+t)*a/3.; + be[j]+=K; + + // record avg current density in the block for use in incremental solutions + if (bIncremental==FALSE) El->Jprev+=(blockproplist[El->blk].Jr+t)/3.; + } + + // contribution to be from magnetization in the block; + t=labellist[El->lbl].MagDir; + if (labellist[El->lbl].MagDirFctn!=NULL) // functional magnetization direction + { + CString str; + CComplex X; + int top1,top2,lua_error_code; + for (j=0,X=0;j<3;j++) X+=(meshnode[n[j]].x + I*meshnode[n[j]].y); + X=X/units[LengthUnits]/3.; + str.Format("x=%.17g\ny=%.17g\nr=x\nz=y\ntheta=%.17g\nR=%.17g\nreturn %s", + X.re,X.im,arg(X)*180/PI,abs(X),labellist[El->lbl].MagDirFctn); + top1=lua_gettop(lua); + if((lua_error_code=lua_dostring(lua,str))!=0) + { + /* + if (lua_error_code==LUA_ERRRUN) + AfxMessageBox("Run Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + */ + + MsgBox("Lua error evaluating \"%s\"",labellist[El->lbl].MagDirFctn); + + exit(7); + } + top2=lua_gettop(lua); + if (top2!=top1){ + str=lua_tostring(lua,-1); + if (str.GetLength()==0){ + MsgBox("\"%s\" does not evaluate to a numerical value", + labellist[El->lbl].MagDirFctn); + exit(7); + } + else t=Re(lua_tonumber(lua,-1)); + lua_pop(lua, 1); + } + } + for(j=0;j<3;j++){ + k=j+1; if(k==3) k=0; + // need to scale so that everything is in proper units... + // conversion is 0.0001 + K=0.0001*blockproplist[El->blk].H_c*( + cos(t*PI/180.)*(meshnode[n[k]].x-meshnode[n[j]].x) + + sin(t*PI/180.)*(meshnode[n[k]].y-meshnode[n[j]].y) )/2.; + be[j]+=K; + be[k]+=K; + } + +//////// Nonlinear Part + + // update permeability for the element; + if (Iter==0){ + k=meshele[i].blk; + + if (blockproplist[k].LamType==0){ + t=blockproplist[k].LamFill; + meshele[i].mu1=blockproplist[k].mu_x*t + (1.-t); + meshele[i].mu2=blockproplist[k].mu_y*t + (1.-t); + } + if (blockproplist[k].LamType==1){ + t=blockproplist[k].LamFill; + mu=blockproplist[k].mu_x; + meshele[i].mu1=mu*t + (1.-t); + meshele[i].mu2=mu/(t + mu*(1.-t)); + } + if (blockproplist[k].LamType==2){ + t=blockproplist[k].LamFill; + mu=blockproplist[k].mu_y; + meshele[i].mu2=mu*t + (1.-t); + meshele[i].mu1=mu/(t + mu*(1.-t)); + } + if (blockproplist[k].LamType>2) + { + meshele[i].mu1=1; + meshele[i].mu2=1; + } + + + if (blockproplist[k].BHpoints != 0) + { + if (bIncremental == FALSE) + { + // There's no previous solution. This is a standard nonlinear problem + LinearFlag = FALSE; + } + else { + double B1p, B2p; + + // too lazy to consistently code incremental/frozen formulation for on-edge lams. + // detect this condition, throw an error, and exit. + if (blockproplist[k].LamType > 0) + { + MsgBox("On-edge Lam Types not yet supported in\nincremental/frozen permeability problems"); + exit(0); + } + + // Get B from previous solution + GetPrev2DB(i, B1p, B2p); + B = sqrt(B1p*B1p + B2p*B2p); + + + + // look up incremental permeability and assign it to the element; + blockproplist[k].IncrementalPermeability(B, muinc, murel); + + if (B == 0) + { + meshele[i].mu1 = muinc; + meshele[i].mu2 = muinc; + meshele[i].v12 = 0; + } + else { + if (bIncremental == 1) + { + // Need to actually compute B1 and B2 to build incremental permeability tensor + meshele[i].mu1 = B*B*muinc*murel / (B1p*B1p*murel + B2p*B2p*muinc); + meshele[i].mu2 = B*B*muinc*murel / (B1p*B1p*muinc + B2p*B2p*murel); + meshele[i].v12 = -B1p*B2p*(murel - muinc) / (B*B*murel*muinc); + } + else { + // Define "frozen permeability" + meshele[i].mu1 = murel; + meshele[i].mu2 = murel; + meshele[i].v12 = 0; + } + } + } + } + + } + + if ((Iter>0) || (bRestart==TRUE)) + { + k=meshele[i].blk; + + if ((blockproplist[k].LamType==0) && + (meshele[i].mu1==meshele[i].mu2) + &&(blockproplist[k].BHpoints>0)) + { + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=L.V[n[j]]*q[j]; + B2+=L.V[n[j]]*p[j]; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + // correction for lengths in cm of 1/0.02 + + // find out new mu from saturation curve; + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu; + meshele[i].mu2=mu; + for(j=0;j<3;j++){ + for(w=0,v[j]=0;w<3;w++) + v[j]+=(Mx[j][w]+My[j][w])*L.V[n[w]]; + } + K=-200.*c*c*c*dv/a; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*v[j]*v[w]; + } + + if ((blockproplist[k].LamType==1) && (blockproplist[k].BHpoints>0)){ + t=blockproplist[k].LamFill; + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=L.V[n[j]]*q[j]; + B2+=L.V[n[j]]*p[j]/t; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu*t; + meshele[i].mu2=mu/(t+mu*(1.-t)); + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(My[j][w]/t+Mx[j][w])*L.V[n[w]]; + u[j]+=(My[j][w]/t + t*Mx[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(a); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + } + if ((blockproplist[k].LamType==2) && (blockproplist[k].BHpoints>0)){ + t=blockproplist[k].LamFill; + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=(L.V[n[j]]*q[j])/t; + B2+=L.V[n[j]]*p[j]; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu2=mu*t; + meshele[i].mu1=mu/(t+mu*(1.-t)); + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(Mx[j][w]/t + My[j][w])*L.V[n[w]]; + u[j]+=(Mx[j][w]/t + t*My[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(a); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + } + } + + // combine block matrices into global matrices; + for(j=0;j<3;j++) + for(k=0;k<3;k++){ + Me[j][k]+= (Mx[j][k]/Re(El->mu2) + My[j][k]/Re(El->mu1) + Mxy[j][k] * Re(El->v12) + Mn[j][k]); + be[j]+=Mn[j][k]*L.V[n[k]]; + } + + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.AddTo(-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // add in contribution from point currents; + for(i=0;i=0) + L.b[i]+=(0.01*nodeproplist[meshnode[i].bc].Jr); + + // apply fixed boundary conditions at points; + for(i=0;i=0) + if((nodeproplist[meshnode[i].bc].Jr==0) && + (nodeproplist[meshnode[i].bc].Ji==0)) + L.SetValue(i,nodeproplist[meshnode[i].bc].Ar / c); + + // apply fixed boundary conditions along segments; + for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + if(Coords==0){ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take ``real'' component. + a*=cos(lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take``real'' component. + a*=cos(lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],a/c); + } + else{ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + r=sqrt(x*x+y*y); + if((x==0)&&(y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + r=sqrt(x*x+y*y); + if((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + L.SetValue(meshele[i].p[k],a/c); + } + + } + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0;k5) + { + if ((res>lastres) && (Relax>0.125)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + + for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); + j=(int) (100.*log10(res)/(log10(Precision)+2.)); + if (j>100) j=100; + TheView->m_prog2.SetPos(j); + } + + // nonlinear iteration has to have a looser tolerance + // than the linear solver--otherwise, things can't ever + // converge. Arbitrarily choose 100*tolerance. + if((res<100.*Precision) && (Iter>0)) LinearFlag=TRUE; + + Iter++; + +} while(LinearFlag==FALSE); + + for(i=0;i0){ + free(CircInt1); + free(CircInt2); + free(CircInt3); + } + return TRUE; +} + +//========================================================================= +//========================================================================= + +BOOL CFemmeDocCore::WriteStatic2D(CBigLinProb &L) +{ + // write solution to disk; + + char c[1024]; + FILE *fp,*fz; + int i,k; + double cf; + double unitconv[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + + // first, echo input .fem file to the .ans file; + sprintf(c,"%s.fem",PathName); + if((fz=fopen(c,"rt"))==NULL){ + Sleep(500); + if((fz=fopen(c,"rt"))==NULL){ + MsgBox("Couldn't open %s.fem\n",PathName); + return FALSE; + } + } + + sprintf(c,"%s.ans",PathName); + if((fp=fopen(c,"wt"))==NULL){ + Sleep(500); + if((fp=fopen(c,"wt"))==NULL){ + MsgBox("Couldn't write to %s.ans\n",PathName); + return FALSE; + } + } + + while(fgets(c,1024,fz)!=NULL) fputs(c,fp); + fclose(fz); + + // then print out node, line, and element information + fprintf(fp,"[Solution]\n"); + cf=unitconv[LengthUnits]; + fprintf(fp,"%i\n",NumNodes); + for (i = 0;i < NumNodes;i++) + { + fprintf(fp, "%.17g %.17g %.17g %i ", meshnode[i].x / cf, + meshnode[i].y / cf, L.b[i], meshnode[i].bc); + // include A from previous solution if this is an incremental permeability problem + if (Aprev != NULL) fprintf(fp, "%.17g\n", Aprev[i]); + else fprintf(fp, "\n"); + } + + fprintf(fp,"%i\n",NumEls); + for(i=0;i +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" + +// #define NEWTON + +// since all node positions were converted to units of cm +// the proper LengthConv is converts centimeters to meters +#define LengthConv 0.01 + +double Power(double x, int y); + +void CFemmeDocCore::GetPrev2DB(int k, double &B1p, double &B2p) +{ + int i,n[3]; + double b[3],c[3],da; + + for(i=0;i<3;i++) n[i]=meshele[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + da=(b[0]*c[1]-b[1]*c[0]); + + B1p=0; + B2p=0; + + for(i=0;i<3;i++) + { + B1p+=Aprev[n[i]]*c[i]/(da*LengthConv); + B2p-=Aprev[n[i]]*b[i]/(da*LengthConv); + } +} + +BOOL CFemmeDocCore::Harmonic2D(CBigComplexLinProb &L) +{ + int i,j,k,ww,s,pctr; + CComplex Mx[3][3],My[3][3],Mxy[3][3]; + CComplex Me[3][3],be[3]; // element matrices; + double l[3],p[3],q[3]; // element shape parameters; + int n[3]; // numbers of nodes for a particular element; + double a,r,t,x,y,B,w,res,lastres,ds,Cduct; + CComplex K,mu,dv,B1,B2,v[3],u[3],mu1,mu2,lag,halflag,deg45,Jv; + CComplex **Mu,*V_old; + double c=PI*4.e-05; + double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + CElement *El; + int Iter=0; + BOOL LinearFlag=TRUE; + BOOL bIncremental=FALSE; + + if (PrevSoln.GetLength()>0) bIncremental=TRUE; + res=0; + +// #ifndef NEWTON + CComplex murel,muinc; +// #else; + CComplex Mnh[3][3]; + CComplex Mna[3][3]; + CComplex Mns[3][3]; +// #endif + + CComplex Mn[3][3]; + + deg45=1+I; + w=Frequency*2.*PI; + + CComplex *CircInt1,*CircInt2,*CircInt3; + + + + // Can't handle LamType==1 or LamType==2 in AC problems. + // Detect if this is being attempted. + for(i=0;i0) + { + CircInt1=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + CircInt2=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + CircInt3=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + for(i=0;i=0) + if(labellist[meshele[i].lbl].InCircuit!=-1){ + El=&meshele[i]; + + // get element area; + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + a=(p[0]*q[1]-p[1]*q[0])/2.; + // r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // if coils are wound, they act like they have + // a zero "bulk" conductivity... + Cduct=blockproplist[El->blk].Cduct; + if (labellist[El->lbl].bIsWound) Cduct=0; + + // evaluate integrals; + + // total cross-section of circuit; + CircInt1[labellist[El->lbl].InCircuit]+=a; + + // integral of conductivity over the circuit; + CircInt2[labellist[El->lbl].InCircuit]+=a*Cduct; + + // integral of applied J over current; + CircInt3[labellist[El->lbl].InCircuit]+= + (blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji)*a*100.; + } + } + + for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); + TheView->m_prog1.SetPos(0); + pctr=0; + + if(Iter>0) L.Wipe(); + + // first, tack in air gap element contributions + for(i=0;ico) + { + ci=ci-co; + co=0; + } + else{ + ci=1-co+ci; + co=1; + } + + // build the element matrix for each quad element in the annulus (same for each element) + // matrix for quad element derived from serendipity element + MG[0][0] = (5*Power (-1 + ci,2)*Power (ci,4)*(K + Ki))/48.; + MG[0][1] = -((-1 + ci)*Power (ci,3)*(5*(-1 + ci*(-5 + 4*ci))*K + (-5 + ci*(-19 + 14*ci))*Ki))/48.; + MG[0][2] = ((-1 + ci)*Power (ci,2)*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; + MG[0][3] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-2 + ci*(-3 + 4*ci))*K + (2 + ci*(-3 + 2*ci))*Ki))/48.; + MG[0][4] = (Power (-1 + ci,3)*Power (ci,3)*(5*K - Ki))/48.; + MG[0][5] = ((-1 + ci)*Power (ci,2)*(-1 + co)*Power (co,2)*(K - 5*Ki))/48.; + MG[0][6] = -((-1 + ci)*Power (ci,2)*co*((-1 + co*(-5 + 4*co))*K + (5 + (19 - 14*co)*co)*Ki))/48.; + MG[0][7] = ((-1 + ci)*Power (ci,2)*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; + MG[0][8] = -((-1 + ci)*Power (ci,2)*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (-2 + (3 - 2*co)*co)*Ki))/48.; + MG[0][9] = ((-1 + ci)*Power (ci,2)*Power (-1 + co,2)*co*(K + Ki))/48.; + MG[1][1] = (Power (ci,2)*(5*Power (1 + (5 - 4*ci)*ci,2)*K + (5 + ci*(38 + ci*(49 + 4*ci*(-29 + 11*ci))))*Ki))/48.; + MG[1][2] = (-5*ci*(-1 + 2*ci)*(-2 + 3*(-1 + ci)*ci)*(-1 + ci*(-5 + 4*ci))*K + ci*(10 + ci*(39 - ci*(50 + ci*(85 + 6*ci*(-23 + 8*ci)))))*Ki)/48.; + MG[1][3] = ((-1 + ci)*ci*(5*(2 + ci*(13 + ci*(3 + 16*(-2 + ci)*ci)))*K + (-2 + 5*ci*(1 + ci*(3 + 4*(-2 + ci)*ci)))*Ki))/48.; + MG[1][4] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-1 + ci*(-5 + 4*ci))*K + Ki + ci*(-1 + 2*ci)*Ki))/48.; + MG[1][5] = -(ci*(-1 + co)*Power (co,2)*((-1 + ci*(-5 + 4*ci))*K + (5 + (19 - 14*ci)*ci)*Ki))/48.; + MG[1][6] = (ci*co*((-1 + ci*(-5 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (-5 + ci*(-19 + 14*ci) - 19*co + ci*(-77 + 58*ci)*co + 2*(7 + (29 - 22*ci)*ci)*Power (co,2))*Ki))/48.; + MG[1][7] = (-(ci*(-1 + ci*(-5 + 4*ci))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + ci*(-10 + co*(-1 + 3*(7 - 4*co)*co) + ci*(-38 + co + 99*Power (co,2) - 60*Power (co,3)) + Power (ci,2)*(28 + 2*co*(-1 + 3*co*(-13 + 8*co))))*Ki)/48.; + MG[1][8] = (ci*(-1 + co)*((-1 + ci*(-5 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co) + Power (ci,2)*(4 + 2*(9 - 10*co)*co) + ci*(-2 + co*(-21 + 22*co)))*Ki))/48.; + MG[1][9] = -(ci*Power (-1 + co,2)*co*((-1 + ci*(-5 + 4*ci))*K + (-1 + ci - 2*Power (ci,2))*Ki))/48.; + MG[2][2] = (5*Power (-2 + ci + 9*Power (ci,2) - 6*Power (ci,3),2)*K + (20 + (-1 + ci)*ci*(-4 + 3*(-1 + ci)*ci*(-25 + 24*(-1 + ci)*ci)))*Ki)/48.; + MG[2][3] = (-5*(4 + Power (ci,2)*(-33 + ci*(18 + ci*(65 + 6*ci*(-13 + 4*ci)))))*K + (4 + Power (ci,2)*(39 - ci*(30 + ci*(115 + 6*ci*(-25 + 8*ci)))))*Ki)/48.; + MG[2][4] = (Power (-1 + ci,2)*ci*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (-2 + ci*(-5 + 3*ci*(-5 + 4*ci)))*Ki))/48.; + MG[2][5] = ((-1 + co)*Power (co,2)*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K - (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; + MG[2][6] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*co*(-1 + co*(-5 + 4*co))*K) + co*(-10 - 38*co + 28*Power (co,2) + Power (ci,2)*(21 + 99*co - 78*Power (co,2)) + ci*(-1 + co - 2*Power (co,2)) + 12*Power (ci,3)*(-1 + co*(-5 + 4*co)))*Ki)/48.; + MG[2][7] = ((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (2*(10 + co) + 6*Power (co,2)*(-7 + 4*co) + 3*Power (ci,2)*(-14 + co*(5 + (55 - 36*co)*co)) + ci*(2 + co*(5 + 3*(5 - 4*co)*co)) + 12*Power (ci,3)*(2 + co*(-1 - 9*co + 6*Power (co,2))))*Ki)/48.; + MG[2][8] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co - 7*Power (co,2) + 4*Power (co,3))*K) + (-1 + co)*(4 + 2*ci*(5 + 3*(5 - 4*ci)*ci) + 3*(-2 + ci*(3 + (17 - 12*ci)*ci))*co + 2*(2 + ci*(-7 + 3*ci*(-11 + 8*ci)))*Power (co,2))*Ki)/48.; + MG[2][9] = (Power (-1 + co,2)*co*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (2 + ci*(5 + 3*(5 - 4*ci)*ci))*Ki))/48.; + MG[3][3] = (Power (-1 + ci,2)*(5*Power (2 + (3 - 4*ci)*ci,2)*K + (20 + ci*(36 + ci*(-35 - 60*ci + 44*Power (ci,2))))*Ki))/48.; + MG[3][4] = -(Power (-1 + ci,3)*ci*(5*(-2 + ci*(-3 + 4*ci))*K + (-10 + ci*(-9 + 14*ci))*Ki))/48.; + MG[3][5] = -((-1 + ci)*(-1 + co)*Power (co,2)*((-2 + ci*(-3 + 4*ci))*K + (-2 + (3 - 2*ci)*ci)*Ki))/48.; + MG[3][6] = ((-1 + ci)*co*((-2 + ci*(-3 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (2 + ci*(-3 + 2*ci) - 2*co + ci*(-21 + 22*ci)*co + 2*(2 + (9 - 10*ci)*ci)*Power (co,2))*Ki))/48.; + MG[3][7] = (-((2 + ci - 7*Power (ci,2) + 4*Power (ci,3))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + (-1 + ci)*(4 + 2*co*(5 + 3*(5 - 4*co)*co) + ci*(-6 + 3*co*(3 + (17 - 12*co)*co)) + 2*Power (ci,2)*(2 + co*(-7 + 3*co*(-11 + 8*co))))*Ki)/48.; + MG[3][8] = ((-1 + ci)*(-1 + co)*((-2 + ci*(-3 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (-20 + 3*ci*(1 + 2*co)*(-6 + 5*co) + 2*co*(-9 + 14*co) + Power (ci,2)*(28 + 30*co - 44*Power (co,2)))*Ki))/48.; + MG[3][9] = -((-1 + ci)*Power (-1 + co,2)*co*((-2 + ci*(-3 + 4*ci))*K + (10 + (9 - 14*ci)*ci)*Ki))/48.; + MG[4][4] = (5*Power (-1 + ci,4)*Power (ci,2)*(K + Ki))/48.; + MG[4][5] = (Power (-1 + ci,2)*ci*(-1 + co)*Power (co,2)*(K + Ki))/48.; + MG[4][6] = -(Power (-1 + ci,2)*ci*co*((-1 + co*(-5 + 4*co))*K + (-1 + co - 2*Power (co,2))*Ki))/48.; + MG[4][7] = (Power (-1 + ci,2)*ci*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (2 + co*(5 + 3*(5 - 4*co)*co))*Ki))/48.; + MG[4][8] = -(Power (-1 + ci,2)*ci*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (10 + (9 - 14*co)*co)*Ki))/48.; + MG[4][9] = (Power (-1 + ci,2)*ci*Power (-1 + co,2)*co*(K - 5*Ki))/48.; + MG[5][5] = (5*Power (-1 + co,2)*Power (co,4)*(K + Ki))/48.; + MG[5][6] = -((-1 + co)*Power (co,3)*(5*(-1 + co*(-5 + 4*co))*K + (-5 + co*(-19 + 14*co))*Ki))/48.; + MG[5][7] = ((-1 + co)*Power (co,2)*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; + MG[5][8] = -(Power (-1 + co,2)*Power (co,2)*(5*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co))*Ki))/48.; + MG[5][9] = (Power (-1 + co,3)*Power (co,3)*(5*K - Ki))/48.; + MG[6][6] = (Power (co,2)*(5*Power (1 + (5 - 4*co)*co,2)*K + (5 + co*(38 + co*(49 + 4*co*(-29 + 11*co))))*Ki))/48.; + MG[6][7] = (-5*co*(-1 + 2*co)*(-2 + 3*(-1 + co)*co)*(-1 + co*(-5 + 4*co))*K + co*(10 + co*(39 - co*(50 + co*(85 + 6*co*(-23 + 8*co)))))*Ki)/48.; + MG[6][8] = ((-1 + co)*co*(5*(2 + co*(13 + co*(3 + 16*(-2 + co)*co)))*K + (-2 + 5*co*(1 + co*(3 + 4*(-2 + co)*co)))*Ki))/48.; + MG[6][9] = -(Power (-1 + co,2)*Power (co,2)*(5*(-1 + co*(-5 + 4*co))*K + Ki + co*(-1 + 2*co)*Ki))/48.; + MG[7][7] = (5*Power (-2 + co + 9*Power (co,2) - 6*Power (co,3),2)*K + (20 + (-1 + co)*co*(-4 + 3*(-1 + co)*co*(-25 + 24*(-1 + co)*co)))*Ki)/48.; + MG[7][8] = (-5*(4 + Power (co,2)*(-33 + co*(18 + co*(65 + 6*co*(-13 + 4*co)))))*K + (4 + Power (co,2)*(39 - co*(30 + co*(115 + 6*co*(-25 + 8*co)))))*Ki)/48.; + MG[7][9] = (Power (-1 + co,2)*co*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (-2 + co*(-5 + 3*co*(-5 + 4*co)))*Ki))/48.; + MG[8][8] = (Power (-1 + co,2)*(5*Power (2 + (3 - 4*co)*co,2)*K + (20 + co*(36 + co*(-35 - 60*co + 44*Power (co,2))))*Ki))/48.; + MG[8][9] = -(Power (-1 + co,3)*co*(5*(-2 + co*(-3 + 4*co))*K + (-10 + co*(-9 + 14*co))*Ki))/48.; + MG[9][9] = (5*Power (-1 + co,4)*Power (co,2)*(K + Ki))/48.; + + // Add each annulus element to the global stiffness matrix + for(k=0;kagelist[i].totalArcElements){ + nn[4]=agelist[i].node[1].n1; + ww[4]=agelist[i].node[1].w1; + } + else{ + nn[4]=agelist[i].node[k+2].n1; + ww[4]=agelist[i].node[k+2].w1; + } + + // outer nodes + if ((k-1)<0){ + nn[5]=agelist[i].node[agelist[i].totalArcElements-1].n2; + ww[5]=agelist[i].node[agelist[i].totalArcElements-1].w2; + } + else{ + nn[5]=agelist[i].node[k-1].n2; + ww[5]=agelist[i].node[k-1].w2; + } + + nn[6]=agelist[i].node[k].n2; + nn[7]=agelist[i].node[k].n3; + nn[8]=agelist[i].node[k+1].n3; + ww[6]=agelist[i].node[k].w2; + ww[7]=agelist[i].node[k].w3; + ww[8]=agelist[i].node[k+1].w3; + + if((k+2)>agelist[i].totalArcElements){ + nn[9]=agelist[i].node[1].n3; + ww[9]=agelist[i].node[1].w3; + } + else{ + nn[9]=agelist[i].node[k+2].n3; + ww[9]=agelist[i].node[k+2].w3; + } + + // fix antiperiodic weights... + if ((k==0) && (agelist[i].BdryFormat==1)) + { + ww[0]=-ww[0]; + ww[5]=-ww[5]; + } + if ((k==agelist[i].totalArcElements) && (agelist[i].BdryFormat==1)) + { + ww[4]=-ww[4]; + ww[9]=-ww[9]; + } + + // scale by weight to get periodic/antiperiodic right + for(int ii=0;ii<10;ii++) + for(int jj=ii;jj<10;jj++) + L.AddTo(-MG[ii][jj]*ww[ii]*ww[jj],nn[ii],nn[jj]); //needs different sign than prob1big version + } + } + + // build element matrices using the matrices derived in Allaire's book. + for(i=0;ipctr){ + j=pctr*5; if (j>100) j=100; + TheView->m_prog1.SetPos(j); + pctr++; + } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++) + { + Me[j][k]=0; + Mx[j][k]=0; + My[j][k]=0; + Mxy[j][k]=0; +//#ifdef NEWTON + if (ACSolver==1) + { + Mnh[j][k]=0; + Mna[j][k]=0; + Mns[j][k]=0; + } +//#endif + Mn[j][k]=0; + } + be[j]=0; + } + + // Determine shape parameters. + // l == element side lengths; + // p corresponds to the `b' parameter in Allaire + // q corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + + // x-contribution; + K = (-1./(4.*a)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Mx[j][k] += K*p[j]*p[k]; + if (j!=k) Mx[k][j]+=K*p[j]*p[k]; + } + + // y-contribution; + K = (-1./(4.*a)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + My[j][k] +=K*q[j]*q[k]; + if (j!=k) My[k][j]+=K*q[j]*q[k]; + } + + // xy-contribution; + K = (-1./(4.*a)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Mxy[j][k] += K*(p[j]*q[k] + p[k]*q[j]); + if (j!=k) Mxy[k][j] += K*(p[j]*q[k] + p[k]*q[j]); + } + + // contribution from eddy currents; + K=-I*a*w*blockproplist[meshele[i].blk].Cduct*c/12.; + + // in-plane laminated blocks appear to have no conductivity; + // eddy currents are accounted for in these elements by their + // frequency-dependent permeability. + if((blockproplist[El->blk].LamType==0) && + (blockproplist[El->blk].Lam_d>0)) K=0; + + // if this element is part of a wound coil, + // it should have a zero "bulk" conductivity... + if(labellist[El->lbl].bIsWound) K=0; + + for(j=0;j<3;j++) + { + for(k=j;k<3;k++){ + Me[j][k]+=K; + Me[k][j]+=K; + } + } + + // contributions to Me, be from derivative boundary conditions; + for(j=0;j<3;j++){ + if (El->e[j] >= 0) + { + if (lineproplist[El->e[j]].BdryFormat==2) + { + // conversion factor is 10^(-4) (I think...) + K=(-0.0001*c*lineproplist[ El->e[j] ].c0*l[j]/6.); + k=j+1; if(k==3) k=0; + Me[j][j]+=2*K; + Me[k][k]+=2*K; + Me[j][k]+=K; + Me[k][j]+=K; + + K=(lineproplist[ El->e[j] ].c1*l[j]/2.)*0.0001; + be[j]+=K; + be[k]+=K; + } + + if (lineproplist[El->e[j]].BdryFormat==1) + { + ds=sqrt(2./(0.4*PI*w*lineproplist[El->e[j]].Sig* + lineproplist[El->e[j]].Mu)); + K=deg45/(-ds*lineproplist[El->e[j]].Mu*100.); + K*=(l[j]/6.); + k=j+1; if(k==3) k=0; + Me[j][j]+=2*K; + Me[k][k]+=2*K; + Me[j][k]+=K; + Me[k][j]+=K; + } + } + } + + // contribution to be from current density in the block + for(j=0;j<3;j++){ + Jv=0; + if(labellist[El->lbl].InCircuit>=0) + { + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==1) Jv=circproplist[k].J; + if(circproplist[k].Case==0) + Jv=-circproplist[k].dV*blockproplist[El->blk].Cduct; + } + K=-(blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji+Jv)*a/3.; + be[j]+=K; + + if(labellist[El->lbl].InCircuit>=0){ + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==2) L.b[NumNodes+k]+=K; + } + } + + // do Case 2 circuit stuff for element + if(labellist[El->lbl].InCircuit>=0){ + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==2){ + K=-I*a*w*blockproplist[meshele[i].blk].Cduct*c; + for(j=0;j<3;j++) L.Put(L.Get(n[j],NumNodes+k)+K/3.,n[j],NumNodes+k); + L.Put(L.Get(NumNodes+k,NumNodes+k)+K,NumNodes+k,NumNodes+k); + } + } + + +/////////////////////////////////////////////////////////////// +// +// New Nonlinear stuff +// +/////////////////////////////////////////////////////////////// + + // update permeability for the element; + if (Iter==0){ + k=meshele[i].blk; + meshele[i].mu1=Mu[k][0]; + meshele[i].mu2=Mu[k][1]; + meshele[i].v12=0; + if (blockproplist[k].BHpoints>0) + { + if (bIncremental==FALSE) + { + // There's no previous solution. This is a standard nonlinear time harmonic problem + LinearFlag=FALSE; + } + else{ + double B1p,B2p; + + // Get B from previous solution + GetPrev2DB(i,B1p,B2p); + B = sqrt(B1p*B1p + B2p*B2p); + + // look up incremental permeability and assign it to the element; + blockproplist[k].IncrementalPermeability(B,w,muinc,murel); + if (B==0) + { + meshele[i].mu1=muinc; + meshele[i].mu2=muinc; + meshele[i].v12=0; + } + else{ + // need to actually compute B1 and B2 to build incremental permeability tensor + meshele[i].mu1=B*B*muinc*murel/(B1p*B1p*murel + B2p*B2p*muinc); + meshele[i].mu2=B*B*muinc*murel/(B1p*B1p*muinc + B2p*B2p*murel); + meshele[i].v12=-B1p*B2p*(murel-muinc)/(B*B*murel*muinc); + } + } + } + } + else{ + + k=meshele[i].blk; + + if ((blockproplist[k].LamType==0) && + (meshele[i].mu1==meshele[i].mu2) + &&(blockproplist[k].BHpoints>0)) + { + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=L.V[n[j]]*q[j]; + B2+=L.V[n[j]]*p[j]; + } + B=c*sqrt(abs(B1*conj(B1))+abs(B2*conj(B2)))/(0.02*a); + // correction for lengths in cm of 1/0.02 + +// #ifdef NEWTON + if(ACSolver==1){ + // find out new mu from saturation curve; + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu; + meshele[i].mu2=mu; + for(j=0;j<3;j++){ + for(ww=0,v[j]=0;ww<3;ww++) + v[j]+=(Mx[j][ww]+My[j][ww])*L.V[n[ww]]; + } + + //Newton-like Iteration + //Comment out for successive approx + K=-200.*c*c*c*dv/a; + for(j=0;j<3;j++) + for(ww=0;ww<3;ww++) + { + // Still compute Mn, the approximate N-R matrix used in + // the complex-symmetric approx. This will be useful + // w.r.t. preconditioning. However, subtract it off of Mnh and Mna + // so that there is no net addition. + Mn[j][ww] =K*Re(v[j]*conj(v[ww])); + Mnh[j][ww]= 0.5*Re(K)*v[j]*conj(v[ww])-Re(Mn[j][ww]); + Mna[j][ww]=I*0.5*Im(K)*v[j]*conj(v[ww])-I*Im(Mn[j][ww]); + Mns[j][ww]= 0.5*K*v[j]*v[ww]; + } + } +//#else + else{ + // find out new mu from saturation curve; + murel=1./(muo*blockproplist[k].Get_v(B)); + muinc=1./(muo*blockproplist[k].GetdHdB(B)); + + // successive approximation; + // K=muinc; // total incremental + // K=murel; // total updated + K=2.*murel*muinc/(murel+muinc); // averaged + meshele[i].mu1=K; + meshele[i].mu2=K; + K=-(1./murel - 1/K); + for(j=0;j<3;j++) + for(ww=0;ww<3;ww++) + Mn[j][ww]=K*(Mx[j][ww]+My[j][ww]); + } +//#endif + + } + } + + // Apply correction for elements subject to prox effects + if((blockproplist[meshele[i].blk].LamType>2) && (Iter==0)) + { + meshele[i].mu1=labellist[meshele[i].lbl].ProximityMu; + meshele[i].mu2=labellist[meshele[i].lbl].ProximityMu; + } + + // combine block matrices into global matrices; + for(j=0;j<3;j++) + for(k=0;k<3;k++){ + +// #ifdef NEWTON + if (ACSolver==1){ + Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k]*(El->v12) + Mn[j][k] ); + be[j]+=(Mnh[j][k]+Mna[j][k]+Mn[j][k])*L.V[n[k]]; + be[j]+=Mns[j][k]*L.V[n[k]].Conj(); + } +// #else + else{ + Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k] * (El->v12)); + be[j]+=Mn[j][k]*L.V[n[k]]; + } +// #endif + } + + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + { + // L.Put(L.Get(n[j],n[k]) + Me[j][k],n[j],n[k]); + L.AddTo(Me[j][k],n[j],n[k]); +//#ifdef NEWTON + if (ACSolver==1){ + if (Mnh[j][k]!=0) L.Put(L.Get(n[j],n[k],1) + Mnh[j][k],n[j],n[k],1); + if (Mns[j][k]!=0) L.Put(L.Get(n[j],n[k],2) + Mns[j][k],n[j],n[k],2); + if (Mna[j][k]!=0) L.Put(L.Get(n[j],n[k],3) + Mna[j][k],n[j],n[k],3); + } +//#endif + } + L.b[n[j]]+=be[j]; + } + } + + // add in contribution from point currents; + for(i=0;i=0){ + K=0.01*(nodeproplist[meshnode[i].bc].Jr + +I*nodeproplist[meshnode[i].bc].Ji); + L.b[i]+=(-K); + } + + // add in total current constraints for circuits; + for(i=0;i=0) + if((nodeproplist[meshnode[i].bc].Jr==0) && + (nodeproplist[meshnode[i].bc].Ji==0)) + { + K= (nodeproplist[meshnode[i].bc].Ar + + I*nodeproplist[meshnode[i].bc].Ai)/c; + L.SetValue(i,K); + } + + // apply fixed boundary conditions along segments; + for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + if(Coords==0){ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],K); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],K); + } + else{ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + r=sqrt(x*x+y*y); + if ((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],K); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + r=sqrt(x*x+y*y); + if((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],K); + } + + } + } + + // "fix" diagonal entries associated with circuits that have + // applied current or voltage that is known a priori + // so that solver doesn't throw a "singular" flag + for(j=0;j5) + { + if ((res>lastres) && (Relax>0.1)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + + for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); + j=(int) (100.*log10(res)/(log10(Precision)+2.)); + if (j>100) j=100; + TheView->m_prog2.SetPos(j); + } + + // nonlinear iteration has to have a looser tolerance + // than the linear solver--otherwise, things can't ever + // converge. Arbitrarily choose 100*tolerance. + if((res<100.*Precision) && Iter>0) LinearFlag=TRUE; + + Iter++; + +} while(LinearFlag==FALSE); + + for (i=0;i0){ + free(CircInt1); + free(CircInt2); + free(CircInt3); + } + + return TRUE; +} + +BOOL CFemmeDocCore::WriteHarmonic2D(CBigComplexLinProb &L) +{ + // write solution to disk; + + char c[1024]; + FILE *fp,*fz; + int i,k; + double cf; + double unitconv[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + + // first, echo input .fem file to the .ans file; + sprintf(c,"%s.fem",PathName); + if((fz=fopen(c,"rt"))==NULL){ + Sleep(500); + if((fz=fopen(c,"rt"))==NULL){ + MsgBox("Couldn't open %s.fem\n",PathName); + return FALSE; + } + } + + sprintf(c,"%s.ans",PathName); + if((fp=fopen(c,"wt"))==NULL){ + Sleep(500); + if((fp=fopen(c,"wt"))==NULL){ + MsgBox("Couldn't write to %s.ans\n",PathName); + return FALSE; + } + } + + while(fgets(c,1024,fz)!=NULL) fputs(c,fp); + fclose(fz); + + // then print out node, line, and element information + fprintf(fp,"[Solution]\n"); + cf=unitconv[LengthUnits]; + fprintf(fp,"%i\n",NumNodes); + for(i=0;i +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" +#include "lua.h" + +#define Log log + +extern lua_State *lua; + +BOOL CFemmeDocCore::StaticAxisymmetric(CBigLinProb &L) +{ + int i,j,k,s,w; + double Me[3][3],Mx[3][3],My[3][3],Mxy[3][3],Mn[3][3]; + double l[3],p[3],q[3],g[3],be[3],u[3],v[3],res,lastres,dv,vol; + int n[3]; // numbers of nodes for a particular element; + double a,K,r,t,x,y,B,mu,R,rn[3],a_hat,R_hat,Cduct; + double c=PI*4.e-05; + double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + double *V_old,*CircInt1,*CircInt2,*CircInt3;; + int flag,Iter=0,pctr; + BOOL LinearFlag=TRUE; + BOOL bIncremental = FALSE; + BOOL bRestart = FALSE; + double murel, muinc; + + if (PrevSoln.GetLength() > 0) bIncremental = PrevType; + res=0; + + CElement *El; + V_old=(double *) calloc(NumNodes,sizeof(double)); + + for(i=0;i0) + { + CircInt1=(double *)calloc(NumCircProps,sizeof(double)); + CircInt2=(double *)calloc(NumCircProps,sizeof(double)); + CircInt3=(double *)calloc(NumCircProps,sizeof(double)); + for(i=0;i=0) + if(labellist[meshele[i].lbl].InCircuit!=-1){ + El=&meshele[i]; + + // get element area; + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // if coils are wound, they act like they have + // a zero "bulk" conductivity... + Cduct=blockproplist[El->blk].Cduct; + if (labellist[El->lbl].bIsWound) Cduct=0; + + // evaluate integrals; + CircInt1[labellist[El->lbl].InCircuit]+=a; + + CircInt2[labellist[El->lbl].InCircuit]+= + 100.*a*Cduct/r; + + CircInt3[labellist[El->lbl].InCircuit]+= + blockproplist[El->blk].Jr*a*100.; + } + } + + for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); + TheView->m_prog1.SetPos(0); + pctr=0; + + if(Iter>0) L.Wipe(); + else{ + if (bIncremental==1) + { + // try to restart from a previous file of the same name + // to cut down on the time to solve the incremental problem + CString myFile; + myFile.Format("%s.ans",PathName); + if (LoadPrevA(myFile,L.V)) bRestart = 2; + } + else if ((bIncremental==0) && (PrevSoln.GetLength()>0)) + { + // load initial guess from the explicitly specified previous solution + bRestart = LoadPrevA(PrevSoln,L.V); + } + + if (bRestart>0) + { + for(i=0;i 1.e-06) L.V[i]/=(meshnode[i].x*0.01*2*PI); + } + } + + for(i=0;ipctr){ + j=pctr*5; if (j>100) j=100; + TheView->m_prog1.SetPos(j); + pctr++; + } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + Me[j][k] = 0.; + Mx[j][k] = 0.; + My[j][k] = 0.; + Mxy[j][k] = 0.; + Mn[j][k] = 0.; + } + be[j]=0.; + } + + // Determine shape parameters. + // l == element side lengths; + // p corresponds to the `b' parameter in Allaire + // q corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++){ + n[k]=El->p[k]; + rn[k]=meshnode[n[k]].x; + } + + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + g[0]=(meshnode[n[2]].x + meshnode[n[1]].x)/2.; + g[1]=(meshnode[n[0]].x + meshnode[n[2]].x)/2.; + g[2]=(meshnode[n[1]].x + meshnode[n[0]].x)/2.; + + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); + } + + a=(p[0]*q[1]-p[1]*q[0])/2.; + R=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + for(j=0,a_hat=0;j<3;j++) a_hat+=(rn[j]*rn[j]*p[j]/(4.*R)); + vol=2.*R*a_hat; + + for(j=0,flag=0;j<3;j++) if(rn[j]<1.e-06) flag++; + switch(flag) + { + case 2: + R_hat=R; + + break; + + case 1: + + if(rn[0]<1.e-06){ + if (fabs(rn[1]-rn[2])<1.e-06) R_hat=rn[2]/2.; + else R_hat=(rn[1] - rn[2])/(2.*log(rn[1]) - 2.*log(rn[2])); + } + if(rn[1]<1.e-06){ + if (fabs(rn[2]-rn[0])<1.e-06) R_hat=rn[0]/2.; + else R_hat=(rn[2] - rn[0])/(2.*log(rn[2]) - 2.*log(rn[0])); + } + if(rn[2]<1.e-06){ + if (fabs(rn[0]-rn[1])<1.e-06) R_hat=rn[1]/2.; + else R_hat=(rn[0] - rn[1])/(2.*log(rn[0]) - 2.*log(rn[1])); + } + + break; + + default: + + if (fabs(q[0])<1.e-06) + R_hat=(q[1]*q[1])/(2.*(-q[1] + rn[0]*log(rn[0]/rn[2]))); + else if (fabs(q[1])<1.e-06) + R_hat=(q[2]*q[2])/(2.*(-q[2] + rn[1]*log(rn[1]/rn[0]))); + else if (fabs(q[2])<1.e-06) + R_hat=(q[0]*q[0])/(2.*(-q[0] + rn[2]*log(rn[2]/rn[1]))); + else + R_hat=-(q[0]*q[1]*q[2])/ + (2.*(q[0]*rn[0]*log(rn[0]) + + q[1]*rn[1]*log(rn[1]) + + q[2]*rn[2]*log(rn[2]))); + + break; + } + + // Mr Contribution + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K=(-1./(2.*a_hat*R)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + Mx[j][k] += K*p[j]*rn[j]*p[k]*rn[k]; + + // need this loop to avoid singularities. This just puts something + // on the main diagonal of nodes that are on the r=0 line. + // The program later sets these nodes to zero, but it's good to + // for scaling reasons to grab entries from the neighboring diagonals + // rather than just setting these entries to 1 or something.... + for(j=0;j<3;j++) + if (rn[j]<1.e-06) Mx[j][j]+=Mx[0][0]+Mx[1][1]+Mx[2][2]; + + // Mz Contribution; + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K=(-1./(2.*a_hat*R_hat)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + My[j][k] += K*(q[j]*rn[j])*(q[k]*rn[k])* + (g[j]/R)*(g[k]/R); + + // Mrz Contribution; + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K = (-1. / (2.*a_hat*R_hat)); + for (j = 0;j<3;j++) + for (k = j;k<3;k++) + Mxy[j][k] += K*((q[j] * rn[j])*(g[j] / R))*(p[k] * rn[k]) + K*((q[k] * rn[k])*(g[k] / R))*(p[j] * rn[j]); + + // Fill out rest of entries of Mx and My; + Mx[1][0]=Mx[0][1]; Mx[2][0]=Mx[0][2]; Mx[2][1]=Mx[1][2]; + My[1][0]=My[0][1]; My[2][0]=My[0][2]; My[2][1]=My[1][2]; + Mxy[1][0] = Mxy[0][1]; Mxy[2][0] = Mxy[0][2]; Mxy[2][1] = Mxy[1][2]; + + // contributions to Me, be from derivative boundary conditions; + for(j=0;j<3;j++){ + if (El->e[j] >= 0) + if (lineproplist[El->e[j]].BdryFormat==2) + { + // conversion factor is 10^(-4) (I think...) + k=j+1; if(k==3) k=0; + r=(meshnode[n[j]].x+meshnode[n[k]].x)/2.; + K=-0.0001*c*2.*r*lineproplist[ El->e[j] ].c0.re*l[j]/6.; + k=j+1; if(k==3) k=0; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K=(lineproplist[ El->e[j] ].c1.re*l[j]/2.)*0.0001*2*r; + be[j]+=K; + be[k]+=K; + } + } + + // contribution to be from current density in the block + for(j=0,El->Jprev=0;j<3;j++) + { + if(labellist[El->lbl].InCircuit>=0) + { + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==1) t=circproplist[k].J.Re(); + if(circproplist[k].Case==0) + t=-100.*circproplist[k].dV.Re()*blockproplist[El->blk].Cduct/R; + } + else t=0; + K=-2.*R*(blockproplist[El->blk].Jr+t)*a/3.; + be[j]+=K; + + // record avg current density in the block for use in incremental solutions + if (bIncremental==FALSE) El->Jprev+=(blockproplist[El->blk].Jr+t)/3.; + } + + // contribution to be from magnetization in the block; + t=labellist[El->lbl].MagDir; + if (labellist[El->lbl].MagDirFctn!=NULL) // functional magnetization direction + { + CString str; + CComplex X; + int top1,top2; + for (j=0,X=0;j<3;j++) X+=(meshnode[n[j]].x + I*meshnode[n[j]].y); + X=X/units[LengthUnits]/3.; + str.Format("r=%.17g\nz=%.17g\nx=r\ny=z\ntheta=%.17g\nR=%.17g\nreturn %s", + X.re,X.im,arg(X)*180/PI,abs(X),labellist[El->lbl].MagDirFctn); + top1=lua_gettop(lua); + if(lua_dostring(lua,str)!=0) + { + MsgBox("Lua error evaluating \"%s\"",labellist[El->lbl].MagDirFctn); + exit(7); + } + top2=lua_gettop(lua); + if (top2!=top1){ + str=lua_tostring(lua,-1); + if (str.GetLength()==0){ + MsgBox("\"%s\" does not evaluate to a numerical value", + labellist[El->lbl].MagDirFctn); + exit(7); + } + else t=Re(lua_tonumber(lua,-1)); + } + } + for(j=0;j<3;j++){ + k=j+1; if(k==3) k=0; + r=(meshnode[n[j]].x+meshnode[n[k]].x)/2.; + // need to scale so that everything is in proper units... + // conversion is 0.0001 + K=-0.0001*r*blockproplist[El->blk].H_c*( + cos(t*PI/180.)*(meshnode[n[k]].x-meshnode[n[j]].x) + + sin(t*PI/180.)*(meshnode[n[k]].y-meshnode[n[j]].y) ); + be[j]+=K; + be[k]+=K; + } + + // update permeability for the element; + if (Iter==0){ + k=meshele[i].blk; + + if (blockproplist[k].LamType == 0) { + mu = blockproplist[k].LamFill; + meshele[i].mu1 = blockproplist[k].mu_x*mu; + meshele[i].mu2 = blockproplist[k].mu_y*mu; + } + if (blockproplist[k].LamType == 1) { + mu = blockproplist[k].LamFill; + K = blockproplist[k].mu_x; + meshele[i].mu1 = K*mu + (1. - mu); + meshele[i].mu2 = K / (mu + K*(1. - mu)); + } + if (blockproplist[k].LamType == 2) { + mu = blockproplist[k].LamFill; + K = blockproplist[k].mu_y; + meshele[i].mu1 = K*mu + (1. - mu); + meshele[i].mu2 = K / (mu + K*(1. - mu)); + } + if (blockproplist[k].LamType>2) + { + meshele[i].mu1 = 1; + meshele[i].mu2 = 1; + } + + if (blockproplist[k].BHpoints != 0) + { + if (bIncremental == FALSE) + { + // There's no previous solution. This is a standard nonlinear problem + LinearFlag = FALSE; + } + else { + double B1p, B2p; + + // too lazy to consistently code incremental/frozen formulation for on-edge lams. + // detect this condition, throw an error, and exit. + if (blockproplist[k].LamType > 0) + { + MsgBox("On-edge Lam Types not yet supported in\nincremental/frozen permeability problems"); + exit(0); + } + + // Get B from previous solution + GetPrevAxiB(i,B1p,B2p); + B = sqrt(B1p*B1p + B2p*B2p); + + // look up incremental permeability and assign it to the element; + blockproplist[k].IncrementalPermeability(B, muinc, murel); + if (B == 0) + { + meshele[i].mu1 = muinc; + meshele[i].mu2 = muinc; + meshele[i].v12 = 0; + } + else { + if (bIncremental == 1) + { + // MsgBox("muinc = %g, murel=%g",muinc,murel); + // Need to actually compute B1 and B2 to build incremental permeability tensor + meshele[i].mu1 = B*B*muinc*murel / (B1p*B1p*murel + B2p*B2p*muinc); + meshele[i].mu2 = B*B*muinc*murel / (B1p*B1p*muinc + B2p*B2p*murel); + meshele[i].v12 = -B1p*B2p*(murel - muinc) / (B*B*murel*muinc); + } + else { + // Define "frozen permeability" + meshele[i].mu1 = murel; + meshele[i].mu2 = murel; + meshele[i].v12 = 0; + } + } + } + } + } + + if ((Iter>0) || (bRestart==TRUE)) + { + k=meshele[i].blk; + + if ((blockproplist[k].LamType==0) && + (meshele[i].mu1==meshele[i].mu2) + &&(blockproplist[k].BHpoints>0)) + { + // Derive B directly from energy; + v[0]=0;v[1]=0;v[2]=0; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + v[j]+=(Mx[j][w]+My[j][w])*L.V[n[w]]; + for(j=0,dv=0;j<3;j++) dv+=L.V[n[j]]*v[j]; + dv*=(10000.*c*c/vol); + B=sqrt(fabs(dv)); + + // find out new mu from saturation curve; + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu; + meshele[i].mu2=mu; + for(j=0;j<3;j++){ + for(w=0,v[j]=0;w<3;w++) + v[j]+=(Mx[j][w]+My[j][w])*L.V[n[w]]; + } + + K=-200.*c*c*c*dv/vol; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*v[j]*v[w]; + } + + if ((blockproplist[k].LamType==1) && (blockproplist[k].BHpoints>0)){ + + // Derive B directly from energy; + t=blockproplist[k].LamFill; + v[0]=0;v[1]=0;v[2]=0; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + v[j]+=(Mx[j][w]+My[j][w]/(t*t))*L.V[n[w]]; + for(j=0,dv=0;j<3;j++) dv+=L.V[n[j]]*v[j]; + dv*=(10000.*c*c/vol); + B=sqrt(fabs(dv)); + + // Evaluate BH curve + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu*t; + meshele[i].mu2=mu/(t+mu*(1.-t)); + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(My[j][w]/t+Mx[j][w])*L.V[n[w]]; + u[j]+=(My[j][w]/t + t*Mx[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(vol); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + } + if ((blockproplist[k].LamType==2) && (blockproplist[k].BHpoints>0)){ + + // Derive B directly from energy; + t=blockproplist[k].LamFill; + v[0]=0;v[1]=0;v[2]=0; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + v[j]+=(Mx[j][w]/(t*t)+My[j][w])*L.V[n[w]]; + for(j=0,dv=0;j<3;j++) dv+=L.V[n[j]]*v[j]; + dv*=(10000.*c*c/vol); + B=sqrt(fabs(dv)); + + // Evaluate BH curve + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu2=mu*t; + meshele[i].mu1=mu/(t+mu*(1.-t)); + + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(Mx[j][w]/t + My[j][w])*L.V[n[w]]; + u[j]+=(Mx[j][w]/t + t*My[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(vol); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + + } + } + + // "Warp" the permeability of this element if part of + // the conformally mapped external region + if((labellist[meshele[i].lbl].IsExternal) && (Iter==0)) + { + double Z=(meshnode[n[0]].y+meshnode[n[1]].y+meshnode[n[2]].y)/3. - extZo; + double kludge=(R*R+Z*Z)*extRi/(extRo*extRo*extRo); + meshele[i].mu1/=kludge; + meshele[i].mu2/=kludge; + } + + // combine block matrices into global matrices; + for(j=0;j<3;j++) + for(k=0;k<3;k++){ + Me[j][k]+= (Mx[j][k]/Re(El->mu2) + My[j][k]/Re(El->mu1) + Mxy[j][k] * Re(El->v12) + Mn[j][k]); + be[j]+=Mn[j][k]*L.V[n[k]]; + } + + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.Put(L.Get(n[j],n[k])-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // add in contribution from point currents; + for(i=0;i=0) + { + r=meshnode[i].x; + L.b[i]+=(0.01*nodeproplist[meshnode[i].bc].Jr*2.*r); + } + + // apply fixed boundary conditions at points; + for(i=0;i=0) + if((nodeproplist[meshnode[i].bc].Jr==0) && + (nodeproplist[meshnode[i].bc].Ji==0)) + L.SetValue(i,nodeproplist[meshnode[i].bc].Ar/c); + } + + // apply fixed boundary conditions along segments; + for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + if(Coords==0){ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take ``real'' component. + a*=cos(lineproplist[s].phi*DEG); + if(x!=0) L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take``real'' component. + a*=cos(lineproplist[s].phi*DEG); + if (x!=0) L.SetValue(meshele[i].p[k],a/c); + } + else{ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + r=sqrt(x*x+y*y); + if((x==0)&&(y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + if (x!=0) L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + r=sqrt(x*x+y*y); + if((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + if (x!=0) L.SetValue(meshele[i].p[k],a/c); + } + + } + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0;k5) + { + if ((res>lastres) && (Relax>0.125)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + + for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); + j=(int) (100.*log10(res)/(log10(Precision)+2.)); + if (j>100) j=100; + TheView->m_prog2.SetPos(j); + } + + // nonlinear iteration has to have a looser tolerance + // than the linear solver--otherwise, things can't ever + // converge. Arbitrarily choose 100*tolerance. + if((res<100.*Precision) && Iter>0) LinearFlag=TRUE; + + Iter++; + +} while(LinearFlag==FALSE); + + // convert answer back to Webers for plotting purposes. + for (i=0;i0){ + free(CircInt1); + free(CircInt2); + free(CircInt3); + } + + return TRUE; +} diff --git a/fkn/prob4big.cpp b/fkn/prob4big.cpp new file mode 100644 index 0000000..35b8a7a --- /dev/null +++ b/fkn/prob4big.cpp @@ -0,0 +1,806 @@ +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" +#define Log log + +// #define NEWTON + +// since all node positions were converted to units of cm +// the proper LengthConv is converts centimeters to meters +#define LengthConv 0.01 + +void CFemmeDocCore::GetPrevAxiB(int k, double &B1p, double &B2p) +{ + // for axisymmetric incremental problem, + // get flux density from the previous solution. + // Code cribbed from CFemmviewDoc::GetElementB(CElement &elm) in femm source + int i,n[3]; + double b[3],c[3],da; + double v[6],dp,dq; + double R[3],Z[3],r; + + for(i=0;i<3;i++) n[i]=meshele[k].p[i]; + + b[0]=meshnode[n[1]].y - meshnode[n[2]].y; + b[1]=meshnode[n[2]].y - meshnode[n[0]].y; + b[2]=meshnode[n[0]].y - meshnode[n[1]].y; + c[0]=meshnode[n[2]].x - meshnode[n[1]].x; + c[1]=meshnode[n[0]].x - meshnode[n[2]].x; + c[2]=meshnode[n[1]].x - meshnode[n[0]].x; + + for(i=0,r=0;i<3;i++){ + R[i]=meshnode[n[i]].x; + Z[i]=meshnode[n[i]].y; + r+=R[i]/3.; + } + + // corner nodes + v[0]=Aprev[n[0]]; + v[2]=Aprev[n[1]]; + v[4]=Aprev[n[2]]; + + // construct values for mid-side nodes; + if ((R[0]<1.e-06) && (R[1]<1.e-06)) v[1]=(v[0]+v[2])/2.; + else v[1]=(R[1]*(3.*v[0] + v[2]) + R[0]*(v[0] + 3.*v[2]))/ + (4.*(R[0] + R[1])); + + if ((R[1]<1.e-06) && (R[2]<1.e-06)) v[3]=(v[2]+v[4])/2.; + else v[3]=(R[2]*(3.*v[2] + v[4]) + R[1]*(v[2] + 3.*v[4]))/ + (4.*(R[1] + R[2])); + + if ((R[2]<1.e-06) && (R[0]<1.e-06)) v[5]=(v[4]+v[0])/2.; + else v[5]=(R[0]*(3.*v[4] + v[0]) + R[2]*(v[4] + 3.*v[0]))/ + (4.*(R[2] + R[0])); + + // derivatives w.r.t. p and q: + dp=(-v[0] + v[2] + 4.*v[3] - 4.*v[5])/3.; + dq=(-v[0] - 4.*v[1] + 4.*v[3] + v[4])/3.; + + // now, compute flux. + da=(b[0]*c[1]-b[1]*c[0]); + da*=2.*PI*r*LengthConv*LengthConv; + B1p=Re(-(c[1]*dp+c[2]*dq)/da); + B2p=Re( (b[1]*dp+b[2]*dq)/da); +} + +BOOL CFemmeDocCore::HarmonicAxisymmetric(CBigComplexLinProb &L) +{ + int i,j,k,s,flag,ww,Iter=0; + int pctr; + CComplex Mx[3][3],My[3][3],Mxy[3][3],Mn[3][3],Me[3][3],be[3]; // element matrices; + double l[3],p[3],q[3]; // element shape parameters; + int n[3]; // numbers of nodes for a particular element; + double a,r,t,x,y,B,w,res,lastres,ds,R,rn[3],g[3],a_hat,R_hat,vol,Cduct; + CComplex K,mu,dv,B1,B2,v[3],u[3],mu1,mu2,lag,halflag,deg45,Jv; + CComplex **Mu,*V_old; + double c=PI*4.e-05; + double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + CElement *El; + BOOL LinearFlag=TRUE; + BOOL bIncremental=FALSE; + + if (PrevSoln.GetLength()>0) bIncremental=TRUE; + res=0; + +// #ifndef NEWTON + CComplex murel,muinc; +// #else + CComplex Mnh[3][3]; + CComplex Mna[3][3]; + CComplex Mns[3][3]; +// #endif + + extRo*=units[LengthUnits]; + extRi*=units[LengthUnits]; + extZo*=units[LengthUnits]; + + deg45=1+I; + w=Frequency*2.*PI; + + CComplex *CircInt1,*CircInt2,*CircInt3; + + + // Can't handle LamType==1 or LamType==2 in AC problems. + // Detect if this is being attempted. + for(i=0;i0) + { + CircInt1=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + CircInt2=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + CircInt3=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); + for(i=0;i=0) + if(labellist[meshele[i].lbl].InCircuit!=-1){ + El=&meshele[i]; + + // get element area; + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // if coils are wound, they act like they have + // a zero "bulk" conductivity... + Cduct=blockproplist[El->blk].Cduct; + if (labellist[El->lbl].bIsWound) Cduct=0; + + // evaluate integrals; + + // total cross-section of circuit; + CircInt1[labellist[El->lbl].InCircuit]+=a; + + // integral of conductivity / R over the circuit; + CircInt2[labellist[El->lbl].InCircuit]+=a*Cduct/(0.01*r); + + // integral of applied J over current; + CircInt3[labellist[El->lbl].InCircuit]+= + (blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji)*a*100.; + } + } + + for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); + TheView->m_prog1.SetPos(0); + pctr=0; + + if (Iter>0) L.Wipe(); + + // build element matrices using the matrices derived in Allaire's book. + for(i=0;ipctr){ + j=pctr*5; if (j>100) j=100; + TheView->m_prog1.SetPos(j); + pctr++; + } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++) + { + Me[j][k]=0; + Mx[j][k]=0; + My[j][k]=0; + Mxy[j][k]=0; + Mn[j][k]=0; +// #ifdef NEWTON + if (ACSolver==1){ + Mnh[j][k]=0; + Mna[j][k]=0; + Mns[j][k]=0; + } +// #endif + } + be[j]=0; + } + + // Determine shape parameters. + // l == element side lengths; + // p corresponds to the `b' parameter in Allaire + // q corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++){ + n[k]=El->p[k]; + rn[k]=meshnode[n[k]].x; + } + + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + g[0]=(meshnode[n[2]].x + meshnode[n[1]].x)/2.; + g[1]=(meshnode[n[0]].x + meshnode[n[2]].x)/2.; + g[2]=(meshnode[n[1]].x + meshnode[n[0]].x)/2.; + + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + R=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + for(j=0,a_hat=0;j<3;j++) a_hat+=(rn[j]*rn[j]*p[j]/(4.*R)); + vol=2.*R*a_hat; + + for(j=0,flag=0;j<3;j++) if(rn[j]<1.e-06) flag++; + switch(flag) + { + case 2: + R_hat=R; + + break; + + case 1: + + if(rn[0]<1.e-06){ + if (fabs(rn[1]-rn[2])<1.e-06) R_hat=rn[2]/2.; + else R_hat=(rn[1] - rn[2])/(2.*log(rn[1]) - 2.*log(rn[2])); + } + if(rn[1]<1.e-06){ + if (fabs(rn[2]-rn[0])<1.e-06) R_hat=rn[0]/2.; + else R_hat=(rn[2] - rn[0])/(2.*log(rn[2]) - 2.*log(rn[0])); + } + if(rn[2]<1.e-06){ + if (fabs(rn[0]-rn[1])<1.e-06) R_hat=rn[1]/2.; + else R_hat=(rn[0] - rn[1])/(2.*log(rn[0]) - 2.*log(rn[1])); + } + + break; + + default: + + if (fabs(q[0])<1.e-06) + R_hat=(q[1]*q[1])/(2.*(-q[1] + rn[0]*log(rn[0]/rn[2]))); + else if (fabs(q[1])<1.e-06) + R_hat=(q[2]*q[2])/(2.*(-q[2] + rn[1]*log(rn[1]/rn[0]))); + else if (fabs(q[2])<1.e-06) + R_hat=(q[0]*q[0])/(2.*(-q[0] + rn[2]*log(rn[2]/rn[1]))); + else + R_hat=-(q[0]*q[1]*q[2])/ + (2.*(q[0]*rn[0]*log(rn[0]) + + q[1]*rn[1]*log(rn[1]) + + q[2]*rn[2]*log(rn[2]))); + + break; + } + + // Mr Contribution + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K=(-1./(2.*a_hat*R)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + Mx[j][k] += K*p[j]*rn[j]*p[k]*rn[k]; + + // need this loop to avoid singularities. This just puts something + // on the main diagonal of nodes that are on the r=0 line. + // The program later sets these nodes to zero, but it's good to + // for scaling reasons to grab entries from the neighboring diagonals + // rather than just setting these entries to 1 or something.... + for(j=0;j<3;j++) + if (rn[j]<1.e-06) Mx[j][j]+=Mx[0][0]+Mx[1][1]+Mx[2][2]; + + // Mz Contribution; + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K=(-1./(2.*a_hat*R_hat)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + My[j][k] += K*(q[j]*rn[j])*(q[k]*rn[k])*(g[j]/R)*(g[k]/R); + + // Mrz Contribution; + // Derived from flux formulation with c0 + c1 r^2 + c2 z + // interpolation in the element. + K=(-1./(2.*a_hat*R_hat)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + // My[j][k] += K * ((q[j]*rn[j])*(g[j]/R)) * ((q[k]*rn[k])*(g[k]/R)); + // Mx[j][j] += K * (p[j]*rn[j]) * (p[k]*rn[k]); + Mxy[j][k] += K*((q[j]*rn[j])*(g[j]/R))*(p[k]*rn[k]) + K*((q[k]*rn[k])*(g[k]/R))*(p[j]*rn[j]); + + // Fill out rest of entries of Mx, My and Mxy; + Mx[1][0] =Mx[0][1]; Mx[2][0] =Mx[0][2]; Mx[2][1] =Mx[1][2]; + My[1][0] =My[0][1]; My[2][0] =My[0][2]; My[2][1] =My[1][2]; + Mxy[1][0]=Mxy[0][1]; Mxy[2][0]=Mxy[0][2]; Mxy[2][1]=Mxy[1][2]; + + + // contribution from eddy currents; + // induced current interpolated as constant (avg. of nodal values) + // over the entire element; + K = -I*R*a*w*blockproplist[meshele[i].blk].Cduct*c/6.; + + // radially laminated blocks appear to have no conductivity; + // eddy currents are accounted for in these elements by their + // frequency-dependent permeability. + if((blockproplist[El->blk].LamType==0) && + (blockproplist[El->blk].Lam_d>0)) K=0; + + // if this element is part of a wound coil, + // it should have a zero "bulk" conductivity... + if(labellist[El->lbl].bIsWound) K=0; + + for(j=0;j<3;j++) + for(k=0;k<3;k++) + Me[j][k]+=K*4./3.; + + // contributions to Me, be from derivative boundary conditions; + for(j=0;j<3;j++){ + k=j+1; if(k==3) k=0; + r=(meshnode[n[j]].x+meshnode[n[k]].x)/2.; + if (El->e[j] >= 0){ + + if (lineproplist[El->e[j]].BdryFormat==2) + { + // conversion factor is 10^(-4) (I think...) + + K = -0.0001*c*2.*r*lineproplist[ El->e[j] ].c0*l[j]/6.; + Me[j][j]+=2*K; + Me[k][k]+=2*K; + Me[j][k]+=K; + Me[k][j]+=K; + + K = (lineproplist[ El->e[j] ].c1*l[j]/2.)*2.*r*0.0001; + be[j]+=K; + be[k]+=K; + } + + if (lineproplist[El->e[j]].BdryFormat==1) + { + ds=sqrt(2./(0.4*PI*w*lineproplist[El->e[j]].Sig* + lineproplist[El->e[j]].Mu)); + K=deg45/(-ds*lineproplist[El->e[j]].Mu*100.); + K*=(2.*r*l[j]/6.); + Me[j][j]+=2*K; + Me[k][k]+=2*K; + Me[j][k]+=K; + Me[k][j]+=K; + } + + } + } + + // contribution to be from current density in the block + for(j=0;j<3;j++){ + Jv=0; + if(labellist[El->lbl].InCircuit>=0) + { + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==1) Jv=circproplist[k].J; + if(circproplist[k].Case==0) + Jv=-100.*circproplist[k].dV* + blockproplist[El->blk].Cduct/R; + } + + K=-2.*R*(blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji+Jv)*a/3.; + be[j]+=K; + + if(labellist[El->lbl].InCircuit>=0){ + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==2) + L.b[NumNodes+k]+=K/R; + } + } + + // do Case 2 circuit stuff for element + if(labellist[El->lbl].InCircuit>=0){ + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==2){ + K=-2.*I*a*w*blockproplist[meshele[i].blk].Cduct*c; + for(j=0;j<3;j++) + L.Put(L.Get(n[j],NumNodes+k)+K/3.,n[j],NumNodes+k); + L.Put(L.Get(NumNodes+k,NumNodes+k)+K/R,NumNodes+k,NumNodes+k); + } + } + +///////////////////////// +// +// Nonlinear Stuff +// +///////////////////////// + + // update permeability for the element; + if (Iter==0){ + k=meshele[i].blk; + meshele[i].mu1=Mu[k][0]; + meshele[i].mu2=Mu[k][1]; + meshele[i].v12=0; + if (blockproplist[k].BHpoints > 0) + { + if (bIncremental==FALSE) LinearFlag=FALSE; + else{ + double B1p,B2p; + + // Get B from previous solution + GetPrevAxiB(i,B1p,B2p); + B = sqrt(B1p*B1p + B2p*B2p); + + // look up incremental permeability and assign it to the element; + blockproplist[k].IncrementalPermeability(B,w,muinc,murel); + if (B==0) + { + meshele[i].mu1=muinc; + meshele[i].mu2=muinc; + meshele[i].v12=0; + } + else{ + // need to actually compute B1 and B2 to build incremental permeability tensor + meshele[i].mu1=B*B*muinc*murel/(B1p*B1p*murel + B2p*B2p*muinc); + meshele[i].mu2=B*B*muinc*murel/(B1p*B1p*muinc + B2p*B2p*murel); + meshele[i].v12=-B1p*B2p*(murel-muinc)/(B*B*murel*muinc); + } + + } + } + } + else{ + k=meshele[i].blk; + + if ((blockproplist[k].LamType==0) && + (meshele[i].mu1==meshele[i].mu2) + &&(blockproplist[k].BHpoints>0)) + { + // Derive B directly from energy; + v[0]=0;v[1]=0;v[2]=0; + for(j=0;j<3;j++) + for(ww=0;ww<3;ww++) + v[j]+=(Mx[j][ww]+My[j][ww])*L.V[n[ww]]; + for(j=0,dv=0;j<3;j++) dv+=conj(L.V[n[j]])*v[j]; + dv*=(10000.*c*c/vol); + B=sqrt(abs(dv)); + +// #ifdef NEWTON + if (ACSolver==1) + { + // find out new mu from saturation curve; + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu; + meshele[i].mu2=mu; + for(j=0;j<3;j++){ + for(ww=0,v[j]=0;ww<3;ww++) + v[j]+=(Mx[j][ww]+My[j][ww])*L.V[n[ww]]; + } + + // Newton iteration + K=-200.*c*c*c*dv/vol; + for(j=0;j<3;j++) + for(ww=0;ww<3;ww++) + { + // Still compute Mn, the approximate N-R matrix used in + // the complex-symmetric approx. This will be useful + // w.r.t. preconditioning. However, subtract it off of Mnh and Mna + // so that there is no net addition. + Mn[j][ww] =K*Re(v[j]*conj(v[ww])); + Mnh[j][ww]= 0.5*Re(K)*v[j]*conj(v[ww])-Re(Mn[j][ww]); + Mna[j][ww]=I*0.5*Im(K)*v[j]*conj(v[ww])-I*Im(Mn[j][ww]); + Mns[j][ww]= 0.5*K*v[j]*v[ww]; + } + } +// #else + else{ + // find out new mu from saturation curve; + murel=1./(muo*blockproplist[k].Get_v(B)); + muinc=1./(muo*blockproplist[k].GetdHdB(B)); + + // successive approximation; + // K=muinc; // total incremental + // K=murel; // total updated + K=2.*murel*muinc/(murel+muinc); // averaged + meshele[i].mu1=K; + meshele[i].mu2=K; + K=-(1./murel - 1/K); + for(j=0;j<3;j++) + for(ww=0;ww<3;ww++) + Mn[j][ww]=K*(Mx[j][ww]+My[j][ww]); + } +// #endif + } + } + + // Apply correction for elements subject to prox effects + if((blockproplist[meshele[i].blk].LamType>2) && (Iter==0)) + { + meshele[i].mu1=labellist[meshele[i].lbl].ProximityMu; + meshele[i].mu2=labellist[meshele[i].lbl].ProximityMu; + } + + // "Warp" the permeability of this element if part of + // the conformally mapped external region + if((labellist[meshele[i].lbl].IsExternal) && (Iter==0)) + { + double Z=(meshnode[n[0]].y+meshnode[n[1]].y+meshnode[n[2]].y)/3. - extZo; + double kludge=(R*R+Z*Z)*extRi/(extRo*extRo*extRo); + meshele[i].mu1/=kludge; + meshele[i].mu2/=kludge; + } + + // combine block matrices into global matrices; + for(j=0;j<3;j++) + for(k=0;k<3;k++){ +//#ifdef NEWTON + if (ACSolver==1){ + Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k]*(El->v12) + Mn[j][k]); + be[j]+=(Mnh[j][k]+Mna[j][k]+Mn[j][k])*L.V[n[k]]; + be[j]+=Mns[j][k]*L.V[n[k]].Conj(); + } +//#else + else{ + Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k] * (El->v12)); + be[j]+=Mn[j][k]*L.V[n[k]]; + } +//#endif + + } + + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + { + L.Put(L.Get(n[j],n[k])+Me[j][k],n[j],n[k]); +//#ifdef NEWTON + if (ACSolver==1){ + if (Mnh[j][k]!=0) L.Put(L.Get(n[j],n[k],1) + Mnh[j][k],n[j],n[k],1); + if (Mns[j][k]!=0) L.Put(L.Get(n[j],n[k],2) + Mns[j][k],n[j],n[k],2); + if (Mna[j][k]!=0) L.Put(L.Get(n[j],n[k],3) + Mna[j][k],n[j],n[k],3); + } +//#endif + } + L.b[n[j]]+=be[j]; + } + +/////////////////////////////////////////////////// + + } + + // add in contribution from point currents; + for(i=0;i=0){ + r=meshnode[i].x; + K = (2.*r*0.01)*(nodeproplist[meshnode[i].bc].Jr + + I*nodeproplist[meshnode[i].bc].Ji); + L.b[i]-=K; + } + + // add in total current constraints for circuits; + for(i=0;i=0) + if((nodeproplist[meshnode[i].bc].Jr==0) && + (nodeproplist[meshnode[i].bc].Ji==0)) + { + K = (nodeproplist[meshnode[i].bc].Ar + + I*nodeproplist[meshnode[i].bc].Ai) / c; + L.SetValue(i,K); + } + + // apply fixed boundary conditions along segments; + for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + if(Coords==0){ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],K); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],K); + } + else{ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + r=sqrt(x*x+y*y); + if ((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],K); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + r=sqrt(x*x+y*y); + if((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + K=(a/c)*exp(I*lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],K); + } + + } + } + + // "fix" diagonal entries associated with circuits that have + // applied current or voltage that is known a priori + // so that solver doesn't throw a "singular" flag + for(j=0;j5) + { + if ((res>lastres) && (Relax>0.1)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + + for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); + j=(int) (100.*log10(res)/(log10(Precision)+2.)); + if (j>100) j=100; + TheView->m_prog2.SetPos(j); + } + + // nonlinear iteration has to have a looser tolerance + // than the linear solver--otherwise, things can't ever + // converge. Arbitrarily choose 100*tolerance. + if((res<100.*Precision) && Iter>0) LinearFlag=TRUE; + + Iter++; + +} while(LinearFlag==FALSE); + + + // convert answer back to webers + for (i=0;i0){ + free(CircInt1); + free(CircInt2); + free(CircInt3); + } + return TRUE; +} diff --git a/fkn/res/fkn.ico b/fkn/res/fkn.ico new file mode 100644 index 0000000..e50c89a Binary files /dev/null and b/fkn/res/fkn.ico differ diff --git a/fkn/spars.cpp b/fkn/spars.cpp new file mode 100644 index 0000000..f175edc --- /dev/null +++ b/fkn/spars.cpp @@ -0,0 +1,422 @@ +#include +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "spars.h" + +#define KLUDGE + +CEntry::CEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigLinProb::CBigLinProb() +{ + n=0; +} + +CBigLinProb::~CBigLinProb() +{ + if (n==0) return; + + int i; + CEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + + free(M); +} + +int CBigLinProb::Create(int d, int bw) +{ + int i; + + bdw=bw; + b=(double *)calloc(d,sizeof(double)); + V=(double *)calloc(d,sizeof(double)); + P=(double *)calloc(d,sizeof(double)); + R=(double *)calloc(d,sizeof(double)); + U=(double *)calloc(d,sizeof(double)); + Z=(double *)calloc(d,sizeof(double)); + + M=(CEntry **)calloc(d,sizeof(CEntry *)); + n=d; + + for(i=0;ic = i; + } + + return 1; +} + +void CBigLinProb::Put(double v, int p, int q) +{ + CEntry *e,*l; + int i; + + if(qc < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CEntry *m = new CEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + return; +} + +double CBigLinProb::Get(int p, int q) +{ + CEntry *e; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) return e->x; + + return 0; +} + +void CBigLinProb::AddTo(double v, int p, int q) +{ + Put(Get(p,q)+v,p,q); +} + +void CBigLinProb::MultA(double *X, double *Y) +{ + int i; + CEntry *e; + + for(i=0;ix*X[i]; + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=e->x*X[e->c]; + Y[e->c]+=e->x*X[i]; + e=e->next; + } + } +} + +double CBigLinProb::Dot(double *X, double *Y) +{ + int i; + double z; + + for(i=0,z=0;ix; + + // SSOR preconditioner: + int i; + double c; + CEntry *e; + + c= LAMBDA*(2.-LAMBDA); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * LAMBDA; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * LAMBDA; + e=e->next; + } + Y[i]/= M[i]->x; + } +} + +int CBigLinProb::PCGSolve(int flag) +{ + int i; + double res,res_o,res_new; + double er,del,rho,pAp; + + // quick check for most obvious sign of singularity; + for(i=0;ix==0){ + fprintf(stderr,"singular flag tripped."); + return 0; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"Conjugate Gradient Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // residual with V=0 + MultPC(b,Z); + res_o=Dot(Z,b); + if(res_o==0) return 1; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>Precision); + + return 1; +} + +void CBigLinProb::SetValue(int i, double x) +{ + int k,fst,lst; + double z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>n) lst=n; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigLinProb::AntiPeriodicity(int i, int j) +{ + int k,fst,lst; + double v1,v2,c; + +#ifdef KLUDGE + int tmpbdw=bdw; + bdw=0; +#endif + + if (jn) lst=n; + } + + for(k=fst;kn) lst=n; + } + + for(k=fst;knext != NULL) e=e->next; + bw=e->c - k; + if (bw>maxbw) maxbw=bw; + } + + MsgBox("Assumed Bandwidth = %i\nActual Bandwidth = %i",bdw,maxbw); +} \ No newline at end of file diff --git a/fkn/spars.h b/fkn/spars.h new file mode 100644 index 0000000..e97c9cf --- /dev/null +++ b/fkn/spars.h @@ -0,0 +1,131 @@ +class CEntry +{ + public: + + double x; // value stored in the entry + int c; // column that the entry lives in + CEntry *next; // pointer to next entry in row; + CEntry(); + + private: +}; + +#define LAMBDA 1.5 + +class CBigLinProb +{ + public: + + // data members + + double *V; // solution + double *P; // search direction; + double *R; // residual; + double *U; // A * P; + double *Z; + double *b; // RHS of linear equation + CEntry **M; // pointer to list of matrix entries; + int n; // dimensions of the matrix; + int bdw; // Optional matrix bandwidth parameter; + double Precision; // error tolerance for solution + + // member functions + + CBigLinProb(); // constructor + ~CBigLinProb(); // destructor + int Create(int d, int bw); // initialize the problem + void Put(double v, int p, int q); + // use to create/set entries in the matrix + double Get(int p, int q); + void AddTo(double v, int p, int q); + int PCGSolve(int flag); // flag==true if guess for V present; + void MultPC(double *X, double *Y); + void MultA(double *X, double *Y); + void SetValue(int i, double x); + void Periodicity(int i, int j); + void AntiPeriodicity(int i, int j); + void Wipe(); + double Dot(double *X, double *Y); + void ComputeBandwidth(); + + CFknDlg *TheView; + + private: + +}; + + +///////////////////////////////////////////////////////////////////// +// for complex matrices...... + +class CComplexEntry +{ + public: + + CComplex x; // value stored in the entry + int c; // column that the entry lives in + CComplexEntry *next; // pointer to next entry in the row; + CComplexEntry(); + + private: +}; + +class CBigComplexLinProb +{ + public: + + // data members + + CComplex *P; // search direction + CComplex *U; + CComplex *R; // residual + CComplex *V; + CComplex *Z; + CComplex *b; // RHS of linear equation + CComplex *uu; + CComplex *vv; + + CComplexEntry **M; // pointer to list of matrix entries; + CComplexEntry **Mh; // Hermitian matrix arising from N-R algorithm; + CComplexEntry **Ma; // Antihermitian matrix arising from N-R algorithm; + CComplexEntry **Ms; // Additional complex-symmetric matrix arising from N-R algorithm; + int n; // dimensions of the matrix; + int bdw; // optional bandwidth parameter; + int bNewton; // Flag which denotes whether or not there are entries in Mh or Ms; + int NumNodes; + double Precision; + + // member functions + + CBigComplexLinProb(); // constructor + ~CBigComplexLinProb(); // destructor + int Create(int d, int bw, int nodes); // initialize the problem + void Put(CComplex v, int p, int q, int k=0); // use to create/set entries in the matrix + CComplex Get(int p, int q, int k=0); + void AddTo(CComplex v, int p, int q); + void MultA(CComplex *X, CComplex *Y, int k=0); + void MultConjA(CComplex *X, CComplex *Y, int k=0); + CComplex Dot(CComplex *x, CComplex *y); + CComplex ConjDot(CComplex *x, CComplex *y); + void SetValue(int i, CComplex x); + void Periodicity(int i, int j); + void AntiPeriodicity(int i, int j); + void Wipe(); + void MultPC(CComplex *X, CComplex *Y); + void MultAPPA(CComplex *X, CComplex *Y); + + + // flag==false initializes solution to zero + // flag==true starts from solution of previous call + int PBCGSolveMod(int flag); // Precondition Biconjugate Gradient + int PCGSQStart(); + int PBCGSolve(int flag); + int BiCGSTAB(int flag); + int KludgeSolve(int flag); + + CFknDlg *TheView; + + private: + +}; + diff --git a/fkn/tmp_prob1big.cpp b/fkn/tmp_prob1big.cpp new file mode 100644 index 0000000..5c9c612 --- /dev/null +++ b/fkn/tmp_prob1big.cpp @@ -0,0 +1,700 @@ +#include +#include +#include +#include "fkn.h" +#include "fknDlg.h" +#include "complex.h" +#include "mesh.h" +#include "spars.h" +#include "FemmeDocCore.h" +#include "lua.h" + +extern lua_State *lua; + +BOOL CFemmeDocCore::Static2D(CBigLinProb &L) +{ + int i,j,k,w,s,sdi_iter,sdin; + double Me[3][3],be[3]; // element matrices; + double Mx[3][3],My[3][3],Mn[3][3]; + double l[3],p[3],q[3]; // element shape parameters; + int n[3]; // numbers of nodes for a particular element; + double a,K,r,t,x,y,B,B1,B2,mu,v[3],u[3],dv,res,lastres,Cduct; + double *V_old,*V_sdi,*CircInt1,*CircInt2,*CircInt3; + double c=PI*4.e-05; + double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + int Iter=0,pctr; + BOOL LinearFlag=TRUE; + BOOL bIncremental = FALSE; + double murel, muinc; + BOOL SDIflag=FALSE; + + if (PrevSoln.GetLength() > 0) bIncremental = TRUE; + res=0; + + CElement *El; + V_old=(double *) calloc(NumNodes,sizeof(double)); + + for(i=0;i0) + { + CircInt1=(double *)calloc(NumCircProps,sizeof(double)); + CircInt2=(double *)calloc(NumCircProps,sizeof(double)); + CircInt3=(double *)calloc(NumCircProps,sizeof(double)); + for(i=0;i=0) + if(labellist[meshele[i].lbl].InCircuit!=-1){ + El=&meshele[i]; + + // get element area; + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + a=(p[0]*q[1]-p[1]*q[0])/2.; + // r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // if coils are wound, they act like they have + // a zero "bulk" conductivity... + Cduct=blockproplist[El->blk].Cduct; + if (labellist[El->lbl].bIsWound) Cduct=0; + + // evaluate integrals; + CircInt1[labellist[El->lbl].InCircuit]+=a; + CircInt2[labellist[El->lbl].InCircuit]+= + a*Cduct; + CircInt3[labellist[El->lbl].InCircuit]+= + blockproplist[El->blk].Jr*a*100.; + } + } + + for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); + TheView->m_prog1.SetPos(0); + pctr=0; + + if(Iter>0) L.Wipe(); + + for(i=0;ipctr){ + j=pctr*5; if (j>100) j=100; + TheView->m_prog1.SetPos(j); + pctr++; + } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + Me[j][k]=0.; + Mx[j][k]=0.; + My[j][k]=0.; + Mn[j][k]=0.; + } + be[j]=0.; + } + + // Determine shape parameters. + // l == element side lengths; + // p corresponds to the `b' parameter in Allaire + // q corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // x-contribution; only need to do main diagonal and above; + K = (-1./(4.*a)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Mx[j][k] += K*p[j]*p[k]; + if (j!=k) Mx[k][j]+=K*p[j]*p[k]; + } + // y-contribution; only need to do main diagonal and above; + K = (-1./(4.*a)); + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + My[j][k] +=K*q[j]*q[k]; + if (j!=k) My[k][j]+=K*q[j]*q[k]; + } + + // contributions to Me, be from derivative boundary conditions; + for(j=0;j<3;j++){ + if (El->e[j] >= 0) + if (lineproplist[El->e[j]].BdryFormat==2) + { + // conversion factor is 10^(-4) (I think...) + K=-0.0001*c*lineproplist[ El->e[j] ].c0.re*l[j]/6.; + k=j+1; if(k==3) k=0; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K=(lineproplist[ El->e[j] ].c1.re*l[j]/2.)*0.0001; + be[j]+=K; + be[k]+=K; + } + } + + // contribution to be from current density in the block + for(j=0,El->Jprev=0;j<3;j++){ + if(labellist[El->lbl].InCircuit>=0) + { + k=labellist[El->lbl].InCircuit; + if(circproplist[k].Case==1) t=circproplist[k].J.Re(); + if(circproplist[k].Case==0) + t=-circproplist[k].dV.Re()*blockproplist[El->blk].Cduct; + } + else t=0; + K=-(blockproplist[El->blk].Jr+t)*a/3.; + be[j]+=K; + + // record avg current density in the block for use in incremental solutions + El->Jprev+=(blockproplist[El->blk].Jr+t)/3.; + } + + // contribution to be from magnetization in the block; + t=labellist[El->lbl].MagDir; + if (labellist[El->lbl].MagDirFctn!=NULL) // functional magnetization direction + { + CString str; + CComplex X; + int top1,top2,lua_error_code; + for (j=0,X=0;j<3;j++) X+=(meshnode[n[j]].x + I*meshnode[n[j]].y); + X=X/units[LengthUnits]/3.; + str.Format("x=%.17g\ny=%.17g\nr=x\nz=y\ntheta=%.17g\nR=%.17g\nreturn %s", + X.re,X.im,arg(X)*180/PI,abs(X),labellist[El->lbl].MagDirFctn); + top1=lua_gettop(lua); + if((lua_error_code=lua_dostring(lua,str))!=0) + { + /* + if (lua_error_code==LUA_ERRRUN) + AfxMessageBox("Run Error"); + if (lua_error_code==LUA_ERRMEM) + AfxMessageBox("Lua memory Error"); + if (lua_error_code==LUA_ERRERR) + AfxMessageBox("User error error"); + if (lua_error_code==LUA_ERRFILE) + AfxMessageBox("File Error"); + */ + + MsgBox("Lua error evaluating \"%s\"",labellist[El->lbl].MagDirFctn); + + exit(7); + } + top2=lua_gettop(lua); + if (top2!=top1){ + str=lua_tostring(lua,-1); + if (str.GetLength()==0){ + MsgBox("\"%s\" does not evaluate to a numerical value", + labellist[El->lbl].MagDirFctn); + exit(7); + } + else t=Re(lua_tonumber(lua,-1)); + lua_pop(lua, 1); + } + } + for(j=0;j<3;j++){ + k=j+1; if(k==3) k=0; + // need to scale so that everything is in proper units... + // conversion is 0.0001 + K=0.0001*blockproplist[El->blk].H_c*( + cos(t*PI/180.)*(meshnode[n[k]].x-meshnode[n[j]].x) + + sin(t*PI/180.)*(meshnode[n[k]].y-meshnode[n[j]].y) )/2.; + be[j]+=K; + be[k]+=K; + } + +//////// Nonlinear Part + + // update permeability for the element; + if (Iter==0){ + k=meshele[i].blk; + + if (blockproplist[k].BHpoints != 0) + { + if (bIncremental == FALSE) + { + // There's no previous solution. This is a standard nonlinear time harmonic problem + LinearFlag = FALSE; + } + else { + double B1p, B2p; + + // Get B from previous solution + GetPrev2DB(i, B1p, B2p); + B = sqrt(B1p*B1p + B2p*B2p); + + // look up incremental permeability and assign it to the element; + blockproplist[k].IncrementalPermeability(B, w, muinc, murel); + if (B == 0) + { + meshele[i].mu1 = muinc; + meshele[i].mu2 = muinc; + meshele[i].v12 = 0; + } + else { + if (bIncremental == 1) + { + // Need to actually compute B1 and B2 to build incremental permeability tensor + meshele[i].mu1 = B*B*muinc*murel / (B1p*B1p*murel + B2p*B2p*muinc); + meshele[i].mu2 = B*B*muinc*murel / (B1p*B1p*muinc + B2p*B2p*murel); + meshele[i].v12 = B1p*B2p*(murel - muinc) / (B*B*murel*muinc); + } + else { + // Define "frozen permeability" + meshele[i].mu1 = murel; + meshele[i].mu2 = murel; + meshele[i].v12 = 0; + } + } + } + } + + if (blockproplist[k].LamType==0){ + t=blockproplist[k].LamFill; + meshele[i].mu1=blockproplist[k].mu_x*t + (1.-t); + meshele[i].mu2=blockproplist[k].mu_y*t + (1.-t); + } + if (blockproplist[k].LamType==1){ + t=blockproplist[k].LamFill; + mu=blockproplist[k].mu_x; + meshele[i].mu1=mu*t + (1.-t); + meshele[i].mu2=mu/(t + mu*(1.-t)); + } + if (blockproplist[k].LamType==2){ + t=blockproplist[k].LamFill; + mu=blockproplist[k].mu_y; + meshele[i].mu2=mu*t + (1.-t); + meshele[i].mu1=mu/(t + mu*(1.-t)); + } + if (blockproplist[k].LamType>2) + { + meshele[i].mu1=1; + meshele[i].mu2=1; + } + } + else{ + k=meshele[i].blk; + + if ((blockproplist[k].LamType==0) && + (meshele[i].mu1==meshele[i].mu2) + &&(blockproplist[k].BHpoints>0)) + { + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=L.V[n[j]]*q[j]; + B2+=L.V[n[j]]*p[j]; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + // correction for lengths in cm of 1/0.02 + + // find out new mu from saturation curve; + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu; + meshele[i].mu2=mu; + for(j=0;j<3;j++){ + for(w=0,v[j]=0;w<3;w++) + v[j]+=(Mx[j][w]+My[j][w])*L.V[n[w]]; + } + K=-200.*c*c*c*dv/a; + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*v[j]*v[w]; + } + + if ((blockproplist[k].LamType==1) && (blockproplist[k].BHpoints>0)){ + t=blockproplist[k].LamFill; + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=L.V[n[j]]*q[j]; + B2+=L.V[n[j]]*p[j]/t; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu1=mu*t; + meshele[i].mu2=mu/(t+mu*(1.-t)); + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(My[j][w]/t+Mx[j][w])*L.V[n[w]]; + u[j]+=(My[j][w]/t + t*Mx[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(a); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + } + if ((blockproplist[k].LamType==2) && (blockproplist[k].BHpoints>0)){ + t=blockproplist[k].LamFill; + for(j=0,B1=0.,B2=0.;j<3;j++){ + B1+=(L.V[n[j]]*q[j])/t; + B2+=L.V[n[j]]*p[j]; + } + B=c*sqrt(B1*B1+B2*B2)/(0.02*a); + blockproplist[k].GetBHProps(B,mu,dv); + mu=1./(muo*mu); + meshele[i].mu2=mu*t; + meshele[i].mu1=mu/(t+mu*(1.-t)); + for(j=0;j<3;j++){ + for(w=0,v[j]=0,u[j]=0;w<3;w++) + { + v[j]+=(Mx[j][w]/t + My[j][w])*L.V[n[w]]; + u[j]+=(Mx[j][w]/t + t*My[j][w])*L.V[n[w]]; + } + } + K=-100.*c*c*c*dv/(a); + for(j=0;j<3;j++) + for(w=0;w<3;w++) + Mn[j][w]=K*(v[j]*u[w]+v[w]*u[j]); + } + } + + // combine block matrices into global matrices; + for(j=0;j<3;j++) + for(k=0;k<3;k++){ + Me[j][k]+= (Mx[j][k]/Re(El->mu2) + My[j][k]/Re(El->mu1) + Mn[j][k]); + be[j]+=Mn[j][k]*L.V[n[k]]; + } + + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.Put(L.Get(n[j],n[k])-Me[j][k],n[j],n[k]); + L.b[n[j]]-=be[j]; + } + } + + // add in contribution from point currents; + for(i=0;i=0) + L.b[i]+=(0.01*nodeproplist[meshnode[i].bc].Jr); + + // apply fixed boundary conditions at points; + for(i=0;i=0) + if((nodeproplist[meshnode[i].bc].Jr==0) && + (nodeproplist[meshnode[i].bc].Ji==0) && (sdi_iter==0)) + L.SetValue(i,nodeproplist[meshnode[i].bc].Ar / c); + + // apply fixed boundary conditions along segments; + for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + if(Coords==0){ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take ``real'' component. + a*=cos(lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + x/=units[LengthUnits]; y/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + x*lineproplist[s].A1 + + y*lineproplist[s].A2; + // just take``real'' component. + a*=cos(lineproplist[s].phi*DEG); + L.SetValue(meshele[i].p[k],a/c); + } + else{ + // first point on the side; + x=meshnode[meshele[i].p[j]].x; + y=meshnode[meshele[i].p[j]].y; + r=sqrt(x*x+y*y); + if((x==0)&&(y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + L.SetValue(meshele[i].p[j],a/c); + + // second point on the side; + x=meshnode[meshele[i].p[k]].x; + y=meshnode[meshele[i].p[k]].y; + r=sqrt(x*x+y*y); + if((x==0) && (y==0)) t=0; + else t=atan2(y,x)/DEG; + r/=units[LengthUnits]; + s=meshele[i].e[j]; + a=lineproplist[s].A0 + r*lineproplist[s].A1 + + t*lineproplist[s].A2; + a*=cos(lineproplist[s].phi*DEG); // just take ``real'' component. + L.SetValue(meshele[i].p[k],a/c); + } + + } + } + + // Apply SDI boundary condition; + if ((SDIflag==TRUE) && (sdi_iter==1)) for(i=0;i=0) + if(lineproplist[ meshele[i].e[j] ].BdryFormat==3) + { + L.SetValue(meshele[i].p[j],0.); + L.SetValue(meshele[i].p[k],0.); + } + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0;k5) + { + if ((res>lastres) && (Relax>0.125)) Relax/=2.; + else Relax+= 0.1 * (1. - Relax); + + for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); + j=(int) (100.*log10(res)/(log10(Precision)+2.)); + if (j>100) j=100; + TheView->m_prog2.SetPos(j); + } + + // nonlinear iteration has to have a looser tolerance + // than the linear solver--otherwise, things can't ever + // converge. Arbitrarily choose 100*tolerance. + if((res<100.*Precision) && (Iter>0)) LinearFlag=TRUE; + + Iter++; + +} while(LinearFlag==FALSE); + + for(i=0;i0){ + free(CircInt1); + free(CircInt2); + free(CircInt3); + } + return TRUE; +} + +//========================================================================= +//========================================================================= + +BOOL CFemmeDocCore::WriteStatic2D(CBigLinProb &L) +{ + // write solution to disk; + + char c[1024]; + FILE *fp,*fz; + int i,k; + double cf; + double unitconv[]={2.54,0.1,1.,100.,0.00254,1.e-04}; + + // first, echo input .fem file to the .ans file; + sprintf(c,"%s.fem",PathName); + if((fz=fopen(c,"rt"))==NULL){ + MsgBox("Couldn't open %s.fem\n",PathName); + return FALSE; + } + + sprintf(c,"%s.ans",PathName); + if((fp=fopen(c,"wt"))==NULL){ + MsgBox("Couldn't write to %s.ans\n",PathName); + return FALSE; + } + + while(fgets(c,1024,fz)!=NULL) fputs(c,fp); + fclose(fz); + + // then print out node, line, and element information + fprintf(fp,"[Solution]\n"); + cf=unitconv[LengthUnits]; + fprintf(fp,"%i\n",NumNodes); + for(i=0;i +#include +#include +#include +#include "hsolv.h" +#include "hsolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "hsolvdoc.h" + +#define muo 1.2566370614359173e-6 + +BOOL Chsolvdoc::SortElements() +{ + // Comb Sort -- see http://en.wikipedia.org/wiki/Comb_sort + int *Score; + int i,j,k,gap; + CElement e; + + Score=(int*)calloc(NumEls,sizeof(int)); + + for(k=0;k 1) + { + gap=(gap*10)/13; + if ((gap==10) || (gap==9)) gap=11; + + } + + //a single "comb" over the input list + for(j=0,i=0;(j+gap)Score[j+gap]) + { + k=j+gap; + i=Score[k];Score[k]=Score[j];Score[j]=i; + e=meshele[k];meshele[k]=meshele[j];meshele[j]=e; + i=1; + } + } + }while((gap>1)&&(i>0)); + + + free(Score); + return TRUE; +} + +BOOL Chsolvdoc::Cuthill() +{ + + FILE *fp; + int i,j,k,n0,n1,n; + int newwide,*newnum,**ocon; + int *numcon,*nxtnum; + CNode swap; + char infile[256]; + + // allocate storage + nxtnum=(int *)calloc(NumNodes,sizeof(int)); + newnum=(int *)calloc(NumNodes,sizeof(int)); + numcon=(int *)calloc(NumNodes,sizeof(int)); + ocon=(int **)calloc(NumNodes,sizeof(int *)); + // initialize node array; + for(i=0;inewwide) + { + newwide=abs(newnum[n0]-ocon[n0][i]); + } + } + + BandWidth=newwide+1; + // } + + // free up the variables that we needed during the routine.... + free(numcon); + free(nxtnum); + free(ocon[0]); + free(ocon); + + // new mapping remains in newnum; + // apply this mapping to elements first. + for(i=0;i +#include +#include +#include +#include +#include "hsolv.h" +#include "hsolvDlg.h" +#include "spars.h" +#include "mesh.h" +#include "hsolvdoc.h" + +void old_main(void *inptr) +{ + ChsolvDlg *TheView; + Chsolvdoc Doc; + char PathName[256]; + CFileDialog *fname_dia; + char outstr[1024]; + int i; + + TheView=(ChsolvDlg *) inptr; + + // get the name of the file to be processed, + // either from argv or from the user + if (__argc<2){ + + fname_dia=new CFileDialog( + TRUE, + "fem | * ", + NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + "heat flow datafile (*.feh) | *.feh; *.FEH | All Files (*.*) | *.*||", + NULL); + + if(fname_dia->DoModal()==IDCANCEL){ + delete[] fname_dia; + MsgBox("No file name!"); + exit(0); + } + + CString fname=fname_dia->GetPathName(); + fname=fname.Left(fname.GetLength()-4); + strcpy(PathName,fname); + delete[] fname_dia; + } + else strcpy(PathName,__argv[1]); + + Doc.PathName=PathName; + Doc.TheView=TheView; + + // load problem geometry + if (Doc.OnOpenDocument()!=TRUE){ + MsgBox("problem loading .feh file"); + exit(7); + } + + // load mesh + if (Doc.LoadMesh()!=TRUE){ + MsgBox("problem loading mesh"); + exit(2); + } + + // load previous solution, if applicable + if (Doc.LoadPrev()!=TRUE){ + exit(3); + } + + // label the dialog to report which problem is being solved + char PaneText[256]; + char *ProbName; + ProbName=PathName; + for(i=0;i< (int) strlen(PathName);i++) + if(PathName[i]=='\\') ProbName=PathName+i; + if (strlen(PathName)>0){ + ProbName++; + sprintf(PaneText,"%s - hsolve",ProbName); + } + + while(!IsWindow(TheView->m_hWnd)) Sleep(1); + TheView->SetWindowText(PaneText); + + // renumber using Cuthill-McKee + TheView->SetDlgItemText(IDC_STATUSWINDOW,"renumbering nodes"); + if (Doc.Cuthill()!=TRUE){ + MsgBox("problem renumbering nodes"); + exit(4); + } + + // display details about the problem to be solved + TheView->SetDlgItemText(IDC_STATUSWINDOW,"solving..."); + sprintf(outstr,"Problem Statistics:\n%i nodes\n%i elements\nPrecision: %3.2e\n", + Doc.NumNodes,Doc.NumEls,Doc.Precision); + TheView->SetDlgItemText(IDC_PROBSTATS,outstr); + + // initialize the problem, allocating the space required to solve it. + + CBigLinProb L; + L.TheView=TheView; + L.Precision=Doc.Precision; + + if (L.Create(Doc.NumNodes+Doc.NumCircProps,Doc.BandWidth)==FALSE){ + MsgBox("couldn't allocate enough space for matrices"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(5); + } + + // Create element matrices and solve the problem; + if (Doc.AnalyzeProblem(L)==FALSE) + { + MsgBox("Couldn't solve the problem"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(6); + } + + TheView->SetDlgItemText(IDC_STATUSWINDOW,"Problem solved"); + + // now that we have results, write 'em to dist + if (Doc.WriteResults(L)==FALSE) + { + MsgBox("couldn't write results to disk"); + Doc.CleanUp(); + L.~CBigLinProb(); + exit(7); + } + TheView->SetDlgItemText(IDC_STATUSWINDOW,"results written to disk"); + + // make sure that everything is freed up to avoid memory leaks + Doc.CleanUp(); + L.~CBigLinProb(); + exit(0); +} diff --git a/hsolv/MESH.H b/hsolv/MESH.H new file mode 100644 index 0000000..f30f7fc --- /dev/null +++ b/hsolv/MESH.H @@ -0,0 +1,108 @@ +#define PI 3.141592653589793238462643383 +#define eo 8.85418781762e-12 +#define AXISYMMETRIC 1 +#define PLANAR 0 +#include "complex.h" +class CNode +{ + public: + + double x,y; + int bc; + int InConductor; + + private: + +}; + +class CElement +{ + public: + + int p[3]; // nodes at the corners of the element + int e[3]; // boundary condition applied to each edge of the element + int blk; // block property applied to the element + int lbl; // block label associated with the element + + private: +}; + +class CBlockLabel +{ + public: + + double x,y; + double MaxArea; + int BlockType,InGroup; + BOOL IsExternal; + BOOL IsDefault; + + private: + +}; + +class CCommonPoint +{ + public: + int x,y,t; + + private: +}; + +///////////////////////////////////////////////////////////////////////////// +// Classes that hold property data: CMaterialProp, CBoundaryProp, CPointProp + +class CMaterialProp +{ + public: + + double Kx,Ky; // Thermal conductivity for linear (possibly anisotropic) problems + double Kt; // Volumetric Heat Capacity, MJ/(m^3*K) + double qv; // charge density, C/m^3 + int npts; + CComplex Kn[128]; // Thermal conductivity as a function of temperature + + CComplex GetK(double T); // evaluate the T-k curve + + private: +}; + +class CBoundaryProp +{ + public: + + int BdryFormat; // type of boundary condition we are applying + // 0 = fixed voltage + // 1 = mixed BC + // 2 = surface charge + // 3 = periodic + // 4 = antiperiodic + + double Tset; // Fixed value of temperature for BdryFormat=0; + double Tinf; // External temperature for convection or radiation + double qs; // Heat flux; + double beta; // radiosity coefficient + double h; // Heat transfer coefficient + + private: +}; + +class CPointProp +{ + public: + + double V; // fixed nodal voltage + double qp; // point current density; + + private: +}; + +class CCircuit +{ + public: + + double V,q; + int CircType; + + private: +}; diff --git a/hsolv/SPARS.CPP b/hsolv/SPARS.CPP new file mode 100644 index 0000000..1f498c5 --- /dev/null +++ b/hsolv/SPARS.CPP @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include "hsolv.h" +#include "hsolvDlg.h" +#include "spars.h" + +#define KLUDGE + +CEntry::CEntry() +{ + next=NULL; + x=0; + c=0; +} + +CBigLinProb::CBigLinProb() +{ + n=0; +} + +CBigLinProb::~CBigLinProb() +{ + if (n==0) return; + + int i; + CEntry *uo,*ui; + + free(b); free(P); free(R); + free(V); free(U); free(Z); + free(Q); + + for(i=0;inext; + delete uo; + } while(ui!=NULL); + } + + free(M); + n=0; +} + +int CBigLinProb::Create(int d, int bw) +{ + int i; + + bdw=bw; + b=(double *)calloc(d,sizeof(double)); + V=(double *)calloc(d,sizeof(double)); + P=(double *)calloc(d,sizeof(double)); + R=(double *)calloc(d,sizeof(double)); + U=(double *)calloc(d,sizeof(double)); + Z=(double *)calloc(d,sizeof(double)); + Q=(BOOL *) calloc(d,sizeof(BOOL)); + M=(CEntry **)calloc(d,sizeof(CEntry *)); + n=d; + + for(i=0;ic = i; + } + + return 1; +} + +void CBigLinProb::Put(double v, int p, int q) +{ + CEntry *e,*l; + int i; + + if(qc < q) && (e->next != NULL)) + { + l=e; + e=e->next; + } + + if(e->c == q){ + e->x=v; + return; + } + + CEntry *m = new CEntry; + + if((e->next == NULL) && (q > e->c)){ + e->next = m; + m->c = q; + m->x = v; + } + else{ + l->next=m; + m->next=e; + m->c=q; + m->x=v; + } + return; +} + +double CBigLinProb::Get(int p, int q) +{ + CEntry *e; + + if(qc < q) && (e->next != NULL)) e=e->next; + + if(e->c == q) return e->x; + + return 0; +} + +void CBigLinProb::MultA(double *X, double *Y) +{ + int i; + CEntry *e; + + for(i=0;ix*X[i]; + e=M[i]->next; + while(e!=NULL) + { + Y[i]+=e->x*X[e->c]; + Y[e->c]+=e->x*X[i]; + e=e->next; + } + } +} + +double CBigLinProb::Dot(double *X, double *Y) +{ + int i; + double z; + + for(i=0,z=0;ix; + + // SSOR preconditioner: + int i; + double c; + CEntry *e; + + c= Lambda*(2-Lambda); + for(i=0;ix; + e=M[i]->next; + while(e!=NULL) + { + Y[e->c] -= e->x * Y[i] * Lambda; + e=e->next; + } + } + + for(i=0;ix; + + // invert Upper Triangle + for(i=n-1;i>=0;i--){ + e=M[i]->next; + while(e!=NULL) + { + Y[i] -= e->x * Y[e->c] * Lambda; + e=e->next; + } + Y[i]/= M[i]->x; + } +} + +int CBigLinProb::PCGSolve(int flag) +{ + int i; + double res,res_o,res_new; + double er,del,rho,pAp; + + // quick check for most obvious sign of singularity; + for(i=0;ix==0){ + MsgBox("singular flag tripped at %i of %i",i,n); + return FALSE; + } + + // initialize progress bar; + TheView->SetDlgItemText(IDC_FRAME1,"Conjugate Gradient Solver"); + TheView->m_prog1.SetPos(0); + int prg1=0; + int prg2; + + // Best guess for relaxation parameter + Lambda=1.5; + + // residual with V=0 + MultPC(b,Z); + res_o=Dot(Z,b); + if(res_o==0) return 1; + + // if flag is false, initialize V with zeros; + if (flag==0) for(i=0;iprg1){ + prg1=prg2; + prg2=(prg1*5); + if(prg2>100) prg2=100; + TheView->m_prog1.SetPos(prg2); + TheView->InvalidateRect(NULL, FALSE); + TheView->UpdateWindow(); + } + + } while(er>Precision); + + return 1; +} + +void CBigLinProb::SetValue(int i, double x) +{ + int k,fst,lst; + double z; + + if(bdw==0){ + fst=0; + lst=n; + } + else{ + fst=i-bdw; if (fst<0) fst=0; + lst=i+bdw; if (lst>n) lst=n; + } + + for(k=fst;kx=0; + e=e->next; + } while(e!=NULL); + } +} + +void CBigLinProb::AntiPeriodicity(int i, int j) +{ + int k,fst,lst; + double v1,v2,c; + +#ifdef KLUDGE + int tmpbdw=bdw; + bdw=0; +#endif + + if (jn) lst=n; + } + + for(k=fst;kn) lst=n; + } + + for(k=fst;k + +int MsgBox(const char* sz, ...); +int MsgBox(const std::string& s); diff --git a/hsolv/complex.cpp b/hsolv/complex.cpp new file mode 100644 index 0000000..7a6f454 --- /dev/null +++ b/hsolv/complex.cpp @@ -0,0 +1,624 @@ +#include +#include "math.h" +#include "stdio.h" +#include "complex.h" + +CComplex::CComplex(double x) +{ + re=x; im=0.; +} + +CComplex::CComplex(int x) +{ + re=(double) x; + im=0.; +} + +CComplex::CComplex() +{ + re=0.; im=0.; +} + +CComplex::CComplex(double x, double y) +{ + re=x; im=y; +} + +CComplex CComplex::Sqrt() +{ + double w,z; + CComplex y; + + if((re==0) && (im==0)) w=0; + else if(fabs(re)>fabs(im)){ + z=im/re; + w=sqrt(fabs(re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=re/im; + w=sqrt(fabs(im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(re>=0){ + y.re=w; + y.im=im/(2.*w); + return y; + } + + if(im>=0){ + y.re=fabs(im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(im)/(2.*w); + y.im= (-w); + return y; +} + +CComplex CComplex::Conj() +{ + return CComplex(re,-im); +} + +double CComplex::Abs() +{ + if ((re==0) && (im==0)) return 0.; + + if (fabs(re)>fabs(im)) + return fabs(re)*sqrt(1.+(im/re)*(im/re)); + else + return fabs(im)*sqrt(1.+(re/im)*(re/im)); +} + +double CComplex::Arg() +{ + if ((re==0) && (im==0)) return 0.; + + return atan2(im,re); +} + +CComplex CComplex::Inv() +{ + double c; + CComplex z; + + if(fabs(re)>fabs(im)) + { + c=im/re; + z.re=1./(re*(1.+c*c)); + z.im=(-c)*z.re; + } + else{ + c=re/im; + z.im=(-1.)/(im*(1.+c*c)); + z.re=(-c)*z.im; + } + + return z; +} + +double CComplex::Re() +{ + return re; +} + +double CComplex::Im() +{ + return im; +} + +void CComplex::Set(double x, double y) +{ + re=x; im=y; +} + +char* CComplex::ToString(char *s) +{ + if (im<0) + sprintf(s,"%.3e - j %.3e",re,fabs(im)); + else + sprintf(s,"%.3e + j %.3e",re,im); + return s; +} + +//******* Addition *************************************************** + +CComplex CComplex::operator+( const CComplex& z ) +{ + return CComplex(re+z.re,im+z.im); +}; + +CComplex CComplex::operator+( int z ) +{ + return CComplex(re+((double) z),im); +}; + +CComplex CComplex::operator+( double z ) +{ + return CComplex(re+z,im); +}; + +void CComplex::operator+=( const CComplex& z) +{ + re+=z.re; + im+=z.im; +}; + +void CComplex::operator+=( double z ) +{ + re+=z; +}; + +void CComplex::operator+=( int z ) +{ + re+=(double) z; +}; + +CComplex operator+( int x, const CComplex& y ) +{ + return CComplex( ((double) x) + y.re, y.im ); +} + +CComplex operator+( double x, const CComplex& y ) +{ + return CComplex( x + y.re, y.im ); +} + +CComplex operator+( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re + y.re, x.im + y.im ); +} + + +//******* Subtraction *************************************************** +CComplex CComplex::operator-() +{ + return CComplex(-re,-im); +} + +CComplex CComplex::operator-( const CComplex& z) +{ + return CComplex(re-z.re,im-z.im); +}; + +CComplex CComplex::operator-( int z ) +{ + return CComplex(re-((double) z),im); +}; + +CComplex CComplex::operator-( double z ) +{ + return CComplex(re-z,im); +}; + +void CComplex::operator-=( const CComplex& z) +{ + re-=z.re; + im-=z.im; +}; + +void CComplex::operator-=( double z ) +{ + re-=z; +}; + +void CComplex::operator-=( int z ) +{ + re-=(double) z; +}; + +CComplex operator-( int x, const CComplex& y ) +{ + return CComplex( ((double) x) - y.re, - y.im ); +} + +CComplex operator-( double x, const CComplex& y ) +{ + return CComplex( x - y.re, - y.im ); +} + +CComplex operator-( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re - y.re, x.im - y.im ); +} + +CComplex operator-( const CComplex& y ) +{ + return CComplex( -y.re,-y.im ); +} +//******* Multiplication *************************************************** + +CComplex CComplex::operator*( const CComplex& z) +{ + return CComplex(re*z.re - im*z.im,re*z.im + im*z.re); +}; + +CComplex CComplex::operator*( int z ) +{ + return CComplex( re*((double) z),im*((double) z) ); +}; + +CComplex CComplex::operator*( double z ) +{ + return CComplex(re*z,im*z); +}; + +void CComplex::operator*=( const CComplex& z) +{ + CComplex x(re*z.re - im*z.im,re*z.im + im*z.re); + re=x.re; im=x.im; +}; + +void CComplex::operator*=( double z ) +{ + re*=z; im*=z; +}; + +void CComplex::operator*=( int z ) +{ + re*=(double) z; + im*=(double) z; +}; + +CComplex operator*( int x, const CComplex& y ) +{ + return CComplex( ((double) x) * y.re, ((double) x)*y.im ); +} + +CComplex operator*( double x, const CComplex& y ) +{ + return CComplex( x*y.re, x*y.im ); +} + +CComplex operator*( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re*y.re-x.im*y.im, x.re*y.im+x.im*y.re ); +} + +//******* Division *************************************************** + +CComplex CComplex::operator/( const CComplex& z) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return *this * y; +}; + + +CComplex CComplex::operator/( int z ) +{ + return CComplex(re/((double) z),im/((double) z)); +}; + +CComplex CComplex::operator/( double z ) +{ + return CComplex(re/z,im/z); +}; + +void CComplex::operator/=( const CComplex& z) +{ + *this=*this/z; +}; + +void CComplex::operator/=( double z ) +{ + re/=z; + im/=z; +}; + +void CComplex::operator/=( int z ) +{ + re/=(double) z; + im/=(double) z; +}; + +CComplex operator/( int x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*=(double) x; + y.im*=(double) x; + + return y; +} + +CComplex operator/( double x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*= x; + y.im*= x; + + return y; +} + +CComplex operator/( const CComplex& x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return x*y; +} + +//****** Equals definitions ******************************** + +void CComplex::operator=(double z) +{ + re=z; + im=0; +} + +void CComplex::operator=(int z) +{ + re=(double) z; + im=0; + +} + +//***** Tests *********************************************** +BOOL CComplex::operator==( const CComplex& z){ + if ((z.im==im) && (z.re==re)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator==(double z){ + if ((z==re) && (im==0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator==(int z){ + if ((re==(double) z) && (im==0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator!=( const CComplex& z){ + if ((z.re==re) && (z.im==im)) return FALSE; + return TRUE; +} + +BOOL CComplex::operator!=(double z){ + if ((re!=z) || (im!=0)) return TRUE; + return FALSE; +} + +BOOL CComplex::operator!=(int z){ + if ((re!=(double) z) || (im!=0)) return TRUE; + return FALSE; +} + +//***** Useful functions ************************************ + +CComplex conj( const CComplex& x) +{ + return CComplex(x.re,-x.im); +} + +CComplex exp( const CComplex& x) +{ + CComplex y; + + y.re=cos(x.im)*exp(x.re); + y.im=sin(x.im)*exp(x.re); + + return y; +} + +CComplex sqrt( const CComplex& x) +{ + double w,z; + CComplex y; + + if((x.re==0) && (x.im==0)) w=0; + else if(fabs(x.re)>fabs(x.im)){ + z=x.im/x.re; + w=sqrt(fabs(x.re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=x.re/x.im; + w=sqrt(fabs(x.im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(x.re>=0){ + y.re=w; + y.im=x.im/(2.*w); + return y; + } + + if(x.im>=0){ + y.re=fabs(x.im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(x.im)/(2.*w); + y.im= (-w); + + return y; +} + +CComplex tanh( const CComplex& x) +{ + CComplex y; + + if (x.re>0){ + y=(1-exp(-2*x))/(1+exp(-2*x)); + } + else{ + y=(exp(2*x)-1)/(exp(2*x)+1); + } + + return y; +} + +CComplex sinh( const CComplex& x) +{ + return (exp(x)-exp(-x))/2; +} + +CComplex cosh( const CComplex& x) +{ + return (exp(x)+exp(-x))/2; +} + + +CComplex cos( const CComplex& x) +{ + return (exp(I*x)+exp(-I*x))/2; +} + +CComplex acos( const CComplex& x) +{ + return PI/2. - arg(I*x + sqrt(1 - x*x)) + I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex sin( const CComplex& x) +{ + return (exp(I*x)-exp(-I*x))/(2*I); +} + +CComplex asin( const CComplex& x) +{ + return arg(I*x + sqrt(1 - x*x)) - I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex tan( const CComplex& x) +{ + return sin(x)/cos(x); +} + +CComplex atan( const CComplex& x) +{ + return (arg(1+I*x) - arg(1-I*x) - I*(log(abs(1+I*x)/abs(1-I*x))))/ 2; +} + +double abs( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + if (fabs(x.re)>fabs(x.im)) + return fabs(x.re)*sqrt(1.+(x.im/x.re)*(x.im/x.re)); + else + return fabs(x.im)*sqrt(1.+(x.re/x.im)*(x.re/x.im)); +} + +double arg( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + return atan2(x.im,x.re); +} + +CComplex log( const CComplex& x) +{ + CComplex y; + + y.im=arg(x); + y.re=log(abs(x)); + + return y; +} + +CComplex pow( const CComplex& x, double y) +{ + return exp(y*log(x)); +} + +CComplex pow( const CComplex& x, int y) +{ + if (y==0) return CComplex(1,0); + + int i; + CComplex z; + + if (y>0){ + z=x; + for(i=1;i // just needs afx.h to define BOOL, TRUE, and FALSE +#define PI 3.141592653589793238462643383 +#define SmallNo 1.e-14 +#define DEG 0.01745329251994329576923690768 + +class CComplex +{ + public: + // data members + double re,im; + + // member functions + CComplex(); + CComplex(double x); + CComplex(int x); + CComplex(double x, double y); + CComplex Sqrt(); + CComplex Conj(); + CComplex Inv(); + void Set(double x, double y); + double Abs(); + double Arg(); + double Re(); + double Im(); + char* ToString(char *s); + + //operator redefinition + //Addition + CComplex operator+( const CComplex& z ); + CComplex operator+(double z); + CComplex operator+(int z); + friend CComplex operator+( int x, const CComplex& y ); + friend CComplex operator+( double x, const CComplex& y ); + friend CComplex operator+( const CComplex& x, const CComplex& y ); + void operator+=( const CComplex& z); + void operator+=(double z); + void operator+=(int z); + + //Subtraction + CComplex operator-(); + CComplex operator-( const CComplex& z ); + CComplex operator-(double z); + CComplex operator-(int z); + friend CComplex operator-( int x, const CComplex& y ); + friend CComplex operator-( double x, const CComplex& y ); + friend CComplex operator-( const CComplex& x, const CComplex& y ); + friend CComplex operator-( const CComplex& x ); + void operator-=( const CComplex& z); + void operator-=(double z); + void operator-=(int z); + + //Multiplication + CComplex operator*( const CComplex& z ); + CComplex operator*(double z); + CComplex operator*(int z); + friend CComplex operator*( int x, const CComplex& y ); + friend CComplex operator*( double x, const CComplex& y ); + friend CComplex operator*( const CComplex& x, const CComplex& y ); + void operator*=( const CComplex& z); + void operator*=(double z); + void operator*=(int z); + + //Division + CComplex operator/( const CComplex& z ); + CComplex operator/(double z); + CComplex operator/(int z); + friend CComplex operator/( int x, const CComplex& y ); + friend CComplex operator/( double x, const CComplex& y ); + friend CComplex operator/( const CComplex &x, const CComplex& y ); + void operator/=( const CComplex& z); + void operator/=(double z); + void operator/=(int z); + + //Equals + void operator=(double z); + void operator=(int z); + + //Tests + BOOL operator==( const CComplex& z); + BOOL operator==(double z); + BOOL operator==(int z); + BOOL operator!=( const CComplex& z); + BOOL operator!=(double z); + BOOL operator!=(int z); + + private: + +}; + +// useful functions... +#define I CComplex(0,1) +double Re( const CComplex& a); +double Im( const CComplex& a); +double abs( const CComplex& x ); +double arg( const CComplex& x ); +CComplex conj( const CComplex& x); +CComplex exp( const CComplex& x ); +CComplex sqrt( const CComplex& x ); +CComplex tanh( const CComplex& x ); +CComplex sinh( const CComplex& x ); +CComplex cosh( const CComplex& x ); +CComplex cos( const CComplex& x ); +CComplex acos( const CComplex& x ); +CComplex sin( const CComplex& x ); +CComplex asin( const CComplex& x ); +CComplex tan( const CComplex& x ); +CComplex atan( const CComplex& x ); +CComplex log( const CComplex& x ); +CComplex pow( const CComplex& x, int y); +CComplex pow( const CComplex& x, double y); +CComplex pow( const CComplex& x, const CComplex& y); + + + diff --git a/hsolv/hsolv.cpp b/hsolv/hsolv.cpp new file mode 100644 index 0000000..e1dafe1 --- /dev/null +++ b/hsolv/hsolv.cpp @@ -0,0 +1,83 @@ +// hsolv.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "hsolv.h" +#include "hsolvDlg.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// ChsolvApp + +BEGIN_MESSAGE_MAP(ChsolvApp, CWinApp) + //{{AFX_MSG_MAP(ChsolvApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// ChsolvApp construction + +ChsolvApp::ChsolvApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +ChsolvApp::~ChsolvApp() +{ + +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only ChsolvApp object + +ChsolvApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// ChsolvApp initialization + +BOOL ChsolvApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + ChsolvDlg dlg; + m_pMainWnd = &dlg; + + dlg.ComLine=m_lpCmdLine; + // SetDialogBkColor(); + + _beginthread( old_main, 0, (void *) &dlg ); + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/hsolv/hsolvDlg.cpp b/hsolv/hsolvDlg.cpp new file mode 100644 index 0000000..6105d9f --- /dev/null +++ b/hsolv/hsolvDlg.cpp @@ -0,0 +1,97 @@ +// hsolvDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "hsolv.h" +#include "hsolvDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// ChsolvDlg dialog + +ChsolvDlg::ChsolvDlg(CWnd* pParent /*=NULL*/) + : CDialog(ChsolvDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(ChsolvDlg) + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void ChsolvDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(ChsolvDlg) + DDX_Control(pDX, IDC_PROGRESS2, m_prog2); + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(ChsolvDlg, CDialog) + //{{AFX_MSG_MAP(ChsolvDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// ChsolvDlg message handlers + +BOOL ChsolvDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + return FALSE; // return TRUE unless you set the focus to a control +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void ChsolvDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR ChsolvDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void ChsolvDlg::OnOK() +{ +} diff --git a/hsolv/hsolvDlg.h b/hsolv/hsolvDlg.h new file mode 100644 index 0000000..7056977 --- /dev/null +++ b/hsolv/hsolvDlg.h @@ -0,0 +1,20 @@ +// MFC-free ChsolvDlg with empty progress, label, and window-update calls. +#pragma once + +#include + +struct CProgressStub { void SetPos(int) {} }; + +class ChsolvDlg { +public: + CProgressStub m_prog1; + CProgressStub m_prog2; + void* m_hWnd = nullptr; + std::string ComLine; + void SetDlgItemText(int, const char*) {} + void SetWindowText(const char*) {} + void UpdateWindow() {} + int InvalidateRect(void* = nullptr, int = 1) { return 1; } +}; + +extern ChsolvDlg* TheView; diff --git a/hsolv/hsolvdoc.cpp b/hsolv/hsolvdoc.cpp new file mode 100644 index 0000000..7c4b6e7 --- /dev/null +++ b/hsolv/hsolvdoc.cpp @@ -0,0 +1,735 @@ +// hsolvdoc.cpp : implementation of the Chsolvdoc class +// + + +#include +#include +#include +#include +#include +#include "hsolv.h" +#include "hsolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "hsolvdoc.h" + +///////////////////////////////////////////////////////////////////////////// +// Chsolvdoc construction/destruction + +Chsolvdoc::Chsolvdoc() +{ + TheView=NULL; + Precision=NULL; + LengthUnits=NULL; + ProblemType=NULL; + Coords=NULL; + BandWidth=NULL; + NumNodes=NULL; + NumEls=NULL; + NumBlockProps=NULL; + NumPBCs=NULL; + NumLineProps=NULL; + NumPointProps=NULL; + NumCircProps=NULL; + NumBlockLabels=NULL; + + meshnode=NULL; + meshele=NULL; + Tprev=NULL; + blockproplist=NULL; + lineproplist=NULL; + nodeproplist=NULL; + circproplist=NULL; + labellist=NULL; + pbclist=NULL; + PathName=NULL; + + extRo=extRi=extZo=NULL; +} + +Chsolvdoc::~Chsolvdoc() +{ + // This space for rent. +} + +void Chsolvdoc::CleanUp() +{ + if (meshnode!=NULL) free(meshnode); + if (meshele!=NULL) free(meshele); + if (blockproplist!=NULL) free(blockproplist); + if (lineproplist!=NULL) free(lineproplist); + if (nodeproplist!=NULL) free(nodeproplist); + if (circproplist!=NULL) free(circproplist); + if (labellist!=NULL) free(labellist); + if (pbclist!=NULL) free(pbclist); + if (Tprev!=NULL) free(Tprev); +} + +///////////////////////////////////////////////////////////////////////////// +// Chsolvdoc commands + +char* StripKey(char *c) +{ + char *d; + int i,k; + + k=(int) strlen(c); + + for(i=0;i0) nodeproplist=(CPointProp *)calloc(k,sizeof(CPointProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + PProp.V=0; + PProp.qp=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&PProp.V); + 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[NumPointProps]=PProp; + NumPointProps++; + q[0]=NULL; + } + + // Boundary Properties; + if( _strnicmp(q,"[bdryprops]",11)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) lineproplist=(CBoundaryProp *)calloc(k,sizeof(CBoundaryProp)); + q[0]=NULL; + } + + if( _strnicmp(q,"",11)==0){ + 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); + 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[NumLineProps]=BProp; + NumLineProps++; + q[0]=NULL; + } + + // Block Properties; + if( _strnicmp(q,"[blockprops]",12)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) blockproplist=(CMaterialProp *)calloc(k,sizeof(CMaterialProp)); + q[0]=NULL; + } + + // timestep + if( _strnicmp(q,"[dt]",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&dT); + q[0]=NULL; + } + + // 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; + q[0]=NULL; + } + + if( _strnicmp(q,"",12)==0){ + MProp.Kx=1; + MProp.Ky=1; // permittivity, relative + MProp.Kt=0; + MProp.qv=0; // charge density, C/m^3 + MProp.npts=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Kx); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Ky); + q[0]=NULL; + } + + if( _strnicmp(q,"",6)==0){ + v=StripKey(s); + sscanf(v,"%lf",&MProp.Kt); + MProp.Kt*=1.e6; + q[0]=NULL; + } + + if( _strnicmp(q,"",5)==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[NumBlockProps]=MProp; + NumBlockProps++; + q[0]=NULL; + } + + // Conductor Properties + if( _strnicmp(q,"[conductorprops]",16)==0){ + v=StripKey(s); + sscanf(v,"%i",&k); + if(k>0) circproplist=(CCircuit *)calloc(k,sizeof(CCircuit)); + q[0]=NULL; + } + + if( _strnicmp(q,"",16)==0){ + CProp.V=0; + CProp.q=0; + CProp.CircType=0; + q[0]=NULL; + } + + if( _strnicmp(q,"",4)==0){ + v=StripKey(s); + sscanf(v,"%lf",&CProp.V); + 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[NumCircProps]=CProp; + NumCircProps++; + q[0]=NULL; + } + + // read in regional attributes + if(_strnicmp(q,"[numblocklabels]",13)==0){ + int i; + v=StripKey(s); + sscanf(v,"%i",&k); + if (k>0) labellist=(CBlockLabel *)calloc(k, sizeof(CBlockLabel)); + NumBlockLabels=k; + for(i=0;i1){ + // strip off point BC number; + j=n & 0xffff; + j=j-2; + if (j<0) j=-1; + + // strip off Conductor number + n= (n - (n & 0xffff))/0x10000 - 1; + } + else{ + j=-1; + n=-1; + } + node.bc=j; + node.InConductor=n; + + // convert all lengths to internal working units of mm + node.x*=c[LengthUnits]; + node.y*=c[LengthUnits]; + + meshnode[i]=node; + } + fclose(fp); + + //read in periodic boundary conditions; + sprintf(infile,"%s.pbc",PathName); + if((fp=fopen(infile,"rt"))==NULL){ + return FALSE; + } + fgets(s,1024,fp); + sscanf(s,"%i",&k); NumPBCs=k; + + if (k!=0) pbclist=(CCommonPoint *)calloc(k,sizeof(CCommonPoint)); + CCommonPoint pbc; + for(i=0;i=0) + { + meshnode[n0].InConductor=n; + meshnode[n1].InConductor=n; + } + } + else j=-1; + + if (j>=0) + { + // search through elements to find one containing the line; + // set corresponding edge equal to the bc number + for(q=0,n=FALSE;q=Re(Kn[npts-1])) return (Im(Kn[npts-1])*(1+I)); + + for(i=0,j=1;j=Re(Kn[i])) && (t<=Re(Kn[j]))) + { + return (1+I)*(Im(Kn[i])+Im(Kn[j]-Kn[i])*Re(t-Kn[i])/Re(Kn[j]-Kn[i])); + } + } + + return (Kx+I*Ky); +} \ No newline at end of file diff --git a/hsolv/hsolvdoc.h b/hsolv/hsolvdoc.h new file mode 100644 index 0000000..4790055 --- /dev/null +++ b/hsolv/hsolvdoc.h @@ -0,0 +1,76 @@ +#define muo 1.2566370614359173e-6 +#define Golden 0.3819660112501051517954131656 + +class Chsolvdoc +{ + + + +// Attributes +public: + + Chsolvdoc(); + ~Chsolvdoc(); + + // General problem attributes + double Precision; + double Depth; + int LengthUnits; + BOOL ProblemType; + BOOL Coords; + double dT; + CString PrevSoln; + + // Axisymmetric external region parameters + double extRo,extRi,extZo; + + ChsolvDlg *TheView; + + // CArrays containing the mesh information + int BandWidth; + CNode *meshnode; + CElement *meshele; + + int NumNodes; + int NumEls; + + // Vector containing previous solution for time-transient analysis + double *Tprev; + + // lists of properties + int NumBlockProps; + int NumPBCs; + int NumLineProps; + int NumPointProps; + int NumCircProps; + int NumBlockLabels; + + CMaterialProp *blockproplist; + CBoundaryProp *lineproplist; + CPointProp *nodeproplist; + CCircuit *circproplist; + CBlockLabel *labellist; + CCommonPoint *pbclist; + + // stuff usually kept track of by CDocument + char *PathName; + + +// Operations +public: + + BOOL LoadMesh(); + BOOL LoadPrev(); + BOOL OnOpenDocument(); + BOOL Cuthill(); + BOOL SortElements(); + BOOL AnalyzeProblem(CBigLinProb &L); + double ChargeOnConductor(int OnConductor, CBigLinProb &L); + BOOL WriteResults(CBigLinProb &L); + void CleanUp(); + +}; + +///////////////////////////////////////////////////////////////////////////// + +double Power(double x, int n); diff --git a/hsolv/prob1big.cpp b/hsolv/prob1big.cpp new file mode 100644 index 0000000..9d5ecde --- /dev/null +++ b/hsolv/prob1big.cpp @@ -0,0 +1,514 @@ +#include "stdafx.h" +#include +#include +#include "hsolv.h" +#include "hsolvDlg.h" +#include "mesh.h" +#include "spars.h" +#include "hsolvdoc.h" + +#define Ksb 5.67032e-8 // Stefan-Boltzmann Constant + +//conversion to internal working units of m +double units[]={0.0254,0.001,0.01,1,2.54e-5,1.e-6}; +double sq(double x){ return x*x; } + +BOOL Chsolvdoc::AnalyzeProblem(CBigLinProb &L) +{ + int i,j,k,bf,pctr=0; + double Me[3][3],be[3]; // element matrices; + double l[3],p[3],q[3]; // element shape parameters; + int n[3],ne[3]; // numbers of nodes for a particular element; + double a,K,r,z,kludge; + double bta,Tinf,Tlast,*Vo; + BOOL IsNonlinear=FALSE; + CElement *El; + CComplex kn; + int iter=0; + + Depth*=units[LengthUnits]; + extRo*=units[LengthUnits]; + extRi*=units[LengthUnits]; + extZo*=units[LengthUnits]; + kludge=1; + + TheView->SetDlgItemText(IDC_FRAME1,"Matrix Construction"); + + Vo=(double *) calloc(NumNodes,sizeof(double)); + + // scan through the problem to see if there are any elements + // with a nonlinear conductivity + for(i=0;i0){ + IsNonlinear=TRUE; + i=NumNodes; + } + } + + do{ + // copy old solution + for(i=0;i=0) + if(nodeproplist[meshnode[i].bc].qp==0) + { + L.V[i]=nodeproplist[meshnode[i].bc].V; + L.Q[i]=-1; + } + + if(meshnode[i].InConductor>=0) + if(circproplist[meshnode[i].InConductor].CircType==1) + { + L.V[i]=circproplist[meshnode[i].InConductor].V; + L.Q[i]=meshnode[i].InConductor; + } + } + + // account for fixed boundary conditions along segments; + for(i=0;i=0) + { + if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) + { + L.V[meshele[i].p[j]]=lineproplist[meshele[i].e[j]].Tset; + L.V[meshele[i].p[k]]=lineproplist[meshele[i].e[j]].Tset; + L.Q[meshele[i].p[j]]=-1; + L.Q[meshele[i].p[k]]=-1; + } + } + } + } + + + // build element matrices using the matrices derived in Allaire's book. + for(i=0;im_prog1.SetPos(pctr); } + + // zero out Me, be; + for(j=0;j<3;j++){ + for(k=0;k<3;k++) Me[j][k]=0; + be[j]=0; + } + + // Determine shape parameters. + // l's are element side lengths; + // p's corresponds to the `b' parameter in Allaire + // q's corresponds to the `c' parameter in Allaire + El=&meshele[i]; + + for(k=0;k<3;k++) n[k]=El->p[k]; + p[0]=meshnode[n[1]].y - meshnode[n[2]].y; + p[1]=meshnode[n[2]].y - meshnode[n[0]].y; + p[2]=meshnode[n[0]].y - meshnode[n[1]].y; + q[0]=meshnode[n[2]].x - meshnode[n[1]].x; + q[1]=meshnode[n[0]].x - meshnode[n[2]].x; + q[2]=meshnode[n[1]].x - meshnode[n[0]].x; + for(j=0,k=1;j<3;k++,j++){ + if (k==3) k=0; + l[j]=sqrt( sq(meshnode[n[k]].x-meshnode[n[j]].x) + + sq(meshnode[n[k]].y-meshnode[n[j]].y) ); + } + a=(p[0]*q[1]-p[1]*q[0])/2.; + r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; + + // get the thermal conductivites to use for this element; + kn = (blockproplist[El->blk].GetK(Vo[n[0]]) + + blockproplist[El->blk].GetK(Vo[n[1]]) + + blockproplist[El->blk].GetK(Vo[n[2]]))/3.; + + if (ProblemType==AXISYMMETRIC){ + Depth=2.*PI*r; + + // "Warp" the permeability of this element is part of + // the conformally mapped external region + if(labellist[meshele[i].lbl].IsExternal) + { + z=(meshnode[n[0]].y+meshnode[n[1]].y+meshnode[n[2]].y)/3. - extZo; + kludge=(r*r+z*z)/(extRi*extRo); + } + else kludge=1; + } + + + // x-contribution; + K = -Depth*Re(kn)/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] += K*p[j]*p[k]; + if (j!=k) Me[k][j]+=K*p[j]*p[k]; + } + + // y-contribution; + K = -Depth*Im(kn)/(4.*a)/kludge; + for(j=0;j<3;j++) + for(k=j;k<3;k++) + { + Me[j][k] +=K*q[j]*q[k]; + if (j!=k) Me[k][j]+=K*q[j]*q[k]; + } + + // contribution to Me and be from time-transient term +/* if (dT!=0) + { + K = -Depth*blockproplist[El->blk].Kt*a/(12.*dT); + + Me[0][0]+=2.*K; + Me[1][1]+=2.*K; + Me[2][2]+=2.*K; + Me[0][1]+=K; Me[1][0]+=K; + Me[0][2]+=K; Me[2][0]+=K; + Me[1][2]+=K; Me[2][1]+=K; + + be[0]+=K*(2.*Tprev[n[0]] + Tprev[n[1]] + Tprev[n[2]]); + be[1]+=K*( Tprev[n[0]] + 2.*Tprev[n[1]] + Tprev[n[2]]); + be[2]+=K*( Tprev[n[0]] + Tprev[n[1]] + 2.*Tprev[n[2]]); + } */ + + if (dT!=0) + { + K = -Depth*blockproplist[El->blk].Kt*a/(3.*dT); + + Me[0][0]+=K; + Me[1][1]+=K; + Me[2][2]+=K; + + be[0]+=K*Tprev[n[0]]; + be[1]+=K*Tprev[n[1]]; + be[2]+=K*Tprev[n[2]]; + } + + // contribution to be[] from volume charge density + for(j = 0;j<3;j++){ + K = -Depth*(blockproplist[El->blk].qv)*a/3.; + be[j]+=K; + } + + + for(j=0;j<3;j++) + { + if (El->e[j] >= 0) + { + k=j+1; if(k==3) k=0; + + if (ProblemType==AXISYMMETRIC) + Depth=PI*(meshnode[n[j]].x + meshnode[n[k]].x); + + // contributions to Me, be from derivative boundary conditions; + // !!! need to put in contribution here for radiation.... + bf=lineproplist[El->e[j]].BdryFormat; + if ((bf==1) || (bf==2) || (bf==3)) + { + double c0,c1; + + switch(bf) + { + case 1: + c1=lineproplist[El->e[j]].qs; + c0=0; + break; + case 2: + c0=lineproplist[El->e[j]].h; + c1=-c0*lineproplist[El->e[j]].Tinf; + break; + case 3: + IsNonlinear=TRUE; + bta =lineproplist[El->e[j]].beta; + Tinf=lineproplist[El->e[j]].Tinf; + Tlast=(Vo[n[j]]+Vo[n[k]])/2.; + + c0 = 4.*bta*Ksb*pow(Tlast,3.); + c1 = -(bta*Ksb*(pow(Tinf,4.) + 3.*pow(Tlast,4.))); + + break; + default: + break; + } + + if (ProblemType==AXISYMMETRIC) + { + K =-2.*PI*c0*l[j]/6.; + Me[j][j]+=K*2. *(3.*meshnode[n[j]].x + meshnode[n[k]].x)/4.; + Me[k][k]+=K*2. *(meshnode[n[j]].x + 3.*meshnode[n[k]].x)/4.; + Me[j][k]+=K *(meshnode[n[j]].x + meshnode[n[k]].x)/2.; + Me[k][j]+=K *(meshnode[n[j]].x + meshnode[n[k]].x)/2.; + + K = 2.*PI*c1*l[j]/2.; + be[j]+=K*(2.*meshnode[n[j]].x + meshnode[n[k]].x)/3.; + be[k]+=K*(meshnode[n[j]].x + 2.*meshnode[n[k]].x)/3.; + } + else + { + K =-Depth*c0*l[j]/6.; + Me[j][j]+=K*2.; + Me[k][k]+=K*2.; + Me[j][k]+=K; + Me[k][j]+=K; + + K = Depth*c1*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + } + /* + // contribution to be[] from surface heating + if (lineproplist[El->e[j]].BdryFormat==2) + { + K =-Depth*lineproplist[El->e[j]].qs*l[j]/2.; + be[j]+=K; + be[k]+=K; + } + */ + } + } + + // process any prescribed nodal values; + for(j=0;j<3;j++) + { + if(L.Q[n[j]]!=-2) + { + for(k=0;k<3;k++) + { + if(j!=k){ + be[k]-=Me[k][j]*L.V[n[j]]; + Me[k][j]=0; + Me[j][k]=0; + } + } + be[j]=L.V[n[j]]*Me[j][j]; + } + } + + // combine block matrices into global matrices; + for (j=0;j<3;j++) + { + ne[j]=n[j]; + if(meshnode[n[j]].InConductor>=0) + if(circproplist[meshnode[n[j]].InConductor].CircType==0) + ne[j]=meshnode[n[j]].InConductor+NumNodes; + } + for (j=0;j<3;j++){ + for (k=j;k<3;k++) + L.Put(L.Get(ne[j],ne[k])-Me[j][k],ne[j],ne[k]); + L.b[ne[j]]-=be[j]; + + if(ne[j]!=n[j]) + { + L.Put(L.Get(n[j],n[j])-Me[j][j],n[j],n[j]); + L.Put(L.Get(n[j],ne[j])+Me[j][j],n[j],ne[j]); + } + } + + } // end of loop that builds element matrices + + // add in contribution from point charge density; + for(i=0;i=0) && (L.Q[i]==-2)) + { + if (ProblemType==AXISYMMETRIC) Depth=2.*PI*meshnode[i].x; + L.b[i]+=(Depth*nodeproplist[meshnode[i].bc].qp); + L.Q[i]=-1; + } + + // some bookkeeping to denote which nodes we can smooth over + if(meshnode[i].InConductor>=0) L.Q[i]=meshnode[i].InConductor; + } + + // Apply any periodicity/antiperiodicity boundary conditions that we have + for(k=0,pctr=0;kSetDlgItemText(IDC_FRAME2,fmsg); + + for(i=0;i100) prog=100; + TheView->m_prog2.SetPos(prog); + + } + } + + }while(IsNonlinear); + + // compute total charge on conductors + // with a specified voltage + for(i=0;ifabs(im)){ + z=im/re; + w=sqrt(fabs(re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=re/im; + w=sqrt(fabs(im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(re>=0){ + y.re=w; + y.im=im/(2.*w); + return y; + } + + if(im>=0){ + y.re=fabs(im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(im)/(2.*w); + y.im= (-w); + return y; +} + +CComplex CComplex::Conj() +{ + return CComplex(re,-im); +} + +double CComplex::Abs() +{ + if ((re==0) && (im==0)) return 0.; + + if (fabs(re)>fabs(im)) + return fabs(re)*sqrt(1.+(im/re)*(im/re)); + else + return fabs(im)*sqrt(1.+(re/im)*(re/im)); +} + +double CComplex::Arg() +{ + if ((re==0) && (im==0)) return 0.; + + return atan2(im,re); +} + +CComplex CComplex::Inv() +{ + double c; + CComplex z; + + if(fabs(re)>fabs(im)) + { + c=im/re; + z.re=1./(re*(1.+c*c)); + z.im=(-c)*z.re; + } + else{ + c=re/im; + z.im=(-1.)/(im*(1.+c*c)); + z.re=(-c)*z.im; + } + + return z; +} + +double CComplex::Re() +{ + return re; +} + +double CComplex::Im() +{ + return im; +} + +void CComplex::Set(double x, double y) +{ + re=x; im=y; +} + +char* CComplex::ToString(char *s) +{ + if (im==0) sprintf(s,"%.16g",re); + else if (im==1) + { + if (re==0) sprintf(s,"I"); + else sprintf(s,"%.16g+I",re); + } + else if (im==-1) + { + if (re==0) sprintf(s,"-I"); + else sprintf(s,"%.16g-I",re); + } + else if (im<0) + { + if (re!=0) sprintf(s,"%.16g-I*%.16g",re,fabs(im)); + else sprintf(s,"-I*%.16g",fabs(im)); + } + else if (im>0) + { + if (re!=0) sprintf(s,"%.16g+I*%.16g",re,im); + else sprintf(s,"I*%.16g",im); + } + else s[0]=NULL; + + return s; +} + +char* CComplex::ToStringAlt(char *s) +{ + if (im==0) sprintf(s,"%g",re); + else if (im==1) + { + if (re==0) sprintf(s,"I"); + else sprintf(s,"%g+I",re); + } + else if (im==-1) + { + if (re==0) sprintf(s,"-I"); + else sprintf(s,"%g-I",re); + } + else if (im<0) + { + if (re!=0) sprintf(s,"%g-I*%g",re,fabs(im)); + else sprintf(s,"-I*%g",fabs(im)); + } + else if (im>0) + { + if (re!=0) sprintf(s,"%g+I*%g",re,im); + else sprintf(s,"I*%g",im); + } + else s[0]=NULL; + + return s; +} + +//******* Addition *************************************************** + +CComplex CComplex::operator+( const CComplex& z ) +{ + return CComplex(re+z.re,im+z.im); +}; + +CComplex CComplex::operator+( int z ) +{ + return CComplex(re+((double) z),im); +}; + +CComplex CComplex::operator+( long long z ) +{ + return CComplex(re+((double) z),im); +}; + +CComplex CComplex::operator+( double z ) +{ + return CComplex(re+z,im); +}; + +void CComplex::operator+=( const CComplex& z) +{ + re+=z.re; + im+=z.im; +}; + +void CComplex::operator+=( double z ) +{ + re+=z; +}; + +void CComplex::operator+=( int z ) +{ + re+=(double) z; +}; + +void CComplex::operator+=( long long z ) +{ + re+=(double) z; +}; + +CComplex operator+( int x, const CComplex& y ) +{ + return CComplex( ((double) x) + y.re, y.im ); +} + +CComplex operator+( double x, const CComplex& y ) +{ + return CComplex( x + y.re, y.im ); +} + +CComplex operator+( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re + y.re, x.im + y.im ); +} + + +//******* Subtraction *************************************************** +CComplex CComplex::operator-() +{ + return CComplex(-re,-im); +} + +CComplex CComplex::operator-( const CComplex& z) +{ + return CComplex(re-z.re,im-z.im); +}; + +CComplex CComplex::operator-( int z ) +{ + return CComplex(re-((double) z),im); +}; + +CComplex CComplex::operator-( long long z ) +{ + return CComplex(re-((double) z),im); +}; + +CComplex CComplex::operator-( double z ) +{ + return CComplex(re-z,im); +}; + +void CComplex::operator-=( const CComplex& z) +{ + re-=z.re; + im-=z.im; +}; + +void CComplex::operator-=( double z ) +{ + re-=z; +}; + +void CComplex::operator-=( int z ) +{ + re-=(double) z; +}; + +void CComplex::operator-=( long long z ) +{ + re-=(double) z; +}; + +CComplex operator-( int x, const CComplex& y ) +{ + return CComplex( ((double) x) - y.re, - y.im ); +} + +CComplex operator-( double x, const CComplex& y ) +{ + return CComplex( x - y.re, - y.im ); +} + +CComplex operator-( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re - y.re, x.im - y.im ); +} + +CComplex operator-( const CComplex& y ) +{ + return CComplex( -y.re,-y.im ); +} +//******* Multiplication *************************************************** + +CComplex CComplex::operator*( const CComplex& z) +{ + return CComplex(re*z.re - im*z.im,re*z.im + im*z.re); +}; + +CComplex CComplex::operator*( int z ) +{ + return CComplex( re*((double) z),im*((double) z) ); +}; + +CComplex CComplex::operator*( long long z ) +{ + return CComplex( re*((double) z),im*((double) z) ); +}; + +CComplex CComplex::operator*( double z ) +{ + return CComplex(re*z,im*z); +}; + +void CComplex::operator*=( const CComplex& z) +{ + CComplex x(re*z.re - im*z.im,re*z.im + im*z.re); + re=x.re; im=x.im; +}; + +void CComplex::operator*=( double z ) +{ + re*=z; im*=z; +}; + +void CComplex::operator*=( int z ) +{ + re*=(double) z; + im*=(double) z; +}; + +void CComplex::operator*=( long long z ) +{ + re*=(double) z; + im*=(double) z; +}; + +CComplex operator*( int x, const CComplex& y ) +{ + return CComplex( ((double) x) * y.re, ((double) x)*y.im ); +} + +CComplex operator*( double x, const CComplex& y ) +{ + return CComplex( x*y.re, x*y.im ); +} + +CComplex operator*( const CComplex& x, const CComplex& y ) +{ + return CComplex( x.re*y.re-x.im*y.im, x.re*y.im+x.im*y.re ); +} + +//******* Division *************************************************** + +CComplex CComplex::operator/( const CComplex& z) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return *this * y; +}; + + +CComplex CComplex::operator/( int z ) +{ + return CComplex(re/((double) z),im/((double) z)); +}; + +CComplex CComplex::operator/( long long z ) +{ + return CComplex(re/((double) z),im/((double) z)); +}; + +CComplex CComplex::operator/( double z ) +{ + return CComplex(re/z,im/z); +}; + +void CComplex::operator/=( const CComplex& z) +{ + *this=*this/z; +}; + +void CComplex::operator/=( double z ) +{ + re/=z; + im/=z; +}; + +void CComplex::operator/=( int z ) +{ + re/=(double) z; + im/=(double) z; +}; + +void CComplex::operator/=( long long z ) +{ + re/=(double) z; + im/=(double) z; +}; + +CComplex operator/( int x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*=(double) x; + y.im*=(double) x; + + return y; +} + +CComplex operator/( long long x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*=(double) x; + y.im*=(double) x; + + return y; +} + +CComplex operator/( double x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + y.re*= x; + y.im*= x; + + return y; +} + +CComplex operator/( const CComplex& x, const CComplex& z ) +{ + double c; + CComplex y; + + if(fabs(z.re)>fabs(z.im)) + { + c=z.im/z.re; + y.re=1./(z.re*(1.+c*c)); + y.im=(-c)*y.re; + } + else{ + c=z.re/z.im; + y.im=(-1.)/(z.im*(1.+c*c)); + y.re=(-c)*y.im; + } + + return x*y; +} + +//****** Equals definitions ******************************** + +void CComplex::operator=(double z) +{ + re=z; + im=0; +} + +void CComplex::operator=(int z) +{ + re=(double) z; + im=0; + +} + +void CComplex::operator=(long long z) +{ + re=(double) z; + im=0; + +} + +//***** Tests *********************************************** +bool CComplex::operator==( const CComplex& z){ + if ((z.im==im) && (z.re==re)) return true; + return false; +} + +bool CComplex::operator==(double z){ + if ((z==re) && (im==0)) return true; + return false; +} + +bool CComplex::operator==(int z){ + if ((re==(double) z) && (im==0)) return true; + return false; +} + +bool CComplex::operator==(long long z){ + if ((re==(double) z) && (im==0)) return true; + return false; +} + +bool CComplex::operator!=( const CComplex& z){ + if ((z.re==re) && (z.im==im)) return false; + return true; +} + +bool CComplex::operator!=(double z){ + if ((re!=z) || (im!=0)) return true; + return false; +} + +bool CComplex::operator!=(int z){ + if ((re!=(double) z) || (im!=0)) return true; + return false; +} + +bool CComplex::operator!=(long long z){ + if ((re!=(double) z) || (im!=0)) return true; + return false; +} + +bool CComplex::operator<( const CComplex& z){ + if (re( const CComplex& z){ + if (re>z.re) return true; + return false; +} + +bool CComplex::operator>(double z){ + if (re>z) return true; + return false; +} + +bool CComplex::operator>(int z){ + if (re>(double) z) return true; + return false; +} + +bool CComplex::operator>(long long z){ + if (re>(double) z) return true; + return false; +} + +bool CComplex::operator<=( const CComplex& z){ + if (re<=z.re) return true; + return false; +} + +bool CComplex::operator<=(double z){ + if (re<=z) return true; + return false; +} + +bool CComplex::operator<=(int z){ + if (re<=(double) z) return true; + return false; +} + +bool CComplex::operator<=(long long z){ + if (re<=(double) z) return true; + return false; +} + +bool CComplex::operator>=( const CComplex& z){ + if (re>=z.re) return true; + return false; +} + +bool CComplex::operator>=(double z){ + if (re>=z) return true; + return false; +} + +bool CComplex::operator>=(int z){ + if (re>=(double) z) return true; + return false; +} + +bool CComplex::operator>=(long long z){ + if (re>=(double) z) return true; + return false; +} + +//***** Useful functions ************************************ + +CComplex conj( const CComplex& x) +{ + return CComplex(x.re,-x.im); +} + +CComplex exp( const CComplex& x) +{ + CComplex y; + + y.re=cos(x.im)*exp(x.re); + y.im=sin(x.im)*exp(x.re); + + return y; +} + +CComplex sqrt( const CComplex& x) +{ + double w,z; + CComplex y; + + if((x.re==0) && (x.im==0)) w=0; + else if(fabs(x.re)>fabs(x.im)){ + z=x.im/x.re; + w=sqrt(fabs(x.re))*sqrt( (1.+sqrt(1.+z*z))/2. ); + } + else{ + z=x.re/x.im; + w=sqrt(fabs(x.im))*sqrt( (fabs(z)+sqrt(1.+z*z))/2. ); + } + + if(w==0){ + y.re=0; + y.im=0; + return y; + } + + if(x.re>=0){ + y.re=w; + y.im=x.im/(2.*w); + return y; + } + + if(x.im>=0){ + y.re=fabs(x.im)/(2.*w); + y.im=w; + return y; + } + + y.re=fabs(x.im)/(2.*w); + y.im= (-w); + + return y; +} + +CComplex tanh( const CComplex& x) +{ + CComplex y; + + if (x.re>0){ + y=(1-exp(-2*x))/(1+exp(-2*x)); + } + else{ + y=(exp(2*x)-1)/(exp(2*x)+1); + } + + return y; +} + +CComplex sinh( const CComplex& x) +{ + return (exp(x)-exp(-x))/2; +} + +CComplex cosh( const CComplex& x) +{ + return (exp(x)+exp(-x))/2; +} + + +CComplex cos( const CComplex& x) +{ + return (exp(I*x)+exp(-I*x))/2; +} + +CComplex acos( const CComplex& x) +{ + if (x.im==0) + { + if ((x.re<=1) && (x.re>=-1)) return PI/2. - arg(I*x + sqrt(1 - x*x)); + } + + return PI/2. - arg(I*x + sqrt(1 - x*x)) + I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex sin( const CComplex& x) +{ + return (exp(I*x)-exp(-I*x))/(2*I); +} + +CComplex asin( const CComplex& x) +{ + if (x.im==0) + { + if ((x.re<=1) && (x.re>=-1)) return arg(I*x + sqrt(1 - x*x)); + } + + return arg(I*x + sqrt(1 - x*x)) - I*log(abs(I*x + sqrt(1 - x*x))); +} + +CComplex tan( const CComplex& x) +{ + return sin(x)/cos(x); +} + +CComplex atan( const CComplex& x) +{ + if (x.im==0) return CComplex(atan(x.re),0); + + return (arg(1+I*x) - arg(1-I*x) - I*(log(abs(1+I*x)/abs(1-I*x))))/ 2; +} + +CComplex atan2( const CComplex& y, const CComplex& x) +{ + if ((y.im==0) && (x.im==0)) return CComplex(atan2(y.re,x.re),0); + + return (arg((x+I*y)/sqrt(x*x+y*y)) - I*log(abs(x+I*y)/sqrt(abs(x*x+y*y)))); +} + +double abs( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + if (fabs(x.re)>fabs(x.im)) + return fabs(x.re)*sqrt(1.+(x.im/x.re)*(x.im/x.re)); + else + return fabs(x.im)*sqrt(1.+(x.re/x.im)*(x.re/x.im)); +} + +double absq( const CComplex& x) +{ + return (x.re*x.re + x.im*x.im); +} + +double arg( const CComplex& x) +{ + if ((x.re==0) && (x.im==0)) return 0.; + + return atan2(x.im,x.re); +} + +CComplex log( const CComplex& x) +{ + CComplex y; + + y.im=arg(x); + y.re=log(abs(x)); + + return y; +} + +CComplex pow( const CComplex& x, int y) +{ + if (y==0) return CComplex(1,0); + + int i; + CComplex z; + + if (y>0){ + z=x; + for(i=1;i( const CComplex& z); + bool operator>( double z); + bool operator>( int z); + bool operator>( long long z); + + bool operator>=( const CComplex& z); + bool operator>=( double z); + bool operator>=( int z); + bool operator>=( long long z); + + + private: + +}; + +// useful functions... +#define I CComplex(0,1) +double Re( const CComplex& a); +double Im( const CComplex& a); +double abs( const CComplex& x ); +double absq( const CComplex& x ); +double arg( const CComplex& x ); +CComplex conj( const CComplex& x); +CComplex exp( const CComplex& x ); +CComplex sqrt( const CComplex& x ); +CComplex tanh( const CComplex& x ); +CComplex sinh( const CComplex& x ); +CComplex cosh( const CComplex& x ); +CComplex cos( const CComplex& x ); +CComplex acos( const CComplex& x ); +CComplex sin( const CComplex& x ); +CComplex asin( const CComplex& x ); +CComplex tan( const CComplex& x ); +CComplex atan( const CComplex& x ); +CComplex atan2( const CComplex& y, const CComplex& x); +CComplex log( const CComplex& x ); +CComplex pow( const CComplex& x, int y); +CComplex pow( const CComplex& x, double y); +CComplex pow( const CComplex& x, const CComplex& y); +CComplex Chop( const CComplex& a, double tol=1.e-12); + + + + +#endif // CCOMPLEX check \ No newline at end of file diff --git a/liblua/lapi.cpp b/liblua/lapi.cpp new file mode 100644 index 0000000..02e4ea6 --- /dev/null +++ b/liblua/lapi.cpp @@ -0,0 +1,504 @@ +/* +** $Id: lapi.c,v 1.110 2000/10/30 12:50:09 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +const char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $"; + + + +#define Index(L,i) ((i) >= 0 ? (L->Cbase+((i)-1)) : (L->top+(i))) + +#define api_incr_top(L) incr_top + + + + +TObject *luaA_index (lua_State *L, int index) { + return Index(L, index); +} + + +static TObject *luaA_indexAcceptable (lua_State *L, int index) { + if (index >= 0) { + TObject *o = L->Cbase+(index-1); + if (o >= L->top) return NULL; + else return o; + } + else return L->top+index; +} + + +void luaA_pushobject (lua_State *L, const TObject *o) { + *L->top = *o; + incr_top; +} + +LUA_API int lua_stackspace (lua_State *L) { + return (L->stack_last - L->top); +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return (L->top - L->Cbase); +} + + +LUA_API void lua_settop (lua_State *L, int index) { + if (index >= 0) + luaD_adjusttop(L, L->Cbase, index); + else + L->top = L->top+index+1; /* index is negative */ +} + + +LUA_API void lua_remove (lua_State *L, int index) { + StkId p = luaA_index(L, index); + while (++p < L->top) *(p-1) = *p; + L->top--; +} + + +LUA_API void lua_insert (lua_State *L, int index) { + StkId p = luaA_index(L, index); + StkId q; + for (q = L->top; q>p; q--) + *q = *(q-1); + *p = *L->top; +} + + +LUA_API void lua_pushvalue (lua_State *L, int index) { + *L->top = *luaA_index(L, index); + api_incr_top(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL) ? LUA_TNONE : ttype(o); +} + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaO_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL) ? 0 : iscfunction(o); +} + +LUA_API int lua_isnumber (lua_State *L, int index) { + TObject *o = luaA_indexAcceptable(L, index); + return (o == NULL) ? 0 : (tonumber(o) == 0); +} + +LUA_API int lua_isstring (lua_State *L, int index) { + int t = lua_type(L, index); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_tag (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL) ? LUA_NOTAG : luaT_tag(o); +} + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1 = luaA_indexAcceptable(L, index1); + StkId o2 = luaA_indexAcceptable(L, index2); + if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ + else return luaO_equalObj(o1, o2); +} + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1 = luaA_indexAcceptable(L, index1); + StkId o2 = luaA_indexAcceptable(L, index2); + if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ + else return luaV_lessthan(L, o1, o2, L->top); +} + +//!!!! + +LUA_API CComplex lua_tonumber (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + + return ((o == NULL || tonumber(o)) ? 0 : nvalue(o)); + +// return nvalue(o); + +} + +LUA_API const char *lua_tostring (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL || tostring(L, o)) ? NULL : svalue(o); +} + +LUA_API size_t lua_strlen (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL || tostring(L, o)) ? 0 : tsvalue(o)->len; +} + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c; +} + +LUA_API void *lua_touserdata (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : + tsvalue(o)->u.d.value; +} + +LUA_API const void *lua_topointer (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + if (o == NULL) return NULL; + switch (ttype(o)) { + case LUA_TTABLE: + return hvalue(o); + case LUA_TFUNCTION: + return clvalue(o); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + ttype(L->top) = LUA_TNIL; + api_incr_top(L); +} + +/* +LUA_API void lua_pushnumber (lua_State *L, double n) { + nvalue(L->top) = n; + ttype(L->top) = LUA_TNUMBER; + api_incr_top(L); +} +*/ +LUA_API void lua_pushnumber (lua_State *L, CComplex n) { + nvalue(L->top) = n; + ttype(L->top) = LUA_TNUMBER; + api_incr_top(L); +} + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + tsvalue(L->top) = luaS_newlstr(L, s, len); + ttype(L->top) = LUA_TSTRING; + api_incr_top(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + luaV_Cclosure(L, fn, n); +} + + +LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) { + /* ORDER LUA_T */ + if (!(tag == LUA_ANYTAG || tag == LUA_TUSERDATA || validtag(tag))) + luaO_verror(L, "invalid tag for a userdata (%d)", tag); + tsvalue(L->top) = luaS_createudata(L, u, tag); + ttype(L->top) = LUA_TUSERDATA; + api_incr_top(L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_getglobal (lua_State *L, const char *name) { + StkId top = L->top; + *top = *luaV_getglobal(L, luaS_new(L, name)); + L->top = top; + api_incr_top(L); +} + + +LUA_API void lua_gettable (lua_State *L, int index) { + StkId t = Index(L, index); + StkId top = L->top; + *(top-1) = *luaV_gettable(L, t); + L->top = top; /* tag method may change top */ +} + + +LUA_API void lua_rawget (lua_State *L, int index) { + StkId t = Index(L, index); + LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); + *(L->top - 1) = *luaH_get(L, hvalue(t), L->top - 1); +} + + +LUA_API void lua_rawgeti (lua_State *L, int index, int n) { + StkId o = Index(L, index); + LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); + *L->top = *luaH_getnum(hvalue(o), n); + api_incr_top(L); +} + + +LUA_API void lua_getglobals (lua_State *L) { + hvalue(L->top) = L->gt; + ttype(L->top) = LUA_TTABLE; + api_incr_top(L); +} + + +LUA_API int lua_getref (lua_State *L, int ref) { + if (ref == LUA_REFNIL) + ttype(L->top) = LUA_TNIL; + else if (0 <= ref && ref < L->refSize && + (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) + *L->top = L->refArray[ref].o; + else + return 0; + api_incr_top(L); + return 1; +} + + +LUA_API void lua_newtable (lua_State *L) { + hvalue(L->top) = luaH_new(L, 0); + ttype(L->top) = LUA_TTABLE; + api_incr_top(L); +} + + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_setglobal (lua_State *L, const char *name) { + StkId top = L->top; + luaV_setglobal(L, luaS_new(L, name)); + L->top = top-1; /* remove element from the top */ +} + + +LUA_API void lua_settable (lua_State *L, int index) { + StkId t = Index(L, index); + StkId top = L->top; + luaV_settable(L, t, top-2); + L->top = top-2; /* pop index and value */ +} + + +LUA_API void lua_rawset (lua_State *L, int index) { + StkId t = Index(L, index); + LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); + *luaH_set(L, hvalue(t), L->top-2) = *(L->top-1); + L->top -= 2; +} + + +LUA_API void lua_rawseti (lua_State *L, int index, int n) { + StkId o = Index(L, index); + LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); + *luaH_setint(L, hvalue(o), n) = *(L->top-1); + L->top--; +} + + +LUA_API void lua_setglobals (lua_State *L) { + StkId newtable = --L->top; + LUA_ASSERT(ttype(newtable) == LUA_TTABLE, "table expected"); + L->gt = hvalue(newtable); +} + + +LUA_API int lua_ref (lua_State *L, int lock) { + int ref; + if (ttype(L->top-1) == LUA_TNIL) + ref = LUA_REFNIL; + else { + if (L->refFree != NONEXT) { /* is there a free place? */ + ref = L->refFree; + L->refFree = L->refArray[ref].st; + } + else { /* no more free places */ + luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref, + "reference table overflow", MAX_INT); + L->nblocks += sizeof(struct Ref); + ref = L->refSize++; + } + L->refArray[ref].o = *(L->top-1); + L->refArray[ref].st = lock ? LOCK : HOLD; + } + L->top--; + return ref; +} + + +/* +** "do" functions (run Lua code) +** (most of them are in ldo.c) +*/ + +LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) { + luaD_call(L, L->top-(nargs+1), nresults); +} + + +/* +** Garbage-collection functions +*/ + +/* GC values are expressed in Kbytes: #bytes/2^10 */ +#define GCscale(x) ((int)((x)>>10)) +#define GCunscale(x) ((unsigned long)(x)<<10) + +LUA_API int lua_getgcthreshold (lua_State *L) { + return GCscale(L->GCthreshold); +} + +LUA_API int lua_getgccount (lua_State *L) { + return GCscale(L->nblocks); +} + +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { + if (newthreshold > GCscale(ULONG_MAX)) + L->GCthreshold = ULONG_MAX; + else + L->GCthreshold = GCunscale(newthreshold); + luaC_checkGC(L); +} + + +/* +** miscellaneous functions +*/ + +LUA_API void lua_settag (lua_State *L, int tag) { + luaT_realtag(L, tag); + switch (ttype(L->top-1)) { + case LUA_TTABLE: + hvalue(L->top-1)->htag = tag; + break; + case LUA_TUSERDATA: + tsvalue(L->top-1)->u.d.tag = tag; + break; + default: + luaO_verror(L, "cannot change the tag of a %.20s", + luaO_typename(L->top-1)); + } +} + + +LUA_API void lua_unref (lua_State *L, int ref) { + if (ref >= 0) { + LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref"); + L->refArray[ref].st = L->refFree; + L->refFree = ref; + } +} + + +LUA_API int lua_next (lua_State *L, int index) { + StkId t = luaA_index(L, index); + Node *n; + LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); + n = luaH_next(L, hvalue(t), luaA_index(L, -1)); + if (n) { + *(L->top-1) = *key(n); + *L->top = *val(n); + api_incr_top(L); + return 1; + } + else { /* no more elements */ + L->top -= 1; /* remove key */ + return 0; + } +} + + +LUA_API int lua_getn (lua_State *L, int index) { + Hash *h = hvalue(luaA_index(L, index)); + const TObject *value = luaH_getstr(h, luaS_new(L, "n")); /* value = h.n */ + if (ttype(value) == LUA_TNUMBER) +// return (int)nvalue(value); +return (int) Re(nvalue(value)); + else { + Number max = 0; + int i = h->size; + Node *n = h->node; + while (i--) { + if (ttype(key(n)) == LUA_TNUMBER && + ttype(val(n)) != LUA_TNIL && + Re(nvalue(key(n))) > Re(max)) + max = nvalue(key(n)); + n++; + } + return (int) Re(max); + } +} + + +LUA_API void lua_concat (lua_State *L, int n) { + StkId top = L->top; + luaV_strconc(L, n, top); + L->top = top-(n-1); + luaC_checkGC(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + TString *ts = luaS_newudata(L, size, NULL); + tsvalue(L->top) = ts; + ttype(L->top) = LUA_TUSERDATA; + api_incr_top(L); + return ts->u.d.value; +} + diff --git a/liblua/lapi.h b/liblua/lapi.h new file mode 100644 index 0000000..5cefdc7 --- /dev/null +++ b/liblua/lapi.h @@ -0,0 +1,17 @@ +/* +** $Id: lapi.h,v 1.20 2000/08/31 14:08:27 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +TObject *luaA_index (lua_State *L, int index); +void luaA_pushobject (lua_State *L, const TObject *o); + +#endif diff --git a/liblua/lauxlib.cpp b/liblua/lauxlib.cpp new file mode 100644 index 0000000..35eb468 --- /dev/null +++ b/liblua/lauxlib.cpp @@ -0,0 +1,218 @@ +/* +** $Id: lauxlib.c,v 1.43 2000/10/30 13:07:48 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +** With care, these functions can be used by other libraries. +*/ + +#include "lua.h" + +#include "lauxlib.h" +#include "luadebug.h" + + + +LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { + int i; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + return -1; /* name not found */ +} + +LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + lua_getstack(L, 0, &ar); + lua_getinfo(L, "n", &ar); + if (ar.name == NULL) + ar.name = "?"; + luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", + narg, ar.name, extramsg); +} + + +static void type_error (lua_State *L, int narg, int t) { + char buff[50]; + sprintf(buff, "%.8s expected, got %.8s", lua_typename(L, t), + lua_typename(L, lua_type(L, narg))); + luaL_argerror(L, narg, buff); +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (space > lua_stackspace(L)) + luaL_verror(L, "stack overflow (%.30s)", mes); +} + + +LUALIB_API void luaL_checktype(lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + type_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { + const char *s = lua_tostring(L, narg); + if (!s) type_error(L, narg, LUA_TSTRING); + if (len) *len = lua_strlen(L, narg); + return s; +} + + +LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) { + if (lua_isnull(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_check_lstr(L, narg, len); +} + + +LUALIB_API CComplex luaL_check_number (lua_State *L, int narg) { + CComplex d = lua_tonumber(L, narg); +// return d + + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + type_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API CComplex luaL_opt_number (lua_State *L, int narg, double def) { + if (lua_isnull(L, narg)) return def; + else return luaL_check_number(L, narg); +} + + +LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n) { + int i; + for (i=0; ip == (B)->buffer) +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->level++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->level > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->level - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->level); + if (toget >= 2) { + lua_concat(L, toget); + B->level = B->level - toget + 1; + } + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_putchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + if (B->level == 0) + lua_pushlstring(B->L, NULL, 0); + else if (B->level > 1) + lua_concat(B->L, B->level); + B->level = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl = lua_strlen(L, -1); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, lua_tostring(L, -1), vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->level++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->level = 0; +} + +/* }====================================================== */ diff --git a/liblua/lauxlib.h b/liblua/lauxlib.h new file mode 100644 index 0000000..52c0102 --- /dev/null +++ b/liblua/lauxlib.h @@ -0,0 +1,100 @@ +/* +** $Id: lauxlib.h,v 1.30 2000/10/30 12:38:50 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API extern +#endif + + +struct luaL_reg { + const char *name; + lua_CFunction func; +}; + + +LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n); +LUALIB_API void luaL_argerror (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg, size_t *len); +LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg, const char *def, size_t *len); +LUALIB_API CComplex luaL_check_number (lua_State *L, int numArg); +LUALIB_API CComplex luaL_opt_number (lua_State *L, int numArg, double def); + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg); +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); +LUALIB_API void luaL_checkany (lua_State *L, int narg); + +LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); +LUALIB_API int luaL_findstring (const char *name, const char *const list[]); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \ + luaL_argerror(L, numarg,extramsg) +#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL)) +#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL)) +#define luaL_check_int(L,n) ((int) Re(luaL_check_number(L, n))) +#define luaL_check_long(L,n) ((long) Re(luaL_check_number(L, n))) +#define luaL_opt_int(L,n,d) ((int) Re(luaL_opt_number(L, n,d))) +#define luaL_opt_long(L,n,d) ((long) Re(luaL_opt_number(L, n,d))) +#define luaL_openl(L,a) luaL_openlib(L, a, (sizeof(a)/sizeof(a[0]))) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#ifndef LUAL_BUFFERSIZE +#define LUAL_BUFFERSIZE BUFSIZ +#endif + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int level; + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_putchar(B,c) \ + ((void)((B)->p < &(B)->buffer[LUAL_BUFFERSIZE] || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); +LUALIB_API void luaL_addvalue (luaL_Buffer *B); +LUALIB_API void luaL_pushresult (luaL_Buffer *B); + + +/* }====================================================== */ + + +#endif + + diff --git a/liblua/lbaselib.cpp b/liblua/lbaselib.cpp new file mode 100644 index 0000000..7c968dc --- /dev/null +++ b/liblua/lbaselib.cpp @@ -0,0 +1,651 @@ +/* +** $Id: lbaselib.c,v 1.17 2000/11/06 13:45:18 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "luadebug.h" +#include "lualib.h" + + + +/* +** If your system does not support `stderr', redefine this function, or +** redefine _ERRORMESSAGE so that it won't need _ALERT. +*/ +static int luaB__ALERT (lua_State *L) { + fputs(luaL_check_string(L, 1), stderr); + return 0; +} + + +/* +** Basic implementation of _ERRORMESSAGE. +** The library `liolib' redefines _ERRORMESSAGE for better error information. +*/ +static int luaB__ERRORMESSAGE (lua_State *L) { + luaL_checktype(L, 1, LUA_TSTRING); + lua_getglobal(L, LUA_ALERT); + if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ + lua_Debug ar; + lua_pushstring(L, "error: "); + lua_pushvalue(L, 1); + if (lua_getstack(L, 1, &ar)) { + lua_getinfo(L, "Sl", &ar); + if (ar.source && ar.currentline > 0) { + char buff[100]; + sprintf(buff, "\n <%.70s: line %d>", ar.short_src, ar.currentline); + lua_pushstring(L, buff); + lua_concat(L, 2); + } + } + lua_pushstring(L, "\n"); + lua_concat(L, 3); + lua_rawcall(L, 1, 0); + } + return 0; +} + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_rawcall(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + lua_error(L, "`tostring' must return a string to `print'"); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_opt_int(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_check_string(L, 1); + char *s2; + unsigned long n; + luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)*s2)) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, CComplex(n,0)); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + lua_error(L, luaL_opt_string(L, 1, NULL)); + return 0; /* to avoid warnings */ +} + +static int luaB_setglobal (lua_State *L) { + luaL_checkany(L, 2); + lua_setglobal(L, luaL_check_string(L, 1)); + return 0; +} + +static int luaB_getglobal (lua_State *L) { + lua_getglobal(L, luaL_check_string(L, 1)); + return 1; +} + +static int luaB_tag (lua_State *L) { + luaL_checkany(L, 1); + lua_pushnumber(L, lua_tag(L, 1)); + return 1; +} + +static int luaB_settag (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, 1); /* push table */ + lua_settag(L, luaL_check_int(L, 2)); + return 1; /* return table */ +} + +static int luaB_newtag (lua_State *L) { + lua_pushnumber(L, lua_newtag(L)); + return 1; +} + +static int luaB_copytagmethods (lua_State *L) { + lua_pushnumber(L, lua_copytagmethods(L, luaL_check_int(L, 1), + luaL_check_int(L, 2))); + return 1; +} + +static int luaB_globals (lua_State *L) { + lua_getglobals(L); /* value to be returned */ + if (!lua_isnull(L, 1)) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, 1); /* new table of globals */ + lua_setglobals(L); + } + return 1; +} + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_rawget(L, -2); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_rawset(L, -3); + return 1; +} + +static int luaB_settagmethod (lua_State *L) { + int tag = luaL_check_int(L, 1); + const char *event = luaL_check_string(L, 2); + luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, + "function or nil expected"); + if (strcmp(event, "gc") == 0) + lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua"); + lua_gettagmethod(L, tag, event); + lua_pushvalue(L, 3); + lua_settagmethod(L, tag, event); + return 1; +} + + +static int luaB_gettagmethod (lua_State *L) { + int tag = luaL_check_int(L, 1); + const char *event = luaL_check_string(L, 2); + if (strcmp(event, "gc") == 0) + lua_error(L, "deprecated use: cannot get the `gc' tag method from Lua"); + lua_gettagmethod(L, tag, event); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushnumber(L, lua_getgccount(L)); + lua_pushnumber(L, lua_getgcthreshold(L)); + return 2; +} + + +static int luaB_collectgarbage (lua_State *L) { + lua_setgcthreshold(L, luaL_opt_int(L, 1, 0)); + return 0; +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, lua_typename(L, lua_type(L, 1))); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int passresults (lua_State *L, int status, int oldtop) { + static const char *const errornames[] = + {"ok", "run-time error", "file error", "syntax error", + "memory error", "error in error handling"}; + if (status == 0) { + int nresults = lua_gettop(L) - oldtop; + if (nresults > 0) + return nresults; /* results are already on the stack */ + else { + lua_pushuserdata(L, NULL); /* at least one result to signal no errors */ + return 1; + } + } + else { /* error */ + lua_pushnil(L); + lua_pushstring(L, errornames[status]); /* error code */ + return 2; + } +} + +static int luaB_dostring (lua_State *L) { + int oldtop = lua_gettop(L); + size_t l; + const char *s = luaL_check_lstr(L, 1, &l); + if (*s == '\27') /* binary files start with ESC... */ + lua_error(L, "`dostring' cannot run pre-compiled code"); + return passresults(L, lua_dobuffer(L, s, l, luaL_opt_string(L, 2, s)), oldtop); +} + + +static int luaB_dofile (lua_State *L) { + int oldtop = lua_gettop(L); + const char *fname = luaL_opt_string(L, 1, NULL); + return passresults(L, lua_dofile(L, fname), oldtop); +} + + +static int luaB_call (lua_State *L) { + int oldtop; + const char *options = luaL_opt_string(L, 3, ""); + int err = 0; /* index of old error method */ + int i, status; + int n; + luaL_checktype(L, 2, LUA_TTABLE); + n = lua_getn(L, 2); + if (!lua_isnull(L, 4)) { /* set new error method */ + lua_getglobal(L, LUA_ERRORMESSAGE); + err = lua_gettop(L); /* get index */ + lua_pushvalue(L, 4); + lua_setglobal(L, LUA_ERRORMESSAGE); + } + oldtop = lua_gettop(L); /* top before function-call preparation */ + /* push function */ + lua_pushvalue(L, 1); + luaL_checkstack(L, n, "too many arguments"); + for (i=0; i=pos; n--) { + lua_rawgeti(L, 1, n); + lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ + } + lua_pushvalue(L, v); + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int luaB_tremove (lua_State *L) { + int pos, n; + luaL_checktype(L, 1, LUA_TTABLE); + n = lua_getn(L, 1); + pos = luaL_opt_int(L, 2, n); + if (n <= 0) return 0; /* table is "empty" */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) lua_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (jt.token); +} + + +/* +** Returns the the previous instruction, for optimizations. +** If there is a jump target between this and the current instruction, +** returns a dummy instruction to avoid wrong optimizations. +*/ +static Instruction previous_instruction (FuncState *fs) { + if (fs->pc > fs->lasttarget) /* no jumps to current position? */ + return fs->f->code[fs->pc-1]; /* returns previous instruction */ + else + return CREATE_0(OP_END); /* no optimizations after an `END' */ +} + + +int luaK_jump (FuncState *fs) { + int j = luaK_code1(fs, OP_JMP, NO_JUMP); + if (j == fs->lasttarget) { /* possible jumps to this jump? */ + luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ + fs->jlt = NO_JUMP; + } + return j; +} + + +static void luaK_fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + if (dest == NO_JUMP) + SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ + else { /* jump is relative to position following jump instruction */ + int offset = dest-(pc+1); + if (abs(offset) > MAXARG_S) + luaK_error(fs->ls, "control structure too long"); + SETARG_S(*jmp, offset); + } +} + + +static int luaK_getjump (FuncState *fs, int pc) { + int offset = GETARG_S(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +** discharge list of jumps to last target. +*/ +int luaK_getlabel (FuncState *fs) { + if (fs->pc != fs->lasttarget) { + int lasttarget = fs->lasttarget; + fs->lasttarget = fs->pc; + luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ + fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ + } + return fs->pc; +} + + +void luaK_deltastack (FuncState *fs, int delta) { + fs->stacklevel += delta; + if (fs->stacklevel > fs->f->maxstacksize) { + if (fs->stacklevel > MAXSTACK) + luaK_error(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = fs->stacklevel; + } +} + + +void luaK_kstr (LexState *ls, int c) { + luaK_code1(ls->fs, OP_PUSHSTRING, c); +} + + +static int number_constant (FuncState *fs, Number r) { + /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ + Proto *f = fs->f; + int c = f->nknum; + int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; + while (--c >= lim) + if (f->knum[c] == r) return c; + /* not found; create a new entry */ + luaM_growvector(fs->L, f->knum, f->nknum, 1, Number, + "constant table overflow", MAXARG_U); + c = f->nknum++; + f->knum[c] = r; + return c; +} + + +void luaK_number (FuncState *fs, Number f) { + if (f <= (Number)MAXARG_S && (Number)(int)Re(f) == f) + luaK_code1(fs, OP_PUSHINT, (int)Re(f)); /* f has a short integer value */ + else + luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); +} + + +void luaK_adjuststack (FuncState *fs, int n) { + if (n > 0) + luaK_code1(fs, OP_POP, n); + else + luaK_code1(fs, OP_PUSHNIL, -n); +} + + +int luaK_lastisopen (FuncState *fs) { + /* check whether last instruction is an open function call */ + Instruction i = previous_instruction(fs); + if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) + return 1; + else return 0; +} + + +void luaK_setcallreturns (FuncState *fs, int nresults) { + if (luaK_lastisopen(fs)) { /* expression is an open function call? */ + SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ + luaK_deltastack(fs, nresults); /* push results */ + } +} + + +static int discharge (FuncState *fs, expdesc *var) { + switch (var->k) { + case VLOCAL: + luaK_code1(fs, OP_GETLOCAL, var->u.index); + break; + case VGLOBAL: + luaK_code1(fs, OP_GETGLOBAL, var->u.index); + break; + case VINDEXED: + luaK_code0(fs, OP_GETTABLE); + break; + case VEXP: + return 0; /* nothing to do */ + } + var->k = VEXP; + var->u.l.t = var->u.l.f = NO_JUMP; + return 1; +} + + +static void discharge1 (FuncState *fs, expdesc *var) { + discharge(fs, var); + /* if it has jumps then it is already discharged */ + if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) + luaK_setcallreturns(fs, 1); /* call must return 1 value */ +} + + +void luaK_storevar (LexState *ls, const expdesc *var) { + FuncState *fs = ls->fs; + switch (var->k) { + case VLOCAL: + luaK_code1(fs, OP_SETLOCAL, var->u.index); + break; + case VGLOBAL: + luaK_code1(fs, OP_SETGLOBAL, var->u.index); + break; + case VINDEXED: /* table is at top-3; pop 3 elements after operation */ + luaK_code2(fs, OP_SETTABLE, 3, 3); + break; + default: + LUA_INTERNALERROR("invalid var kind to store"); + } +} + + +static OpCode invertjump (OpCode op) { + switch (op) { + case OP_JMPNE: return OP_JMPEQ; + case OP_JMPEQ: return OP_JMPNE; + case OP_JMPLT: return OP_JMPGE; + case OP_JMPLE: return OP_JMPGT; + case OP_JMPGT: return OP_JMPLE; + case OP_JMPGE: return OP_JMPLT; + case OP_JMPT: case OP_JMPONT: return OP_JMPF; + case OP_JMPF: case OP_JMPONF: return OP_JMPT; + default: + LUA_INTERNALERROR("invalid jump instruction"); + return OP_END; /* to avoid warnings */ + } +} + + +static void luaK_patchlistaux (FuncState *fs, int list, int target, + OpCode special, int special_target) { + Instruction *code = fs->f->code; + while (list != NO_JUMP) { + int next = luaK_getjump(fs, list); + Instruction *i = &code[list]; + OpCode op = GET_OPCODE(*i); + if (op == special) /* this `op' already has a value */ + luaK_fixjump(fs, list, special_target); + else { + luaK_fixjump(fs, list, target); /* do the patch */ + if (op == OP_JMPONT) /* remove eventual values */ + SET_OPCODE(*i, OP_JMPT); + else if (op == OP_JMPONF) + SET_OPCODE(*i, OP_JMPF); + } + list = next; + } +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->lasttarget) /* same target that list `jlt'? */ + luaK_concat(fs, &fs->jlt, list); /* delay fixing */ + else + luaK_patchlistaux(fs, list, target, OP_END, 0); +} + + +static int need_value (FuncState *fs, int list, OpCode hasvalue) { + /* check whether list has a jump without a value */ + for (; list != NO_JUMP; list = luaK_getjump(fs, list)) + if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; + return 0; /* not found */ +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + for (;;) { /* traverse `l1' */ + int next = luaK_getjump(fs, list); + if (next == NO_JUMP) { /* end of list? */ + luaK_fixjump(fs, list, l2); + return; + } + list = next; + } + } +} + + +static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { + int prevpos; /* position of last instruction */ + Instruction *previous; + int *golist, *exitlist; + if (!invert) { + golist = &v->u.l.f; /* go if false */ + exitlist = &v->u.l.t; /* exit if true */ + } + else { + golist = &v->u.l.t; /* go if true */ + exitlist = &v->u.l.f; /* exit if false */ + } + discharge1(fs, v); + prevpos = fs->pc-1; + previous = &fs->f->code[prevpos]; + LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here"); + if (!ISJUMP(GET_OPCODE(*previous))) + prevpos = luaK_code1(fs, jump, NO_JUMP); + else { /* last instruction is already a jump */ + if (invert) + SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); + } + luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ + luaK_patchlist(fs, *golist, luaK_getlabel(fs)); + *golist = NO_JUMP; +} + + +void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { + luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); +} + + +static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { + luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT); +} + + +static int code_label (FuncState *fs, OpCode op, int arg) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_code1(fs, op, arg); +} + + +void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { + FuncState *fs = ls->fs; + if (!discharge(fs, v)) { /* `v' is an expression? */ + OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); + if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { + /* expression has no jumps */ + if (onlyone) + luaK_setcallreturns(fs, 1); /* call must return 1 value */ + } + else { /* expression has jumps */ + int final; /* position after whole expression */ + int j = NO_JUMP; /* eventual jump over values */ + int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ + int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ + if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) + || need_value(fs, v->u.l.t, OP_JMPONT)) { + /* expression needs values */ + if (ISJUMP(previous)) + luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ + else { + j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ + /* correct stack for compiler and symbolic execution */ + luaK_adjuststack(fs, 1); + } + p_nil = code_label(fs, OP_PUSHNILJMP, 0); + p_1 = code_label(fs, OP_PUSHINT, 1); + luaK_patchlist(fs, j, luaK_getlabel(fs)); + } + final = luaK_getlabel(fs); + luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); + luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); + v->u.l.f = v->u.l.t = NO_JUMP; + } + } +} + + +void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { + FuncState *fs = ls->fs; + if (op == OPR_MINUS) { + luaK_tostack(ls, v, 1); + luaK_code0(fs, OP_MINUS); + } + else { /* op == NOT */ + Instruction *previous; + discharge1(fs, v); + previous = &fs->f->code[fs->pc-1]; + if (ISJUMP(GET_OPCODE(*previous))) + SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); + else + luaK_code0(fs, OP_NOT); + /* interchange true and false lists */ + { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } + } +} + + +void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { + FuncState *fs = ls->fs; + switch (op) { + case OPR_AND: + luaK_goiftrue(fs, v, 1); + break; + case OPR_OR: + luaK_goiffalse(fs, v, 1); + break; + default: + luaK_tostack(ls, v, 1); /* all other binary operators need a value */ + } +} + + + +static const struct { + OpCode opcode; /* opcode for each binary operator */ + int arg; /* default argument for the opcode */ +} codes[] = { /* ORDER OPR */ + {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, + {OP_POW, 0}, {OP_CONCAT, 2}, + {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, + {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, + {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} +}; + + +void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { + FuncState *fs = ls->fs; + switch (op) { + case OPR_AND: { + LUA_ASSERT(v1->u.l.t == NO_JUMP, "list must be closed"); + discharge1(fs, v2); + v1->u.l.t = v2->u.l.t; + luaK_concat(fs, &v1->u.l.f, v2->u.l.f); + break; + } + case OPR_OR: { + LUA_ASSERT(v1->u.l.f == NO_JUMP, "list must be closed"); + discharge1(fs, v2); + v1->u.l.f = v2->u.l.f; + luaK_concat(fs, &v1->u.l.t, v2->u.l.t); + break; + } + default: { + luaK_tostack(ls, v2, 1); /* `v2' must be a value */ + luaK_code1(fs, codes[op].opcode, codes[op].arg); + } + } +} + + +static void codelineinfo (FuncState *fs) { + Proto *f = fs->f; + LexState *ls = fs->ls; + if (ls->lastline > fs->lastline) { + luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int, + "line info overflow", MAX_INT); + if (ls->lastline > fs->lastline+1) + f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); + f->lineinfo[f->nlineinfo++] = fs->pc; + fs->lastline = ls->lastline; + } +} + + +int luaK_code0 (FuncState *fs, OpCode o) { + return luaK_code2(fs, o, 0, 0); +} + + +int luaK_code1 (FuncState *fs, OpCode o, int arg1) { + return luaK_code2(fs, o, arg1, 0); +} + + +int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { + Instruction i = previous_instruction(fs); + int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop; + int optm = 0; /* 1 when there is an optimization */ + switch (o) { + case OP_CLOSURE: { + delta = -arg2+1; + break; + } + case OP_SETTABLE: { + delta = -arg2; + break; + } + case OP_SETLIST: { + if (arg2 == 0) return NO_JUMP; /* nothing to do */ + delta = -arg2; + break; + } + case OP_SETMAP: { + if (arg1 == 0) return NO_JUMP; /* nothing to do */ + delta = -2*arg1; + break; + } + case OP_RETURN: { + if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { + SET_OPCODE(i, OP_TAILCALL); + SETARG_B(i, arg1); + optm = 1; + } + break; + } + case OP_PUSHNIL: { + if (arg1 == 0) return NO_JUMP; /* nothing to do */ + delta = arg1; + switch(GET_OPCODE(i)) { + case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; + default: break; + } + break; + } + case OP_POP: { + if (arg1 == 0) return NO_JUMP; /* nothing to do */ + delta = -arg1; + switch(GET_OPCODE(i)) { + case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; + default: break; + } + break; + } + case OP_GETTABLE: { + switch(GET_OPCODE(i)) { + case OP_PUSHSTRING: /* `t.x' */ + SET_OPCODE(i, OP_GETDOTTED); + optm = 1; + break; + case OP_GETLOCAL: /* `t[i]' */ + SET_OPCODE(i, OP_GETINDEXED); + optm = 1; + break; + default: break; + } + break; + } + case OP_ADD: { + switch(GET_OPCODE(i)) { + case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ + default: break; + } + break; + } + case OP_SUB: { + switch(GET_OPCODE(i)) { + case OP_PUSHINT: /* `a-k' */ + i = CREATE_S(OP_ADDI, -GETARG_S(i)); + optm = 1; + break; + default: break; + } + break; + } + case OP_CONCAT: { + delta = -arg1+1; + switch(GET_OPCODE(i)) { + case OP_CONCAT: /* `a..b..c' */ + SETARG_U(i, GETARG_U(i)+1); + optm = 1; + break; + default: break; + } + break; + } + case OP_MINUS: { + switch(GET_OPCODE(i)) { + case OP_PUSHINT: /* `-k' */ + SETARG_S(i, -GETARG_S(i)); + optm = 1; + break; + case OP_PUSHNUM: /* `-k' */ + SET_OPCODE(i, OP_PUSHNEGNUM); + optm = 1; + break; + default: break; + } + break; + } + case OP_JMPNE: { + if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ + i = CREATE_S(OP_JMPT, NO_JUMP); + optm = 1; + } + break; + } + case OP_JMPEQ: { + if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ + i = CREATE_0(OP_NOT); + delta = -1; /* just undo effect of previous PUSHNIL */ + optm = 1; + } + break; + } + case OP_JMPT: + case OP_JMPONT: { + switch (GET_OPCODE(i)) { + case OP_NOT: { + i = CREATE_S(OP_JMPF, NO_JUMP); + optm = 1; + break; + } + case OP_PUSHINT: { + if (o == OP_JMPT) { /* JMPONT must keep original integer value */ + i = CREATE_S(OP_JMP, NO_JUMP); + optm = 1; + } + break; + } + case OP_PUSHNIL: { + if (GETARG_U(i) == 1) { + fs->pc--; /* erase previous instruction */ + luaK_deltastack(fs, -1); /* correct stack */ + return NO_JUMP; + } + break; + } + default: break; + } + break; + } + case OP_JMPF: + case OP_JMPONF: { + switch (GET_OPCODE(i)) { + case OP_NOT: { + i = CREATE_S(OP_JMPT, NO_JUMP); + optm = 1; + break; + } + case OP_PUSHINT: { /* `while 1 do ...' */ + fs->pc--; /* erase previous instruction */ + luaK_deltastack(fs, -1); /* correct stack */ + return NO_JUMP; + } + case OP_PUSHNIL: { /* `repeat ... until nil' */ + if (GETARG_U(i) == 1) { + i = CREATE_S(OP_JMP, NO_JUMP); + optm = 1; + } + break; + } + default: break; + } + break; + } + case OP_GETDOTTED: + case OP_GETINDEXED: + case OP_TAILCALL: + case OP_ADDI: { + LUA_INTERNALERROR("instruction used only for optimizations"); + break; + } + default: { + LUA_ASSERT(delta != VD, "invalid delta"); + break; + } + } + luaK_deltastack(fs, delta); + if (optm) { /* optimize: put instruction in place of last one */ + fs->f->code[fs->pc-1] = i; /* change previous instruction */ + return fs->pc-1; /* do not generate new instruction */ + } + /* else build new instruction */ + switch ((enum Mode)luaK_opproperties[o].mode) { + case iO: i = CREATE_0(o); break; + case iU: i = CREATE_U(o, arg1); break; + case iS: i = CREATE_S(o, arg1); break; + case iAB: i = CREATE_AB(o, arg1, arg2); break; + } + codelineinfo(fs); + /* put new instruction in code array */ + luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, + "code size overflow", MAX_INT); + fs->f->code[fs->pc] = i; + return fs->pc++; +} + + +const struct OpProperties luaK_opproperties[NUM_OPCODES] = { + {iO, 0, 0}, /* OP_END */ + {iU, 0, 0}, /* OP_RETURN */ + {iAB, 0, 0}, /* OP_CALL */ + {iAB, 0, 0}, /* OP_TAILCALL */ + {iU, VD, 0}, /* OP_PUSHNIL */ + {iU, VD, 0}, /* OP_POP */ + {iS, 1, 0}, /* OP_PUSHINT */ + {iU, 1, 0}, /* OP_PUSHSTRING */ + {iU, 1, 0}, /* OP_PUSHNUM */ + {iU, 1, 0}, /* OP_PUSHNEGNUM */ + {iU, 1, 0}, /* OP_PUSHUPVALUE */ + {iU, 1, 0}, /* OP_GETLOCAL */ + {iU, 1, 0}, /* OP_GETGLOBAL */ + {iO, 1, 2}, /* OP_GETTABLE */ + {iU, 1, 1}, /* OP_GETDOTTED */ + {iU, 1, 1}, /* OP_GETINDEXED */ + {iU, 2, 1}, /* OP_PUSHSELF */ + {iU, 1, 0}, /* OP_CREATETABLE */ + {iU, 0, 1}, /* OP_SETLOCAL */ + {iU, 0, 1}, /* OP_SETGLOBAL */ + {iAB, VD, 0}, /* OP_SETTABLE */ + {iAB, VD, 0}, /* OP_SETLIST */ + {iU, VD, 0}, /* OP_SETMAP */ + {iO, 1, 2}, /* OP_ADD */ + {iS, 1, 1}, /* OP_ADDI */ + {iO, 1, 2}, /* OP_SUB */ + {iO, 1, 2}, /* OP_MULT */ + {iO, 1, 2}, /* OP_DIV */ + {iO, 1, 2}, /* OP_POW */ + {iU, VD, 0}, /* OP_CONCAT */ + {iO, 1, 1}, /* OP_MINUS */ + {iO, 1, 1}, /* OP_NOT */ + {iS, 0, 2}, /* OP_JMPNE */ + {iS, 0, 2}, /* OP_JMPEQ */ + {iS, 0, 2}, /* OP_JMPLT */ + {iS, 0, 2}, /* OP_JMPLE */ + {iS, 0, 2}, /* OP_JMPGT */ + {iS, 0, 2}, /* OP_JMPGE */ + {iS, 0, 1}, /* OP_JMPT */ + {iS, 0, 1}, /* OP_JMPF */ + {iS, 0, 1}, /* OP_JMPONT */ + {iS, 0, 1}, /* OP_JMPONF */ + {iS, 0, 0}, /* OP_JMP */ + {iO, 0, 0}, /* OP_PUSHNILJMP */ + {iS, 0, 0}, /* OP_FORPREP */ + {iS, 0, 3}, /* OP_FORLOOP */ + {iS, 2, 0}, /* OP_LFORPREP */ + {iS, 0, 3}, /* OP_LFORLOOP */ + {iAB, VD, 0} /* OP_CLOSURE */ +}; + diff --git a/liblua/lcode.h b/liblua/lcode.h new file mode 100644 index 0000000..3f0a209 --- /dev/null +++ b/liblua/lcode.h @@ -0,0 +1,70 @@ +/* +** $Id: lcode.h,v 1.16 2000/08/09 14:49:13 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; + + +enum Mode {iO, iU, iS, iAB}; /* instruction format */ + +#define VD 100 /* flag for variable delta */ + +extern const struct OpProperties { + char mode; + unsigned char push; + unsigned char pop; +} luaK_opproperties[]; + + +void luaK_error (LexState *ls, const char *msg); +int luaK_code0 (FuncState *fs, OpCode o); +int luaK_code1 (FuncState *fs, OpCode o, int arg1); +int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); +int luaK_jump (FuncState *fs); +void luaK_patchlist (FuncState *fs, int list, int target); +void luaK_concat (FuncState *fs, int *l1, int l2); +void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); +int luaK_getlabel (FuncState *fs); +void luaK_deltastack (FuncState *fs, int delta); +void luaK_kstr (LexState *ls, int c); +void luaK_number (FuncState *fs, Number f); +void luaK_adjuststack (FuncState *fs, int n); +int luaK_lastisopen (FuncState *fs); +void luaK_setcallreturns (FuncState *fs, int nresults); +void luaK_tostack (LexState *ls, expdesc *v, int onlyone); +void luaK_storevar (LexState *ls, const expdesc *var); +void luaK_prefix (LexState *ls, UnOpr op, expdesc *v); +void luaK_infix (LexState *ls, BinOpr op, expdesc *v); +void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2); + + +#endif diff --git a/liblua/ldblib.cpp b/liblua/ldblib.cpp new file mode 100644 index 0000000..3061af9 --- /dev/null +++ b/liblua/ldblib.cpp @@ -0,0 +1,188 @@ +/* +** $Id: ldblib.c,v 1.29 2000/11/06 17:58:38 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "luadebug.h" +#include "lualib.h" + + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, i); + lua_pushstring(L, v); + lua_settable(L, -3); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushstring(L, i); + lua_pushnumber(L, v); + lua_settable(L, -3); +} + + +static int getinfo (lua_State *L) { + lua_Debug ar; + const char *options = luaL_opt_string(L, 2, "flnSu"); + char buff[20]; + if (lua_isnumber(L, 1)) { + if (!lua_getstack(L, (int)Re(lua_tonumber(L, 1)), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, 1)) { + lua_pushvalue(L, 1); + sprintf(buff, ">%.10s", options); + options = buff; + } + else + luaL_argerror(L, 1, "function or level expected"); + if (!lua_getinfo(L, options, &ar)) + luaL_argerror(L, 2, "invalid option"); + lua_newtable(L); + for (; *options; options++) { + switch (*options) { + case 'S': + settabss(L, "source", ar.source); + if (ar.source) + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabss(L, "what", ar.what); + break; + case 'l': + settabsi(L, "currentline", ar.currentline); + break; + case 'u': + settabsi(L, "nups", ar.nups); + break; + case 'n': + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + break; + case 'f': + lua_pushstring(L, "func"); + lua_pushvalue(L, -3); + lua_settable(L, -3); + break; + } + } + return 1; /* return table */ +} + + +static int getlocal (lua_State *L) { + lua_Debug ar; + const char *name; + if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ + luaL_argerror(L, 1, "level out of range"); + name = lua_getlocal(L, &ar, luaL_check_int(L, 2)); + if (name) { + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int setlocal (lua_State *L) { + lua_Debug ar; + if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ + luaL_argerror(L, 1, "level out of range"); + luaL_checkany(L, 3); + lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2))); + return 1; +} + + + +/* dummy variables (to define unique addresses) */ +static char key1, key2; +#define KEY_CALLHOOK (&key1) +#define KEY_LINEHOOK (&key2) + + +static void hookf (lua_State *L, void *key) { + lua_getregistry(L); + lua_pushuserdata(L, key); + lua_gettable(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushvalue(L, 1); + lua_rawcall(L, 1, 0); + } + else + lua_pop(L, 1); /* pop result from gettable */ + lua_pop(L, 1); /* pop table */ +} + + +static void callf (lua_State *L, lua_Debug *ar) { + lua_pushstring(L, ar->event); + hookf(L, KEY_CALLHOOK); +} + + +static void linef (lua_State *L, lua_Debug *ar) { + lua_pushnumber(L, ar->currentline); + hookf(L, KEY_LINEHOOK); +} + + +static void sethook (lua_State *L, void *key, lua_Hook hook, + lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) { + lua_settop(L, 1); + if (lua_isnil(L, 1)) + (*sethookf)(L, NULL); + else if (lua_isfunction(L, 1)) + (*sethookf)(L, hook); + else + luaL_argerror(L, 1, "function expected"); + lua_getregistry(L); + lua_pushuserdata(L, key); + lua_pushvalue(L, -1); /* dup key */ + lua_gettable(L, -3); /* get old value */ + lua_pushvalue(L, -2); /* key (again) */ + lua_pushvalue(L, 1); + lua_settable(L, -5); /* set new value */ +} + + +static int setcallhook (lua_State *L) { + sethook(L, KEY_CALLHOOK, callf, lua_setcallhook); + return 1; +} + + +static int setlinehook (lua_State *L) { + sethook(L, KEY_LINEHOOK, linef, lua_setlinehook); + return 1; +} + + +static const struct luaL_reg dblib[] = { + {"getlocal", getlocal}, + {"getinfo", getinfo}, + {"setcallhook", setcallhook}, + {"setlinehook", setlinehook}, + {"setlocal", setlocal} +}; + + +LUALIB_API void lua_dblibopen (lua_State *L) { + luaL_openl(L, dblib); +} + diff --git a/liblua/ldebug.cpp b/liblua/ldebug.cpp new file mode 100644 index 0000000..a5a2ab1 --- /dev/null +++ b/liblua/ldebug.cpp @@ -0,0 +1,466 @@ +/* +** $Id: ldebug.c,v 1.50 2000/10/30 12:38:50 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "luadebug.h" + + + +static const char *getfuncname (lua_State *L, StkId f, const char **name); + + +static void setnormalized (TObject *d, const TObject *s) { + if (ttype(s) == LUA_TMARK) { + clvalue(d) = infovalue(s)->func; + ttype(d) = LUA_TFUNCTION; + } + else *d = *s; +} + + +static int isLmark (StkId o) { + return (o && ttype(o) == LUA_TMARK && !infovalue(o)->func->isC); +} + + +LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { + lua_Hook oldhook = L->callhook; + L->callhook = func; + return oldhook; +} + + +LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { + lua_Hook oldhook = L->linehook; + L->linehook = func; + return oldhook; +} + + +static StkId aux_stackedfunction (lua_State *L, int level, StkId top) { + int i; + for (i = (top-1) - L->stack; i>=0; i--) { + if (is_T_MARK(L->stack[i].ttype)) { + if (level == 0) + return L->stack+i; + level--; + } + } + return NULL; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + StkId f = aux_stackedfunction(L, level, L->top); + if (f == NULL) return 0; /* there is no such level */ + else { + ar->_func = f; + return 1; + } +} + + +static int nups (StkId f) { + switch (ttype(f)) { + case LUA_TFUNCTION: + return clvalue(f)->nupvalues; + case LUA_TMARK: + return infovalue(f)->func->nupvalues; + default: + return 0; + } +} + + +int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { + int refi; + if (lineinfo == NULL || pc == -1) + return -1; /* no line info or function is not active */ + refi = prefi ? *prefi : 0; + if (lineinfo[refi] < 0) + refline += -lineinfo[refi++]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + while (lineinfo[refi] > pc) { + refline--; + refi--; + if (lineinfo[refi] < 0) + refline -= -lineinfo[refi--]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + } + for (;;) { + int nextline = refline + 1; + int nextref = refi + 1; + if (lineinfo[nextref] < 0) + nextline += -lineinfo[nextref++]; + LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); + if (lineinfo[nextref] > pc) + break; + refline = nextline; + refi = nextref; + } + if (prefi) *prefi = refi; + return refline; +} + + +static int currentpc (StkId f) { + CallInfo *ci = infovalue(f); + LUA_ASSERT(isLmark(f), "function has no pc"); + if (ci->pc) + return (*ci->pc - ci->func->f.l->code) - 1; + else + return -1; /* function is not active */ +} + + +static int currentline (StkId f) { + if (!isLmark(f)) + return -1; /* only active lua functions have current-line information */ + else { + CallInfo *ci = infovalue(f); + int *lineinfo = ci->func->f.l->lineinfo; + return luaG_getline(lineinfo, currentpc(f), 1, NULL); + } +} + + + +static Proto *getluaproto (StkId f) { + return (isLmark(f) ? infovalue(f)->func->f.l : NULL); +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + StkId f = ar->_func; + Proto *fp = getluaproto(f); + if (!fp) return NULL; /* `f' is not a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(f)); + if (!name) return NULL; + luaA_pushobject(L, (f+1)+(n-1)); /* push value */ + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + StkId f = ar->_func; + Proto *fp = getluaproto(f); + L->top--; /* pop new value */ + if (!fp) return NULL; /* `f' is not a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(f)); + if (!name || name[0] == '(') return NULL; /* `(' starts private locals */ + *((f+1)+(n-1)) = *L->top; + return name; +} + + +static void infoLproto (lua_Debug *ar, Proto *f) { + ar->source = f->source->str; + ar->linedefined = f->lineDefined; + ar->what = "Lua"; +} + + +static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { + Closure *cl = NULL; + switch (ttype(func)) { + case LUA_TFUNCTION: + cl = clvalue(func); + break; + case LUA_TMARK: + cl = infovalue(func)->func; + break; + default: + lua_error(L, "value for `lua_getinfo' is not a function"); + } + if (cl->isC) { + ar->source = "=C"; + ar->linedefined = -1; + ar->what = "C"; + } + else + infoLproto(ar, cl->f.l); + luaO_chunkid(ar->short_src, ar->source, sizeof(ar->short_src)); + if (ar->linedefined == 0) + ar->what = "main"; +} + + +static const char *travtagmethods (lua_State *L, const TObject *o) { + if (ttype(o) == LUA_TFUNCTION) { + int e; + for (e=0; elast_tag; t++) + if (clvalue(o) == luaT_gettm(L, t, e)) + return luaT_eventname[e]; + } + } + return NULL; +} + + +static const char *travglobals (lua_State *L, const TObject *o) { + Hash *g = L->gt; + int i; + for (i=0; isize; i++) { + if (luaO_equalObj(o, val(node(g, i))) && + ttype(key(node(g, i))) == LUA_TSTRING) + return tsvalue(key(node(g, i)))->str; + } + return NULL; +} + + +static void getname (lua_State *L, StkId f, lua_Debug *ar) { + TObject o; + setnormalized(&o, f); + /* try to find a name for given function */ + if ((ar->name = travglobals(L, &o)) != NULL) + ar->namewhat = "global"; + /* not found: try tag methods */ + else if ((ar->name = travtagmethods(L, &o)) != NULL) + ar->namewhat = "tag-method"; + else ar->namewhat = ""; /* not found at all */ +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + StkId func; + int isactive = (*what != '>'); + if (isactive) + func = ar->_func; + else { + what++; /* skip the '>' */ + func = L->top - 1; + } + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(L, ar, func); + break; + } + case 'l': { + ar->currentline = currentline(func); + break; + } + case 'u': { + ar->nups = nups(func); + break; + } + case 'n': { + ar->namewhat = (isactive) ? getfuncname(L, func, &ar->name) : NULL; + if (ar->namewhat == NULL) + getname(L, func, ar); + break; + } + case 'f': { + setnormalized(L->top, func); + incr_top; /* push function */ + break; + } + default: return 0; /* invalid option */ + } + } + if (!isactive) L->top--; /* pop function */ + return 1; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + + +static int pushpc (int *stack, int pc, int top, int n) { + while (n--) + stack[top++] = pc-1; + return top; +} + + +static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { + int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ + const Instruction *code = pt->code; + int top = pt->numparams; + int pc = 0; + if (pt->is_vararg) /* varargs? */ + top++; /* `arg' */ + while (pc < lastpc) { + const Instruction i = code[pc++]; + LUA_ASSERT(0 <= top && top <= pt->maxstacksize, "wrong stack"); + switch (GET_OPCODE(i)) { + case OP_RETURN: { + LUA_ASSERT(top >= GETARG_U(i), "wrong stack"); + top = GETARG_U(i); + break; + } + case OP_TAILCALL: { + LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); + top = GETARG_B(i); + break; + } + case OP_CALL: { + int nresults = GETARG_B(i); + if (nresults == MULT_RET) nresults = 1; + LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); + top = pushpc(stack, pc, GETARG_A(i), nresults); + break; + } + case OP_PUSHNIL: { + top = pushpc(stack, pc, top, GETARG_U(i)); + break; + } + case OP_POP: { + top -= GETARG_U(i); + break; + } + case OP_SETTABLE: + case OP_SETLIST: { + top -= GETARG_B(i); + break; + } + case OP_SETMAP: { + top -= 2*GETARG_U(i); + break; + } + case OP_CONCAT: { + top -= GETARG_U(i); + stack[top++] = pc-1; + break; + } + case OP_CLOSURE: { + top -= GETARG_B(i); + stack[top++] = pc-1; + break; + } + case OP_JMPONT: + case OP_JMPONF: { + int newpc = pc + GETARG_S(i); + /* jump is forward and do not skip `lastpc'? */ + if (pc < newpc && newpc <= lastpc) { + stack[top-1] = pc-1; /* value comes from `and'/`or' */ + pc = newpc; /* do the jump */ + } + else + top--; /* do not jump; pop value */ + break; + } + default: { + OpCode op = GET_OPCODE(i); + LUA_ASSERT(luaK_opproperties[op].push != VD, + "invalid opcode for default"); + top -= luaK_opproperties[op].pop; + LUA_ASSERT(top >= 0, "wrong stack"); + top = pushpc(stack, pc, top, luaK_opproperties[op].push); + } + } + } + return code[stack[stackpos]]; +} + + +static const char *getobjname (lua_State *L, StkId obj, const char **name) { + StkId func = aux_stackedfunction(L, 0, obj); + if (!isLmark(func)) + return NULL; /* not an active Lua function */ + else { + Proto *p = infovalue(func)->func->f.l; + int pc = currentpc(func); + int stackpos = obj - (func+1); /* func+1 == function base */ + Instruction i = luaG_symbexec(p, pc, stackpos); + LUA_ASSERT(pc != -1, "function must be active"); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + *name = p->kstr[GETARG_U(i)]->str; + return "global"; + } + case OP_GETLOCAL: { + *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); + LUA_ASSERT(*name, "local must exist"); + return "local"; + } + case OP_PUSHSELF: + case OP_GETDOTTED: { + *name = p->kstr[GETARG_U(i)]->str; + return "field"; + } + default: + return NULL; /* no useful name found */ + } + } +} + + +static const char *getfuncname (lua_State *L, StkId f, const char **name) { + StkId func = aux_stackedfunction(L, 0, f); /* calling function */ + if (!isLmark(func)) + return NULL; /* not an active Lua function */ + else { + Proto *p = infovalue(func)->func->f.l; + int pc = currentpc(func); + Instruction i; + if (pc == -1) return NULL; /* function is not activated */ + i = p->code[pc]; + switch (GET_OPCODE(i)) { + case OP_CALL: case OP_TAILCALL: + return getobjname(L, (func+1)+GETARG_A(i), name); + default: + return NULL; /* no useful name found */ + } + } +} + + +/* }====================================================== */ + + +void luaG_typeerror (lua_State *L, StkId o, const char *op) { + const char *name; + const char *kind = getobjname(L, o, &name); + const char *t = luaO_typename(o); + if (kind) + luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", + op, kind, name, t); + else + luaO_verror(L, "attempt to %.30s a %.10s value", op, t); +} + + +void luaG_binerror (lua_State *L, StkId p1, int t, const char *op) { + if (ttype(p1) == t) p1++; + LUA_ASSERT(ttype(p1) != t, "must be an error"); + luaG_typeerror(L, p1, op); +} + + +void luaG_ordererror (lua_State *L, StkId top) { + const char *t1 = luaO_typename(top-2); + const char *t2 = luaO_typename(top-1); + if (t1[2] == t2[2]) + luaO_verror(L, "attempt to compare two %.10s values", t1); + else + luaO_verror(L, "attempt to compare %.10s with %.10s", t1, t2); +} + diff --git a/liblua/ldebug.h b/liblua/ldebug.h new file mode 100644 index 0000000..d4b2d3b --- /dev/null +++ b/liblua/ldebug.h @@ -0,0 +1,21 @@ +/* +** $Id: ldebug.h,v 1.7 2000/10/05 12:14:08 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" +#include "luadebug.h" + + +void luaG_typeerror (lua_State *L, StkId o, const char *op); +void luaG_binerror (lua_State *L, StkId p1, int t, const char *op); +int luaG_getline (int *lineinfo, int pc, int refline, int *refi); +void luaG_ordererror (lua_State *L, StkId top); + + +#endif diff --git a/liblua/ldo.cpp b/liblua/ldo.cpp new file mode 100644 index 0000000..fbb892a --- /dev/null +++ b/liblua/ldo.cpp @@ -0,0 +1,385 @@ +/* +** $Id: ldo.c,v 1.109 2000/10/30 12:38:50 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + +/* space to handle stack overflow errors */ +#define EXTRA_STACK (2*LUA_MINSTACK) + + +void luaD_init (lua_State *L, int stacksize) { + L->stack = luaM_newvector(L, stacksize+EXTRA_STACK, TObject); + L->nblocks += stacksize*sizeof(TObject); + L->stack_last = L->stack+(stacksize-1); + L->stacksize = stacksize; + L->Cbase = L->top = L->stack; +} + + +void luaD_checkstack (lua_State *L, int n) { + if (L->stack_last - L->top <= n) { /* stack overflow? */ + if (L->stack_last-L->stack > (L->stacksize-1)) { + /* overflow while handling overflow */ + luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ + } + else { + L->stack_last += EXTRA_STACK; /* to be used by error message */ + lua_error(L, "stack overflow"); + } + } +} + + +static void restore_stack_limit (lua_State *L) { + if (L->top - L->stack < L->stacksize - 1) + L->stack_last = L->stack + (L->stacksize-1); +} + + +/* +** Adjust stack. Set top to base+extra, pushing NILs if needed. +** (we cannot add base+extra unless we are sure it fits in the stack; +** otherwise the result of such operation on pointers is undefined) +*/ +void luaD_adjusttop (lua_State *L, StkId base, int extra) { + int diff = extra-(L->top-base); + if (diff <= 0) + L->top = base+extra; + else { + luaD_checkstack(L, diff); + while (diff--) + ttype(L->top++) = LUA_TNIL; + } +} + + +/* +** Open a hole inside the stack at `pos' +*/ +static void luaD_openstack (lua_State *L, StkId pos) { + int i = L->top-pos; + while (i--) pos[i+1] = pos[i]; + incr_top; +} + + +static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { + StkId old_Cbase = L->Cbase; + StkId old_top = L->Cbase = L->top; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->allowhooks = 0; /* cannot call hooks inside a hook */ + (*hook)(L, ar); + LUA_ASSERT(L->allowhooks == 0, "invalid allow"); + L->allowhooks = 1; + L->top = old_top; + L->Cbase = old_Cbase; +} + + +void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook) { + if (L->allowhooks) { + lua_Debug ar; + ar._func = func; + ar.event = "line"; + ar.currentline = line; + dohook(L, &ar, linehook); + } +} + + +static void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, + const char *event) { + if (L->allowhooks) { + lua_Debug ar; + ar._func = func; + ar.event = event; + infovalue(func)->pc = NULL; /* function is not active */ + dohook(L, &ar, callhook); + } +} + + +static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) { + int nup = cl->nupvalues; /* number of upvalues */ + StkId old_Cbase = L->Cbase; + int n; + L->Cbase = base; /* new base for C function */ + luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ + for (n=0; ntop++) = cl->upvalue[n]; + n = (*cl->f.c)(L); /* do the actual call */ + L->Cbase = old_Cbase; /* restore old C base */ + return L->top - n; /* return index of first result */ +} + + +void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults) { + StkId base = L->top - nParams; + luaD_openstack(L, base); + clvalue(base) = f; + ttype(base) = LUA_TFUNCTION; + luaD_call(L, base, nResults); +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, the results are on the stack, starting at the original +** function position. +** The number of results is nResults, unless nResults=LUA_MULTRET. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + lua_Hook callhook; + StkId firstResult; + CallInfo ci; + Closure *cl; + if (ttype(func) != LUA_TFUNCTION) { + /* `func' is not a function; check the `function' tag method */ + Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION); + if (tm == NULL) + luaG_typeerror(L, func, "call"); + luaD_openstack(L, func); + clvalue(func) = tm; /* tag method is the new function to be called */ + ttype(func) = LUA_TFUNCTION; + } + cl = clvalue(func); + ci.func = cl; + infovalue(func) = &ci; + ttype(func) = LUA_TMARK; + callhook = L->callhook; + if (callhook) + luaD_callHook(L, func, callhook, "call"); + firstResult = (cl->isC ? callCclosure(L, cl, func+1) : + luaV_execute(L, cl, func+1)); + if (callhook) /* same hook that was active at entry */ + luaD_callHook(L, func, callhook, "return"); + LUA_ASSERT(ttype(func) == LUA_TMARK, "invalid tag"); + /* move results to `func' (to erase parameters and function) */ + if (nResults == LUA_MULTRET) { + while (firstResult < L->top) /* copy all results */ + *func++ = *firstResult++; + L->top = func; + } + else { /* copy at most `nResults' */ + for (; nResults > 0 && firstResult < L->top; nResults--) + *func++ = *firstResult++; + L->top = func; + for (; nResults > 0; nResults--) { /* if there are not enough results */ + ttype(L->top) = LUA_TNIL; /* adjust the stack */ + incr_top; /* must check stack space */ + } + } + luaC_checkGC(L); +} + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = (struct CallS *)ud; + luaD_call(L, c->func, c->nresults); +} + + +LUA_API int lua_call (lua_State *L, int nargs, int nresults) { + StkId func = L->top - (nargs+1); /* function to be called */ + struct CallS c; + int status; + c.func = func; c.nresults = nresults; + status = luaD_runprotected(L, f_call, &c); + if (status != 0) /* an error occurred? */ + L->top = func; /* remove parameters from the stack */ + return status; +} + + +/* +** Execute a protected parser. +*/ +struct ParserS { /* data to `f_parser' */ + ZIO *z; + int bin; +}; + +static void f_parser (lua_State *L, void *ud) { + struct ParserS *p = (struct ParserS *)ud; + Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); + luaV_Lclosure(L, tf, 0); +} + + +static int protectedparser (lua_State *L, ZIO *z, int bin) { + struct ParserS p; + unsigned long old_blocks; + int status; + p.z = z; p.bin = bin; + luaC_checkGC(L); + old_blocks = L->nblocks; + status = luaD_runprotected(L, f_parser, &p); + if (status == 0) { + /* add new memory to threshold (as it probably will stay) */ + L->GCthreshold += (L->nblocks - old_blocks); + } + else if (status == LUA_ERRRUN) /* an error occurred: correct error code */ + status = LUA_ERRSYNTAX; + return status; +} + + +static int parse_file (lua_State *L, const char *filename) { + ZIO z; + int status; + int bin; /* flag for file mode */ + int c; /* look ahead char */ + FILE *f = (filename == NULL) ? stdin : fopen(filename, "r"); + if (f == NULL) return LUA_ERRFILE; /* unable to open file */ + c = fgetc(f); + ungetc(c, f); + bin = (c == ID_CHUNK); + if (bin && f != stdin) { + f = freopen(filename, "rb", f); /* set binary mode */ + if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ + } + lua_pushstring(L, "@"); + lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename); + lua_concat(L, 2); + filename = lua_tostring(L, -1); /* filename = '@'..filename */ + lua_pop(L, 1); /* OK: there is no GC during parser */ + luaZ_Fopen(&z, f, filename); + status = protectedparser(L, &z, bin); + if (f != stdin) + fclose(f); + return status; +} + + +LUA_API int lua_dofile (lua_State *L, const char *filename) { + int status = parse_file(L, filename); + if (status == 0) /* parse OK? */ + status = lua_call(L, 0, LUA_MULTRET); /* call main */ + return status; +} + + +static int parse_buffer (lua_State *L, const char *buff, size_t size, + const char *name) { + ZIO z; + if (!name) name = "?"; + luaZ_mopen(&z, buff, size, name); + return protectedparser(L, &z, buff[0]==ID_CHUNK); +} + + +LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) { + int status = parse_buffer(L, buff, size, name); + if (status == 0) /* parse OK? */ + status = lua_call(L, 0, LUA_MULTRET); /* call main */ + return status; +} + + +LUA_API int lua_dostring (lua_State *L, const char *str) { + return lua_dobuffer(L, str, strlen(str), str); +} + + +/* +** {====================================================== +** Error-recover functions (based on long jumps) +** ======================================================= +*/ + +/* chain list of long jump buffers */ +struct lua_longjmp { + jmp_buf b; + struct lua_longjmp *previous; + volatile int status; /* error code */ +}; + + +static void message (lua_State *L, const char *s) { + const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); + if (ttype(em) == LUA_TFUNCTION) { + *L->top = *em; + incr_top; + lua_pushstring(L, s); + luaD_call(L, L->top-2, 0); + } +} + + +/* +** Reports an error, and jumps up to the available recovery label +*/ +LUA_API void lua_error (lua_State *L, const char *s) { + if (s) message(L, s); + luaD_breakrun(L, LUA_ERRRUN); +} + + +void luaD_breakrun (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + longjmp(L->errorJmp->b, 1); + } + else { + if (errcode != LUA_ERRMEM) + message(L, "unable to recover; exiting\n"); + exit(EXIT_FAILURE); + } +} + + +int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { + StkId oldCbase = L->Cbase; + StkId oldtop = L->top; + struct lua_longjmp lj; + int allowhooks = L->allowhooks; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + if (setjmp(lj.b) == 0) + (*f)(L, ud); + else { /* an error occurred: restore the state */ + L->allowhooks = allowhooks; + L->Cbase = oldCbase; + L->top = oldtop; + restore_stack_limit(L); + } + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + diff --git a/liblua/ldo.h b/liblua/ldo.h new file mode 100644 index 0000000..3fba1f5 --- /dev/null +++ b/liblua/ldo.h @@ -0,0 +1,33 @@ +/* +** $Id: ldo.h,v 1.28 2000/10/06 12:45:25 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" + + +/* +** macro to increment stack top. +** There must be always an empty slot at the L->stack.top +*/ +#define incr_top {if (L->top == L->stack_last) luaD_checkstack(L, 1); L->top++;} + + +void luaD_init (lua_State *L, int stacksize); +void luaD_adjusttop (lua_State *L, StkId base, int extra); +void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); +void luaD_call (lua_State *L, StkId func, int nResults); +void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults); +void luaD_checkstack (lua_State *L, int n); + +void luaD_breakrun (lua_State *L, int errcode); +int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); + + +#endif diff --git a/liblua/lfunc.cpp b/liblua/lfunc.cpp new file mode 100644 index 0000000..6841ef7 --- /dev/null +++ b/liblua/lfunc.cpp @@ -0,0 +1,109 @@ +/* +** $Id: lfunc.c,v 1.34 2000/10/30 12:20:29 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "lfunc.h" +#include "lmem.h" +#include "lstate.h" + + +#define sizeclosure(n) ((int)sizeof(Closure) + (int)sizeof(TObject)*((n)-1)) + + +Closure *luaF_newclosure (lua_State *L, int nelems) { + int size = sizeclosure(nelems); + Closure *c = (Closure *)luaM_malloc(L, size); + c->next = L->rootcl; + L->rootcl = c; + c->mark = c; + c->nupvalues = nelems; + L->nblocks += size; + return c; +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + f->knum = NULL; + f->nknum = 0; + f->kstr = NULL; + f->nkstr = 0; + f->kproto = NULL; + f->nkproto = 0; + f->code = NULL; + f->ncode = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->marked = 0; + f->lineinfo = NULL; + f->nlineinfo = 0; + f->nlocvars = 0; + f->locvars = NULL; + f->lineDefined = 0; + f->source = NULL; + f->next = L->rootproto; /* chain in list of protos */ + L->rootproto = f; + return f; +} + + +static size_t protosize (Proto *f) { + return sizeof(Proto) + + f->nknum*sizeof(Number) + + f->nkstr*sizeof(TString *) + + f->nkproto*sizeof(Proto *) + + f->ncode*sizeof(Instruction) + + f->nlocvars*sizeof(struct LocVar) + + f->nlineinfo*sizeof(int); +} + + +void luaF_protook (lua_State *L, Proto *f, int pc) { + f->ncode = pc; /* signal that proto was properly created */ + L->nblocks += protosize(f); +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + if (f->ncode > 0) /* function was properly created? */ + L->nblocks -= protosize(f); + luaM_free(L, f->code); + luaM_free(L, f->locvars); + luaM_free(L, f->kstr); + luaM_free(L, f->knum); + luaM_free(L, f->kproto); + luaM_free(L, f->lineinfo); + luaM_free(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + L->nblocks -= sizeclosure(c->nupvalues); + luaM_free(L, c); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; inlocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return f->locvars[i].varname->str; + } + } + return NULL; /* not found */ +} + diff --git a/liblua/lfunc.h b/liblua/lfunc.h new file mode 100644 index 0000000..32afbc5 --- /dev/null +++ b/liblua/lfunc.h @@ -0,0 +1,24 @@ +/* +** $Id: lfunc.h,v 1.13 2000/09/29 12:42:13 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + + +Proto *luaF_newproto (lua_State *L); +void luaF_protook (lua_State *L, Proto *f, int pc); +Closure *luaF_newclosure (lua_State *L, int nelems); +void luaF_freeproto (lua_State *L, Proto *f); +void luaF_freeclosure (lua_State *L, Closure *c); + +const char *luaF_getlocalname (const Proto *func, int local_number, int pc); + + +#endif diff --git a/liblua/lgc.cpp b/liblua/lgc.cpp new file mode 100644 index 0000000..6b916a8 --- /dev/null +++ b/liblua/lgc.cpp @@ -0,0 +1,353 @@ +/* +** $Id: lgc.c,v 1.72 2000/10/26 12:47:05 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include "lua.h" + +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +typedef struct GCState { + Hash *tmark; /* list of marked tables to be visited */ + Closure *cmark; /* list of marked closures to be visited */ +} GCState; + + + +static void markobject (GCState *st, TObject *o); + + +/* mark a string; marks larger than 1 cannot be changed */ +#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} + + + +static void protomark (Proto *f) { + if (!f->marked) { + int i; + f->marked = 1; + strmark(f->source); + for (i=0; inkstr; i++) + strmark(f->kstr[i]); + for (i=0; inkproto; i++) + protomark(f->kproto[i]); + for (i=0; inlocvars; i++) /* mark local-variable names */ + strmark(f->locvars[i].varname); + } +} + + +static void markstack (lua_State *L, GCState *st) { + StkId o; + for (o=L->stack; otop; o++) + markobject(st, o); +} + + +static void marklock (lua_State *L, GCState *st) { + int i; + for (i=0; irefSize; i++) { + if (L->refArray[i].st == LOCK) + markobject(st, &L->refArray[i].o); + } +} + + +static void markclosure (GCState *st, Closure *cl) { + if (!ismarked(cl)) { + if (!cl->isC) + protomark(cl->f.l); + cl->mark = st->cmark; /* chain it for later traversal */ + st->cmark = cl; + } +} + + +static void marktagmethods (lua_State *L, GCState *st) { + int e; + for (e=0; elast_tag; t++) { + Closure *cl = luaT_gettm(L, t, e); + if (cl) markclosure(st, cl); + } + } +} + + +static void markobject (GCState *st, TObject *o) { + switch (ttype(o)) { + case LUA_TUSERDATA: case LUA_TSTRING: + strmark(tsvalue(o)); + break; + case LUA_TMARK: + markclosure(st, infovalue(o)->func); + break; + case LUA_TFUNCTION: + markclosure(st, clvalue(o)); + break; + case LUA_TTABLE: { + if (!ismarked(hvalue(o))) { + hvalue(o)->mark = st->tmark; /* chain it in list of marked */ + st->tmark = hvalue(o); + } + break; + } + default: break; /* numbers, etc */ + } +} + + +static void markall (lua_State *L) { + GCState st; + st.cmark = NULL; + st.tmark = L->gt; /* put table of globals in mark list */ + L->gt->mark = NULL; + marktagmethods(L, &st); /* mark tag methods */ + markstack(L, &st); /* mark stack objects */ + marklock(L, &st); /* mark locked objects */ + for (;;) { /* mark tables and closures */ + if (st.cmark) { + int i; + Closure *f = st.cmark; /* get first closure from list */ + st.cmark = f->mark; /* remove it from list */ + for (i=0; inupvalues; i++) /* mark its upvalues */ + markobject(&st, &f->upvalue[i]); + } + else if (st.tmark) { + int i; + Hash *h = st.tmark; /* get first table from list */ + st.tmark = h->mark; /* remove it from list */ + for (i=0; isize; i++) { + Node *n = node(h, i); + if (ttype(key(n)) != LUA_TNIL) { + if (ttype(val(n)) == LUA_TNIL) + luaH_remove(h, key(n)); /* dead element; try to remove it */ + markobject(&st, &n->key); + markobject(&st, &n->val); + } + } + } + else break; /* nothing else to mark */ + } +} + + +static int hasmark (const TObject *o) { + /* valid only for locked objects */ + switch (o->ttype) { + case LUA_TSTRING: case LUA_TUSERDATA: + return tsvalue(o)->marked; + case LUA_TTABLE: + return ismarked(hvalue(o)); + case LUA_TFUNCTION: + return ismarked(clvalue(o)); + default: /* number */ + return 1; + } +} + + +/* macro for internal debugging; check if a link of free refs is valid */ +#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n)) + +static void invalidaterefs (lua_State *L) { + int n = L->refSize; + int i; + for (i=0; irefArray[i]; + if (r->st == HOLD && !hasmark(&r->o)) + r->st = COLLECTED; + LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || + (r->st == HOLD && hasmark(&r->o)) || + r->st == COLLECTED || + r->st == NONEXT || + (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), + "inconsistent ref table"); + } + LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table"); +} + + + +static void collectproto (lua_State *L) { + Proto **p = &L->rootproto; + Proto *next; + while ((next = *p) != NULL) { + if (next->marked) { + next->marked = 0; + p = &next->next; + } + else { + *p = next->next; + luaF_freeproto(L, next); + } + } +} + + +static void collectclosure (lua_State *L) { + Closure **p = &L->rootcl; + Closure *next; + while ((next = *p) != NULL) { + if (ismarked(next)) { + next->mark = next; /* unmark */ + p = &next->next; + } + else { + *p = next->next; + luaF_freeclosure(L, next); + } + } +} + + +static void collecttable (lua_State *L) { + Hash **p = &L->roottable; + Hash *next; + while ((next = *p) != NULL) { + if (ismarked(next)) { + next->mark = next; /* unmark */ + p = &next->next; + } + else { + *p = next->next; + luaH_free(L, next); + } + } +} + + +static void checktab (lua_State *L, stringtable *tb) { + if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) + luaS_resize(L, tb, tb->size/2); /* table is too big */ +} + + +static void collectstrings (lua_State *L, int all) { + int i; + for (i=0; istrt.size; i++) { /* for each list */ + TString **p = &L->strt.hash[i]; + TString *next; + while ((next = *p) != NULL) { + if (next->marked && !all) { /* preserve? */ + if (next->marked < FIXMARK) /* does not change FIXMARKs */ + next->marked = 0; + p = &next->nexthash; + } + else { /* collect */ + *p = next->nexthash; + L->strt.nuse--; + L->nblocks -= sizestring(next->len); + luaM_free(L, next); + } + } + } + checktab(L, &L->strt); +} + + +static void collectudata (lua_State *L, int all) { + int i; + for (i=0; iudt.size; i++) { /* for each list */ + TString **p = &L->udt.hash[i]; + TString *next; + while ((next = *p) != NULL) { + LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); + if (next->marked && !all) { /* preserve? */ + next->marked = 0; + p = &next->nexthash; + } + else { /* collect */ + int tag = next->u.d.tag; + *p = next->nexthash; + next->nexthash = L->TMtable[tag].collected; /* chain udata */ + L->TMtable[tag].collected = next; + L->nblocks -= sizestring(next->len); + L->udt.nuse--; + } + } + } + checktab(L, &L->udt); +} + + +#define MINBUFFER 256 +static void checkMbuffer (lua_State *L) { + if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */ + size_t newsize = L->Mbuffsize/2; /* still larger than MINBUFFER */ + L->nblocks += (newsize - L->Mbuffsize)*sizeof(char); + L->Mbuffsize = newsize; + luaM_reallocvector(L, L->Mbuffer, newsize, char); + } +} + + +static void callgcTM (lua_State *L, const TObject *o) { + Closure *tm = luaT_gettmbyObj(L, o, TM_GC); + if (tm != NULL) { + int oldah = L->allowhooks; + L->allowhooks = 0; /* stop debug hooks during GC tag methods */ + luaD_checkstack(L, 2); + clvalue(L->top) = tm; + ttype(L->top) = LUA_TFUNCTION; + *(L->top+1) = *o; + L->top += 2; + luaD_call(L, L->top-2, 0); + L->allowhooks = oldah; /* restore hooks */ + } +} + + +static void callgcTMudata (lua_State *L) { + int tag; + TObject o; + ttype(&o) = LUA_TUSERDATA; + L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */ + for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */ + TString *udata; + while ((udata = L->TMtable[tag].collected) != NULL) { + L->TMtable[tag].collected = udata->nexthash; /* remove it from list */ + tsvalue(&o) = udata; + callgcTM(L, &o); + luaM_free(L, udata); + } + } +} + + +void luaC_collect (lua_State *L, int all) { + collectudata(L, all); + callgcTMudata(L); + collectstrings(L, all); + collecttable(L); + collectproto(L); + collectclosure(L); +} + + +static void luaC_collectgarbage (lua_State *L) { + markall(L); + invalidaterefs(L); /* check unlocked references */ + luaC_collect(L, 0); + checkMbuffer(L); + L->GCthreshold = 2*L->nblocks; /* set new threshold */ + callgcTM(L, &luaO_nilobject); +} + + +void luaC_checkGC (lua_State *L) { + if (L->nblocks >= L->GCthreshold) + luaC_collectgarbage(L); +} + diff --git a/liblua/lgc.h b/liblua/lgc.h new file mode 100644 index 0000000..87a14d1 --- /dev/null +++ b/liblua/lgc.h @@ -0,0 +1,18 @@ +/* +** $Id: lgc.h,v 1.8 2000/10/02 14:47:43 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +void luaC_collect (lua_State *L, int all); +void luaC_checkGC (lua_State *L); + + +#endif diff --git a/liblua/liolib.cpp b/liblua/liolib.cpp new file mode 100644 index 0000000..7d4e5b4 --- /dev/null +++ b/liblua/liolib.cpp @@ -0,0 +1,732 @@ +/* +** $Id: liolib.c,v 1.91 2000/10/31 13:10:24 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "luadebug.h" +#include "lualib.h" + + +#ifndef OLD_ANSI +#include +#include +#define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s)) +#define free(b) if (b) (free)(b) +#else +/* no support for locale and for strerror: fake them */ +#define setlocale(a,b) ((void)a, strcmp((b),"C")==0?"C":NULL) +#define LC_ALL 0 +#define LC_COLLATE 0 +#define LC_CTYPE 0 +#define LC_MONETARY 0 +#define LC_NUMERIC 0 +#define LC_TIME 0 +#define strerror(e) "generic I/O error" +#define errno (-1) +#endif + + + +#ifdef POPEN +/* FILE *popen(); +int pclose(); */ +#define CLOSEFILE(L, f) ((pclose(f) == -1) ? fclose(f) : 0) +#else +/* no support for popen */ +#define popen(x,y) NULL /* that is, popen always fails */ +#define CLOSEFILE(L, f) (fclose(f)) +#endif + + +#define INFILE 0 +#define OUTFILE 1 + +typedef struct IOCtrl { + int ref[2]; /* ref for strings _INPUT/_OUTPUT */ + int iotag; /* tag for file handles */ + int closedtag; /* tag for closed handles */ +} IOCtrl; + + + +static const char *const filenames[] = {"_INPUT", "_OUTPUT"}; + + +static int pushresult (lua_State *L, int i) { + if (i) { + lua_pushuserdata(L, NULL); + return 1; + } + else { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + lua_pushnumber(L, errno); + return 3;; + } +} + + +/* +** {====================================================== +** FILE Operations +** ======================================================= +*/ + + +static FILE *gethandle (lua_State *L, IOCtrl *ctrl, int f) { + void *p = lua_touserdata(L, f); + if (p != NULL) { /* is `f' a userdata ? */ + int ftag = lua_tag(L, f); + if (ftag == ctrl->iotag) /* does it have the correct tag? */ + return (FILE *)p; + else if (ftag == ctrl->closedtag) + lua_error(L, "cannot access a closed file"); + /* else go through */ + } + return NULL; +} + + +static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) { + FILE *f = gethandle(L, ctrl, arg); + luaL_arg_check(L, f, arg, "invalid file handle"); + return f; +} + + +static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) { + FILE *f; + lua_getglobals(L); + lua_getref(L, ctrl->ref[inout]); + lua_rawget(L, -2); + f = gethandle(L, ctrl, -1); + if (f == NULL) + luaL_verror(L, "global variable `%.10s' is not a file handle", + filenames[inout]); + return f; +} + + +static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f, + const char *name) { + lua_pushusertag(L, f, ctrl->iotag); + lua_setglobal(L, name); +} + + +#define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout])) + + +static int setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { + if (f == NULL) + return pushresult(L, 0); + else { + setfile(L, ctrl, f, inout); + lua_pushusertag(L, f, ctrl->iotag); + return 1; + } +} + + +static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) { + if (f == stdin || f == stdout || f == stderr) + return 1; + else { + lua_pushusertag(L, f, ctrl->iotag); + lua_settag(L, ctrl->closedtag); + return (CLOSEFILE(L, f) == 0); + } +} + + +static int io_close (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + lua_pop(L, 1); /* remove upvalue */ + return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 1))); +} + + +static int file_collect (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *f = getnonullfile(L, ctrl, 1); + if (f != stdin && f != stdout && f != stderr) + CLOSEFILE(L, f); + return 0; +} + + +static int io_open (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *f; + lua_pop(L, 1); /* remove upvalue */ + f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); + if (f) { + lua_pushusertag(L, f, ctrl->iotag); + return 1; + } + else + return pushresult(L, 0); +} + + + +static int io_fromto (lua_State *L, int inout, const char *mode) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *current; + lua_pop(L, 1); /* remove upvalue */ + if (lua_isnull(L, 1)) { + closefile(L, ctrl, getfilebyref(L, ctrl, inout)); + current = (inout == 0) ? stdin : stdout; + } + else if (lua_tag(L, 1) == ctrl->iotag) /* deprecated option */ + current = (FILE *)lua_touserdata(L, 1); + else { + const char *s = luaL_check_string(L, 1); + current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode); + } + return setreturn(L, ctrl, current, inout); +} + + +static int io_readfrom (lua_State *L) { + return io_fromto(L, INFILE, "r"); +} + + +static int io_writeto (lua_State *L) { + return io_fromto(L, OUTFILE, "w"); +} + + +static int io_appendto (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *current; + lua_pop(L, 1); /* remove upvalue */ + current = fopen(luaL_check_string(L, 1), "a"); + return setreturn(L, ctrl, current, OUTFILE); +} + + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + + +#ifdef LUA_COMPAT_READPATTERN + +/* +** We cannot lookahead without need, because this can lock stdin. +** This flag signals when we need to read a next char. +*/ +#define NEED_OTHER (EOF-1) /* just some flag different from EOF */ + + +static int read_pattern (lua_State *L, FILE *f, const char *p) { + int inskip = 0; /* {skip} level */ + int c = NEED_OTHER; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (*p != '\0') { + switch (*p) { + case '{': + inskip++; + p++; + continue; + case '}': + if (!inskip) lua_error(L, "unbalanced braces in read pattern"); + inskip--; + p++; + continue; + default: { + const char *ep = luaI_classend(L, p); /* get what is next */ + int m; /* match result */ + if (c == NEED_OTHER) c = getc(f); + m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); + if (m) { + if (!inskip) luaL_putchar(&b, c); + c = NEED_OTHER; + } + switch (*ep) { + case '+': /* repetition (1 or more) */ + if (!m) goto break_while; /* pattern fails? */ + /* else go through */ + case '*': /* repetition (0 or more) */ + while (m) { /* reads the same item until it fails */ + c = getc(f); + m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); + if (m && !inskip) luaL_putchar(&b, c); + } + /* go through to continue reading the pattern */ + case '?': /* optional */ + p = ep+1; /* continues reading the pattern */ + continue; + default: + if (!m) goto break_while; /* pattern fails? */ + p = ep; /* else continues reading the pattern */ + } + } + } + } break_while: + if (c != NEED_OTHER) ungetc(c, f); + luaL_pushresult(&b); /* close buffer */ + return (*p == '\0'); +} + +#else + +#define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0) + +#endif + + +static int read_number (lua_State *L, FILE *f) { +// double d; +// if (fscanf(f, "%lf", &d) == 1) { +// lua_pushnumber(L, d); +// return 1; +// } +// else return 0; /* read fails */ +//} + char v[256],s[256]; + int i,k; + + if (fscanf(f,"%s",v)>0){ + sprintf(s,"return %s",v); + i=lua_gettop(L); + lua_dostring(L,s); + k=lua_gettop(L); + return (k-i); + } + else return 0; /* read fails */ +} + +static int read_word (lua_State *L, FILE *f) { + int c; + luaL_Buffer b; + luaL_buffinit(L, &b); + do { c = fgetc(f); } while (isspace(c)); /* skip spaces */ + while (c != EOF && !isspace(c)) { + luaL_putchar(&b, c); + c = fgetc(f); + } + ungetc(c, f); + luaL_pushresult(&b); /* close buffer */ + return (lua_strlen(L, -1) > 0); +} + + +static int read_line (lua_State *L, FILE *f) { + int n = 0; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + char *p = luaL_prepbuffer(&b); + if (!fgets(p, LUAL_BUFFERSIZE, f)) /* read fails? */ + break; + n = strlen(p); + if (p[n-1] != '\n') + luaL_addsize(&b, n); + else { + luaL_addsize(&b, n-1); /* do not add the `\n' */ + break; + } + } + luaL_pushresult(&b); /* close buffer */ + return (n > 0); /* read something? */ +} + + +static void read_file (lua_State *L, FILE *f) { + size_t len = 0; + size_t size = BUFSIZ; + char *buffer = NULL; + for (;;) { + char *newbuffer = (char *)realloc(buffer, size); + if (newbuffer == NULL) { + free(buffer); + lua_error(L, "not enough memory to read a file"); + } + buffer = newbuffer; + len += fread(buffer+len, sizeof(char), size-len, f); + if (len < size) break; /* did not read all it could */ + size *= 2; + } + lua_pushlstring(L, buffer, len); + free(buffer); +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + char *buffer; + size_t n1; + char statbuff[BUFSIZ]; + if (n <= BUFSIZ) + buffer = statbuff; + else { + buffer = (char *)malloc(n); + if (buffer == NULL) + lua_error(L, "not enough memory to read a file"); + } + n1 = fread(buffer, sizeof(char), n, f); + lua_pushlstring(L, buffer, n1); + if (buffer != statbuff) free(buffer); + return (n1 > 0 || n == 0); +} + + +static int io_read (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + int lastarg = lua_gettop(L) - 1; + int firstarg = 1; + FILE *f = gethandle(L, ctrl, firstarg); + int n; + if (f) firstarg++; + else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ + lua_pop(L, 1); + if (firstarg > lastarg) { /* no arguments? */ + lua_settop(L, 0); /* erase upvalue and other eventual garbage */ + firstarg = lastarg = 1; /* correct indices */ + lua_pushstring(L, "*l"); /* push default argument */ + } + else /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, lastarg-firstarg+1+LUA_MINSTACK, "too many arguments"); + for (n = firstarg; n<=lastarg; n++) { + int success; + if (lua_isnumber(L, n)) + success = read_chars(L, f, (size_t)Re(lua_tonumber(L, n))); + else { + const char *p = luaL_check_string(L, n); + if (p[0] != '*') + success = read_pattern(L, f, p); /* deprecated! */ + else { + switch (p[1]) { + case 'n': /* number */ + if (!read_number(L, f)) goto endloop; /* read fails */ + continue; /* number is already pushed; avoid the "pushstring" */ + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_file(L, f); + success = 1; /* always success */ + break; + case 'w': /* word */ + success = read_word(L, f); + break; + default: + luaL_argerror(L, n, "invalid format"); + success = 0; /* to avoid warnings */ + } + } + } + if (!success) { + lua_pop(L, 1); /* remove last result */ + break; /* read fails */ + } + } endloop: + return n - firstarg; +} + +/* }====================================================== */ + + +static int io_write (lua_State *L) { + char cc[256]; + int lastarg = lua_gettop(L) - 1; + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + int arg = 1; + int status = 1; + FILE *f = gethandle(L, ctrl, arg); + if (f) arg++; + else f = getfilebyref(L, ctrl, OUTFILE); /* get _OUTPUT */ + for (; arg <= lastarg; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { /* LUA_NUMBER */ + /* optimization: could be done exactly as for strings */ + CComplex xx; + xx=lua_tonumber(L, arg); + status = status && fprintf(f, "%s", xx.ToString(cc)) > 0; + } + else { + size_t l; + const char *s = luaL_check_lstr(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + pushresult(L, status); + return 1; +} + + +static int io_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *f; + int op; + long offset; + lua_pop(L, 1); /* remove upvalue */ + f = getnonullfile(L, ctrl, 1); + op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames); + offset = luaL_opt_long(L, 3, 0); + luaL_arg_check(L, op != -1, 2, "invalid mode"); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0); /* error */ + else { + lua_pushnumber(L, ftell(f)); + return 1; + } +} + + +static int io_flush (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); + FILE *f; + lua_pop(L, 1); /* remove upvalue */ + f = gethandle(L, ctrl, 1); + luaL_arg_check(L, f || lua_isnull(L, 1), 1, "invalid file handle"); + return pushresult(L, fflush(f) == 0); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Other O.S. Operations +** ======================================================= +*/ + +static int io_execute (lua_State *L) { + lua_pushnumber(L, system(luaL_check_string(L, 1))); + return 1; +} + + +static int io_remove (lua_State *L) { + return pushresult(L, remove(luaL_check_string(L, 1)) == 0); +} + + +static int io_rename (lua_State *L) { + return pushresult(L, rename(luaL_check_string(L, 1), + luaL_check_string(L, 2)) == 0); +} + + +static int io_tmpname (lua_State *L) { + lua_pushstring(L, tmpnam(NULL)); + return 1; +} + + + +static int io_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int io_clock (lua_State *L) { + lua_pushnumber(L, ((double)clock())/CLOCKS_PER_SEC); + return 1; +} + + +static int io_date (lua_State *L) { + char b[256]; + const char *s = luaL_opt_string(L, 1, "%c"); + struct tm *stm; + time_t t; + time(&t); stm = localtime(&t); + if (strftime(b, sizeof(b), s, stm)) + lua_pushstring(L, b); + else + lua_error(L, "invalid `date' format"); + return 1; +} + + +static int setloc (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames); + luaL_arg_check(L, op != -1, 2, "invalid option"); + lua_pushstring(L, setlocale(cat[op], luaL_check_string(L, 1))); + return 1; +} + + +static int io_exit (lua_State *L) { + exit(luaL_opt_int(L, 1, EXIT_SUCCESS)); + return 0; /* to avoid warnings */ +} + +/* }====================================================== */ + + + +static int io_debug (lua_State *L) { + for (;;) { + char buffer[250]; + fprintf(stderr, "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + lua_dostring(L, buffer); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int errorfb (lua_State *L) { + int level = 1; /* skip level 0 (it's this function) */ + int firstpart = 1; /* still before eventual `...' */ + lua_Debug ar; + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addstring(&b, "error: "); + luaL_addstring(&b, luaL_check_string(L, 1)); + luaL_addstring(&b, "\n"); + while (lua_getstack(L, level++, &ar)) { + char buff[120]; /* enough to fit following `sprintf's */ + if (level == 2) + luaL_addstring(&b, "stack traceback:\n"); + else if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + luaL_addstring(&b, " ...\n"); /* too many levels */ + while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + sprintf(buff, "%4d: ", level-1); + luaL_addstring(&b, buff); + lua_getinfo(L, "Snl", &ar); + switch (*ar.namewhat) { + case 'g': case 'l': /* global, local */ + sprintf(buff, "function `%.50s'", ar.name); + break; + case 'f': /* field */ + sprintf(buff, "method `%.50s'", ar.name); + break; + case 't': /* tag method */ + sprintf(buff, "`%.50s' tag method", ar.name); + break; + default: { + if (*ar.what == 'm') /* main? */ + sprintf(buff, "main of %.70s", ar.short_src); + else if (*ar.what == 'C') /* C function? */ + sprintf(buff, "%.70s", ar.short_src); + else + sprintf(buff, "function <%d:%.70s>", ar.linedefined, ar.short_src); + ar.source = NULL; /* do not print source again */ + } + } + luaL_addstring(&b, buff); + if (ar.currentline > 0) { + sprintf(buff, " at line %d", ar.currentline); + luaL_addstring(&b, buff); + } + if (ar.source) { + sprintf(buff, " [%.70s]", ar.short_src); + luaL_addstring(&b, buff); + } + luaL_addstring(&b, "\n"); + } + luaL_pushresult(&b); + lua_getglobal(L, LUA_ALERT); + if (lua_isfunction(L, -1)) { /* avoid loop if _ALERT is not defined */ + lua_pushvalue(L, -2); /* error message */ + lua_rawcall(L, 1, 0); + } + return 0; +} + + + +static const struct luaL_reg iolib[] = { + {LUA_ERRORMESSAGE, errorfb}, + {"clock", io_clock}, + {"date", io_date}, + {"debug", io_debug}, + {"execute", io_execute}, + {"exit", io_exit}, + {"getenv", io_getenv}, + {"remove", io_remove}, + {"rename", io_rename}, + {"setlocale", setloc}, + {"tmpname", io_tmpname} +}; + + +static const struct luaL_reg iolibtag[] = { + {"appendto", io_appendto}, + {"closefile", io_close}, + {"flush", io_flush}, + {"openfile", io_open}, + {"read", io_read}, + {"readfrom", io_readfrom}, + {"seek", io_seek}, + {"write", io_write}, + {"writeto", io_writeto} +}; + + +static void openwithcontrol (lua_State *L) { + IOCtrl *ctrl = (IOCtrl *)lua_newuserdata(L, sizeof(IOCtrl)); + unsigned int i; + ctrl->iotag = lua_newtag(L); + ctrl->closedtag = lua_newtag(L); + for (i=0; iref[INFILE] = lua_ref(L, 1); + lua_pushstring(L, filenames[OUTFILE]); + ctrl->ref[OUTFILE] = lua_ref(L, 1); + /* predefined file handles */ + setfile(L, ctrl, stdin, INFILE); + setfile(L, ctrl, stdout, OUTFILE); + setfilebyname(L, ctrl, stdin, "_STDIN"); + setfilebyname(L, ctrl, stdout, "_STDOUT"); + setfilebyname(L, ctrl, stderr, "_STDERR"); + /* close files when collected */ + lua_pushcclosure(L, file_collect, 1); /* pops `ctrl' from stack */ + lua_settagmethod(L, ctrl->iotag, "gc"); +} + + +LUALIB_API void lua_iolibopen (lua_State *L) { + luaL_openl(L, iolib); + openwithcontrol(L); +} + diff --git a/liblua/llex.cpp b/liblua/llex.cpp new file mode 100644 index 0000000..4f511ab --- /dev/null +++ b/liblua/llex.cpp @@ -0,0 +1,380 @@ +/* +** $Id: llex.c,v 1.72 2000/10/20 16:39:03 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#include "lua.h" + +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "luadebug.h" +#include "lzio.h" + + + +#define next(LS) (LS->current = zgetc(LS->z)) + + + +/* ORDER RESERVED */ +static const char *const token2string [] = { + "and", "break", "do", "else", "elseif", "end", "for", + "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", + "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", ""}; + + +void luaX_init (lua_State *L) { + int i; + for (i=0; imarked = (unsigned char)(RESERVEDMARK+i); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { + if (val > limit) { + char buff[100]; + sprintf(buff, "too many %.50s (limit=%d)", msg, limit); + luaX_error(ls, buff, ls->t.token); + } +} + + +void luaX_syntaxerror (LexState *ls, const char *s, const char *token) { + char buff[MAXSRC]; + luaO_chunkid(buff, ls->source->str, sizeof(buff)); + luaO_verror(ls->L, "%.99s;\n last token read: `%.30s' at line %d in %.80s", + s, token, ls->linenumber, buff); +} + + +void luaX_error (LexState *ls, const char *s, int token) { + char buff[TOKEN_LEN]; + luaX_token2str(token, buff); + if (buff[0] == '\0') + luaX_syntaxerror(ls, s, ls->L->Mbuffer); + else + luaX_syntaxerror(ls, s, buff); +} + + +void luaX_token2str (int token, char *s) { + if (token < 256) { + s[0] = (char)token; + s[1] = '\0'; + } + else + strcpy(s, token2string[token-FIRST_RESERVED]); +} + + +static void luaX_invalidchar (LexState *ls, int c) { + char buff[8]; + sprintf(buff, "0x%02X", c); + luaX_syntaxerror(ls, "invalid control char", buff); +} + + +static void inclinenumber (LexState *LS) { + next(LS); /* skip '\n' */ + ++LS->linenumber; + luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk"); +} + + +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) { + LS->L = L; + LS->lookahead.token = TK_EOS; /* no look-ahead token */ + LS->z = z; + LS->fs = NULL; + LS->linenumber = 1; + LS->lastline = 1; + LS->source = source; + next(LS); /* read first char */ + if (LS->current == '#') { + do { /* skip first line */ + next(LS); + } while (LS->current != '\n' && LS->current != EOZ); + } +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +/* use Mbuffer to store names, literal strings and numbers */ + +#define EXTRABUFF 128 +#define checkbuffer(L, n, len) if ((len)+(n) > L->Mbuffsize) \ + luaO_openspace(L, (len)+(n)+EXTRABUFF) + +#define save(L, c, l) (L->Mbuffer[l++] = (char)c) +#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS)) + + +static const char *readname (LexState *LS) { + lua_State *L = LS->L; + size_t l = 0; + checkbuffer(L, 10, l); + do { + checkbuffer(L, 10, l); + save_and_next(L, LS, l); + } while (isalnum(LS->current) || LS->current == '_'); + save(L, '\0', l); + return L->Mbuffer; +} + + +/* LUA_NUMBER */ +static void read_number (LexState *LS, int comma, SemInfo *seminfo) { + lua_State *L = LS->L; + size_t l = 0; + checkbuffer(L, 10, l); + if (comma) save(L, '.', l); + while (isdigit(LS->current)) { + checkbuffer(L, 10, l); + save_and_next(L, LS, l); + } + if (LS->current == '.') { + save_and_next(L, LS, l); + if (LS->current == '.') { + save_and_next(L, LS, l); + save(L, '\0', l); + luaX_error(LS, "ambiguous syntax" + " (decimal point x string concatenation)", TK_NUMBER); + } + } + while (isdigit(LS->current)) { + checkbuffer(L, 10, l); + save_and_next(L, LS, l); + } + if (LS->current == 'e' || LS->current == 'E') { + save_and_next(L, LS, l); /* read 'E' */ + if (LS->current == '+' || LS->current == '-') + save_and_next(L, LS, l); /* optional exponent sign */ + while (isdigit(LS->current)) { + checkbuffer(L, 10, l); + save_and_next(L, LS, l); + } + } + save(L, '\0', l); + if (!luaO_str2d(L->Mbuffer, &seminfo->r)) + luaX_error(LS, "malformed number", TK_NUMBER); +} + + +static void read_long_string (LexState *LS, SemInfo *seminfo) { + lua_State *L = LS->L; + int cont = 0; + size_t l = 0; + checkbuffer(L, 10, l); + save(L, '[', l); /* save first '[' */ + save_and_next(L, LS, l); /* pass the second '[' */ + for (;;) { + checkbuffer(L, 10, l); + switch (LS->current) { + case EOZ: + save(L, '\0', l); + luaX_error(LS, "unfinished long string", TK_STRING); + break; /* to avoid warnings */ + case '[': + save_and_next(L, LS, l); + if (LS->current == '[') { + cont++; + save_and_next(L, LS, l); + } + continue; + case ']': + save_and_next(L, LS, l); + if (LS->current == ']') { + if (cont == 0) goto endloop; + cont--; + save_and_next(L, LS, l); + } + continue; + case '\n': + save(L, '\n', l); + inclinenumber(LS); + continue; + default: + save_and_next(L, LS, l); + } + } endloop: + save_and_next(L, LS, l); /* skip the second ']' */ + save(L, '\0', l); + seminfo->ts = luaS_newlstr(L, L->Mbuffer+2, l-5); +} + + +static void read_string (LexState *LS, int del, SemInfo *seminfo) { + lua_State *L = LS->L; + size_t l = 0; + checkbuffer(L, 10, l); + save_and_next(L, LS, l); + while (LS->current != del) { + checkbuffer(L, 10, l); + switch (LS->current) { + case EOZ: case '\n': + save(L, '\0', l); + luaX_error(LS, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': + next(LS); /* do not save the '\' */ + switch (LS->current) { + case 'a': save(L, '\a', l); next(LS); break; + case 'b': save(L, '\b', l); next(LS); break; + case 'f': save(L, '\f', l); next(LS); break; + case 'n': save(L, '\n', l); next(LS); break; + case 'r': save(L, '\r', l); next(LS); break; + case 't': save(L, '\t', l); next(LS); break; + case 'v': save(L, '\v', l); next(LS); break; + case '\n': save(L, '\n', l); inclinenumber(LS); break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + int c = 0; + int i = 0; + do { + c = 10*c + (LS->current-'0'); + next(LS); + } while (++i<3 && isdigit(LS->current)); + if (c != (unsigned char)c) { + save(L, '\0', l); + luaX_error(LS, "escape sequence too large", TK_STRING); + } + save(L, c, l); + break; + } + default: /* handles \\, \", \', and \? */ + save_and_next(L, LS, l); + } + break; + default: + save_and_next(L, LS, l); + } + } + save_and_next(L, LS, l); /* skip delimiter */ + save(L, '\0', l); + seminfo->ts = luaS_newlstr(L, L->Mbuffer+1, l-3); +} + + +int luaX_lex (LexState *LS, SemInfo *seminfo) { + for (;;) { + switch (LS->current) { + + case ' ': case '\t': case '\r': /* `\r' to avoid problems with DOS */ + next(LS); + continue; + + case '\n': + inclinenumber(LS); + continue; + + case '$': + luaX_error(LS, "unexpected `$' (pragmas are no longer supported)", '$'); + break; + + case '-': + next(LS); + if (LS->current != '-') return '-'; + do { next(LS); } while (LS->current != '\n' && LS->current != EOZ); + continue; + + case '[': + next(LS); + if (LS->current != '[') return '['; + else { + read_long_string(LS, seminfo); + return TK_STRING; + } + + case '=': + next(LS); + if (LS->current != '=') return '='; + else { next(LS); return TK_EQ; } + + case '<': + next(LS); + if (LS->current != '=') return '<'; + else { next(LS); return TK_LE; } + + case '>': + next(LS); + if (LS->current != '=') return '>'; + else { next(LS); return TK_GE; } + + case '~': + next(LS); + if (LS->current != '=') return '~'; + else { next(LS); return TK_NE; } + + case '"': + case '\'': + read_string(LS, LS->current, seminfo); + return TK_STRING; + + case '.': + next(LS); + if (LS->current == '.') { + next(LS); + if (LS->current == '.') { + next(LS); + return TK_DOTS; /* ... */ + } + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(LS->current)) return '.'; + else { + read_number(LS, 1, seminfo); + return TK_NUMBER; + } + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + read_number(LS, 0, seminfo); + return TK_NUMBER; + + case EOZ: + return TK_EOS; + + case '_': goto tname; + + default: + if (!isalpha(LS->current)) { + int c = LS->current; + if (iscntrl(c)) + luaX_invalidchar(LS, c); + next(LS); + return c; + } + tname: { /* identifier or reserved word */ + TString *ts = luaS_new(LS->L, readname(LS)); + if (ts->marked >= RESERVEDMARK) /* reserved word? */ + return ts->marked-RESERVEDMARK+FIRST_RESERVED; + seminfo->ts = ts; + return TK_NAME; + } + } + } +} + diff --git a/liblua/llex.h b/liblua/llex.h new file mode 100644 index 0000000..46825b1 --- /dev/null +++ b/liblua/llex.h @@ -0,0 +1,73 @@ +/* +** $Id: llex.h,v 1.31 2000/09/27 17:41:58 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word (+1 for final 0) */ +#define TOKEN_LEN 15 + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FOR, TK_FUNCTION, TK_IF, TK_LOCAL, + TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED ((int)(TK_WHILE-FIRST_RESERVED+1)) + + +typedef class { + public: + Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + struct zio *z; /* input stream */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + TString *source; /* current source name */ +} LexState; + + +void luaX_init (lua_State *L); +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); +int luaX_lex (LexState *LS, SemInfo *seminfo); +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); +void luaX_syntaxerror (LexState *ls, const char *s, const char *token); +void luaX_error (LexState *ls, const char *s, int token); +void luaX_token2str (int token, char *s); + + +#endif diff --git a/liblua/llimits.h b/liblua/llimits.h new file mode 100644 index 0000000..3a46909 --- /dev/null +++ b/liblua/llimits.h @@ -0,0 +1,200 @@ +/* +** $Id: llimits.h,v 1.19 2000/10/26 12:47:05 roberto Exp $ +** Limits, basic types, and some other "installation-dependent" definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + + +/* +** try to find number of bits in an integer +*/ +#ifndef BITS_INT +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define BITS_INT 16 +#else +#if INT_MAX > 2147483640L +/* machine has at least 32 bits */ +#define BITS_INT 32 +#else +#error "you must define BITS_INT with number of bits in an integer" +#endif +#endif +#endif + + +/* +** Define the type `number' of Lua +** GREP LUA_NUMBER to change that +*/ +#ifndef LUA_NUM_TYPE +#define LUA_NUM_TYPE CComplex +#endif + +typedef CComplex Number; + +/* function to convert a Number to a string */ +#define NUMBER_FMT "%.16g" /* LUA_NUMBER */ +void lua_number2str(char *s,Number n); + + +typedef unsigned long lint32; /* unsigned int with at least 32 bits */ + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to int (for hashing only) +** (the shift removes bits that are usually 0 because of alignment) +*/ +#define IntPoint(p) (((unsigned long)(p)) >> 3) + + + +#define MINPOWER2 4 /* minimum size for "growing" vectors */ + + + +#ifndef DEFAULT_STACK_SIZE +#define DEFAULT_STACK_SIZE 1024 +#endif + + + +/* type to ensure maximum alignment */ +union L_Umaxalign { double d; char *s; long l; }; + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +** For a very small machine, you may change that to 2 bytes (and adjust +** the following limits accordingly) +*/ +typedef unsigned long Instruction; + + +/* +** size and position of opcode arguments. +** For an instruction with 2 bytes, size is 16, and size_b can be 5 +** (accordingly, size_u will be 10, and size_a will be 5) +*/ +#define SIZE_INSTRUCTION 32 +#define SIZE_B 9 + +#define SIZE_OP 6 +#define SIZE_U (SIZE_INSTRUCTION-SIZE_OP) +#define POS_U SIZE_OP +#define POS_B SIZE_OP +#define SIZE_A (SIZE_INSTRUCTION-(SIZE_OP+SIZE_B)) +#define POS_A (SIZE_OP+SIZE_B) + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in BITS_INT-1 bits (-1 for sign) +*/ +#if SIZE_U < BITS_INT-1 +#define MAXARG_U ((1<>1) /* `S' is signed */ +#else +#define MAXARG_U MAX_INT +#define MAXARG_S MAX_INT +#endif + +#if SIZE_A < BITS_INT-1 +#define MAXARG_A ((1< MAXARG_B +#undef MAXSTACK +#define MAXSTACK MAXARG_B +#endif + + +/* maximum number of local variables */ +#ifndef MAXLOCALS +#define MAXLOCALS 200 /* arbitrary limit (=MAXSTACK +#undef MAXLOCALS +#define MAXLOCALS (MAXSTACK-1) +#endif + + +/* maximum number of upvalues */ +#ifndef MAXUPVALUES +#define MAXUPVALUES 32 /* arbitrary limit (<=MAXARG_B) */ +#endif +#if MAXUPVALUES>MAXARG_B +#undef MAXUPVALUES +#define MAXUPVALUES MAXARG_B +#endif + + +/* maximum number of variables in the left side of an assignment */ +#ifndef MAXVARSLH +#define MAXVARSLH 100 /* arbitrary limit (=MULT_RET +#undef MAXVARSLH +#define MAXVARSLH (MULT_RET-1) +#endif + + +/* maximum number of parameters in a function */ +#ifndef MAXPARAMS +#define MAXPARAMS 100 /* arbitrary limit (=MAXLOCALS +#undef MAXPARAMS +#define MAXPARAMS (MAXLOCALS-1) +#endif + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 64 +#if LFIELDS_PER_FLUSH>(MAXSTACK/4) +#undef LFIELDS_PER_FLUSH +#define LFIELDS_PER_FLUSH (MAXSTACK/4) +#endif + +/* number of record items to accumulate before a SETMAP instruction */ +/* (each item counts 2 elements on the stack: an index and a value) */ +#define RFIELDS_PER_FLUSH (LFIELDS_PER_FLUSH/2) + + +/* maximum lookback to find a real constant (for code generation) */ +#ifndef LOOKBACKNUMS +#define LOOKBACKNUMS 20 /* arbitrary constant */ +#endif + + +#endif diff --git a/liblua/lmathlib.cpp b/liblua/lmathlib.cpp new file mode 100644 index 0000000..991cdbf --- /dev/null +++ b/liblua/lmathlib.cpp @@ -0,0 +1,286 @@ +/* +** $Id: lmathlib.c,v 1.32 2000/10/31 13:10:24 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + +/* +** If you want Lua to operate in radians (instead of degrees), +** define RADIANS +*/ +#define RADIANS +#ifdef RADIANS +#define FROMRAD(a) (a) +#define TORAD(a) (a) +#else +#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) +#define TORAD(a) ((a)*RADIANS_PER_DEGREE) +#endif + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, abs(luaL_check_number(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1)))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1)))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1)))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1)))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1)))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1)))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, atan2(luaL_check_number(L, 1),luaL_check_number(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(Re(luaL_check_number(L, 1)))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(Re(luaL_check_number(L, 1)))); + return 1; +} + +static int math_mod (lua_State *L) { + lua_pushnumber(L, fmod(Re(luaL_check_number(L, 1)), Re(luaL_check_number(L, 2)))); + return 1; +} + +static int math_sqrt (lua_State *L) { + + lua_pushnumber(L, sqrt(luaL_check_number(L, 1))); + return 1; + +// CComplex x; +// x = sqrt(lua_tonumber(L,1)); +// lua_pushnumber(L,x); +// return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_check_number(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log(luaL_check_number(L, 1))/log(10.) ); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_check_number(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(Re(luaL_check_number(L, 1)), &e)); + lua_pushnumber(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(Re(luaL_check_number(L, 1)), luaL_check_int(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + double dmin = Re(luaL_check_number(L, 1)); + int i; + for (i=2; i<=n; i++) { + double d = Re(luaL_check_number(L, i)); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + double dmax = Re(luaL_check_number(L, 1)); + int i; + for (i=2; i<=n; i++) { + double d = Re(luaL_check_number(L, i)); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the '%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) "rand()" may return a value larger than RAND_MAX */ + double r = (double)(rand()%RAND_MAX) / (double)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_check_int(L, 1); + luaL_arg_check(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, (int)(r*u)+1); /* integer between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_check_int(L, 1); + int u = luaL_check_int(L, 2); + luaL_arg_check(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, (int)(r*(u-l+1))+l); /* integer between `l' and `u' */ + break; + } + default: lua_error(L, "wrong number of arguments"); + } + return 1; +} + +static int math_randomseed (lua_State *L) { + srand(luaL_check_int(L, 1)); + return 0; +} + +static int math_arg (lua_State *L) { + lua_pushnumber(L, arg(luaL_check_number(L, 1))); + return 1; +} + +static int math_re (lua_State *L) { + lua_pushnumber(L, Re(luaL_check_number(L, 1))); + return 1; +} + +static int math_im (lua_State *L) { + lua_pushnumber(L, Im(luaL_check_number(L, 1))); + return 1; +} + +static int math_conj (lua_State *L) { + lua_pushnumber(L, conj(luaL_check_number(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, tanh(luaL_check_number(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, cosh(luaL_check_number(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, sinh(luaL_check_number(L, 1))); + return 1; +} + +static const struct luaL_reg mathlib[] = { +{"abs", math_abs}, +{"sin", math_sin}, +{"cos", math_cos}, +{"tan", math_tan}, +{"asin", math_asin}, +{"acos", math_acos}, +{"atan", math_atan}, +{"atan2", math_atan2}, +{"ceil", math_ceil}, +{"floor", math_floor}, +{"mod", math_mod}, +{"frexp", math_frexp}, +{"ldexp", math_ldexp}, +{"sqrt", math_sqrt}, +{"min", math_min}, +{"max", math_max}, +{"log", math_log}, +{"log10", math_log10}, +{"exp", math_exp}, +{"deg", math_deg}, +{"rad", math_rad}, +{"random", math_random}, +{"randomseed", math_randomseed}, +{"arg", math_arg}, +{"re", math_re}, +{"im", math_im}, +{"conj", math_conj}, +{"tanh", math_tanh}, +{"cosh", math_cosh}, +{"sinh", math_sinh}, +}; + +/* +** Open math library +*/ +LUALIB_API void lua_mathlibopen (lua_State *L) { + luaL_openl(L, mathlib); + lua_pushcfunction(L, math_pow); + lua_settagmethod(L, LUA_TNUMBER, "pow"); + lua_pushnumber(L, PI); + lua_setglobal(L, "PI"); + // does this work? + lua_pushnumber(L, I); + lua_setglobal(L, "I"); +} + diff --git a/liblua/lmem.cpp b/liblua/lmem.cpp new file mode 100644 index 0000000..03a804c --- /dev/null +++ b/liblua/lmem.cpp @@ -0,0 +1,150 @@ +/* +** $Id: lmem.c,v 1.39 2000/10/30 16:29:59 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + + +#ifdef LUA_DEBUG +/* +** {====================================================================== +** Controlled version for realloc. +** ======================================================================= +*/ + + +#include +#include +#include + +#define realloc(b, s) debug_realloc(b, s) +#define malloc(b) debug_realloc(NULL, b) +#define free(b) debug_realloc(b, 0) + + +/* ensures maximum alignment for HEADER */ +#define HEADER (sizeof(union L_Umaxalign)) + +#define MARKSIZE 16 +#define MARK 0x55 /* 01010101 (a nice pattern) */ + + +#define blocksize(b) ((unsigned long *)((char *)(b) - HEADER)) + +unsigned long memdebug_numblocks = 0; +unsigned long memdebug_total = 0; +unsigned long memdebug_maxmem = 0; +unsigned long memdebug_memlimit = LONG_MAX; + + +static void *checkblock (void *block) { + unsigned long *b = blocksize(block); + unsigned long size = *b; + int i; + for (i=0;i memdebug_memlimit) + return NULL; /* to test memory allocation errors */ + else { + size_t realsize = HEADER+size+MARKSIZE; + char *newblock = (char *)(malloc)(realsize); /* alloc a new block */ + int i; + if (realsize < size) return NULL; /* overflow! */ + if (newblock == NULL) return NULL; + if (block) { + size_t oldsize = *blocksize(block); + if (oldsize > size) oldsize = size; + memcpy(newblock+HEADER, block, oldsize); + freeblock(block); /* erase (and check) old copy */ + } + memdebug_total += size; + if (memdebug_total > memdebug_maxmem) memdebug_maxmem = memdebug_total; + memdebug_numblocks++; + *(unsigned long *)newblock = size; + for (i=0;i= limit-inc) lua_error(L, errormsg); + if ((newn ^ nelems) <= nelems || /* still the same power-of-2 limit? */ + (nelems > 0 && newn < MINPOWER2)) /* or block already is MINPOWER2? */ + return block; /* do not need to reallocate */ + else /* it crossed a power-of-2 boundary; grow to next power */ + return luaM_realloc(L, block, luaO_power2(newn)*size); +} + + +/* +** generic allocation routine. +*/ +void *luaM_realloc (lua_State *L, void *block, lint32 size) { + if (size == 0) { + free(block); /* block may be NULL; that is OK for free */ + return NULL; + } + else if (size >= MAX_SIZET) + lua_error(L, "memory allocation error: block too big"); + block = realloc(block, size); + if (block == NULL) { + if (L) + luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */ + else return NULL; /* error before creating state! */ + } + return block; +} + + diff --git a/liblua/lmem.h b/liblua/lmem.h new file mode 100644 index 0000000..451edf0 --- /dev/null +++ b/liblua/lmem.h @@ -0,0 +1,42 @@ +/* +** $Id: lmem.h,v 1.16 2000/10/30 16:29:59 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include +#include "lua.h" +#include "llimits.h" + + +void *luaM_realloc (lua_State *L, void *oldblock, lint32 size); +void *luaM_growaux (lua_State *L, void *block, size_t nelems, + int inc, size_t size, const char *errormsg, + size_t limit); + +#define luaM_free(L, b) luaM_realloc(L, (b), 0) +#define luaM_malloc(L, t) luaM_realloc(L, NULL, (t)) +#define luaM_new(L, t) ((t *)luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L, n,t) ((t *)luaM_malloc(L, (n)*(lint32)sizeof(t))) + +#define luaM_growvector(L, v,nelems,inc,t,e,l) \ + ((v)=(t *)luaM_growaux(L, v,nelems,inc,sizeof(t),e,l)) + +#define luaM_reallocvector(L, v,n,t) \ + ((v)=(t *)luaM_realloc(L, v,(n)*(lint32)sizeof(t))) + + +#ifdef LUA_DEBUG +extern unsigned long memdebug_numblocks; +extern unsigned long memdebug_total; +extern unsigned long memdebug_maxmem; +extern unsigned long memdebug_memlimit; +#endif + + +#endif + diff --git a/liblua/lobject.cpp b/liblua/lobject.cpp new file mode 100644 index 0000000..ff8413e --- /dev/null +++ b/liblua/lobject.cpp @@ -0,0 +1,209 @@ +/* +** $Id: lobject.c,v 1.55 2000/10/20 16:36:32 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +// const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; +TObject luaO_nilobject; + +//luaO_nilobject.ttype = 1; +//luaO_nilobject.Value = {NULL}; + +const char *const luaO_typenames[] = { + "userdata", "nil", "number", "string", "table", "function" +}; + + + +/* +** returns smaller power of 2 larger than `n' (minimum is MINPOWER2) +*/ +lint32 luaO_power2 (lint32 n) { + lint32 p = MINPOWER2; + while (p<=n) p<<=1; + return p; +} + + +int luaO_equalObj (const TObject *t1, const TObject *t2) { + if (ttype(t1) != ttype(t2)) return 0; + switch (ttype(t1)) { + case LUA_TNUMBER: + return (Re(nvalue(t1)) == Re(nvalue(t2))) && (Im(nvalue(t1)) == Im(nvalue(t2))); + case LUA_TSTRING: case LUA_TUSERDATA: + return tsvalue(t1) == tsvalue(t2); + case LUA_TTABLE: + return hvalue(t1) == hvalue(t2); + case LUA_TFUNCTION: + return clvalue(t1) == clvalue(t2); + default: + LUA_ASSERT(ttype(t1) == LUA_TNIL, "invalid type"); + return 1; /* LUA_TNIL */ + } +} + + +char *luaO_openspace (lua_State *L, size_t n) { + if (n > L->Mbuffsize) { + luaM_reallocvector(L, L->Mbuffer, n, char); + L->nblocks += (n - L->Mbuffsize)*sizeof(char); + L->Mbuffsize = n; + } + return L->Mbuffer; +} + +// LUA_NUMBER +CComplex lua_str2number(const char *s, char **endptr) +{ + CComplex x; + char *q; + + // strip off real part; + x.re=strtod(s, &q); + + // if string _only_ contains a real, return; + if (q[0]==NULL){ + *endptr=q; + return x; + } + + // remainder of string _may_ contain a complex number; + + if (strcmp(q,"I")==0){ + x.im=1; + *endptr=(q+1); + return x; + } + + if (strcmp(q,"+I")==0){ + x.im=1; + *endptr=(q+2); + return x; + } + + if (strcmp(q,"-I")==0){ + x.im=-1; + *endptr=(q+2); + return x; + } + + if (strncmp(q,"I*",2)==0){ + x.im=strtod(q+2,endptr); + return x; + } + + if (strncmp(q,"+I*",3)==0){ + x.im=strtod(q+3,endptr); + return x; + } + + if (strncmp(q,"-I*",3)==0){ + x.im=-strtod(q+3,endptr); + return x; + } + + *endptr=q; + return x; +} + +int luaO_str2d (const char *s, Number *result) { // LUA_NUMBER + char *endptr; + Number res = lua_str2number(s, &endptr); + if (endptr == s) return 0; // no conversion + while (isspace((unsigned char)*endptr)) endptr++; + if (*endptr != '\0') return 0; // invalid trailing characters? + *result = res; + return 1; +} + +/* +// LUA_NUMBER +int luaO_str2d(const char *v, Number *result) +{ + char s[256]; + int i,k; + + lua_State *L = lua_open(100); + i=lua_gettop(L); + sprintf(s,"return %s",s); + lua_dostring(L,s); + k=lua_gettop(L); + if(k!=i) + { + *result=lua_tonumber(L,-1); + lua_close(L); + return 1; + } + lua_close(L); + return 0; +} +*/ + +/* maximum length of a string format for `luaO_verror' */ +#define MAX_VERROR 280 + +/* this function needs to handle only '%d' and '%.XXs' formats */ +void luaO_verror (lua_State *L, const char *fmt, ...) { + va_list argp; + char buff[MAX_VERROR]; /* to hold formatted message */ + va_start(argp, fmt); + vsprintf(buff, fmt, argp); + va_end(argp); + lua_error(L, buff); +} + + +void luaO_chunkid (char *out, const char *source, int bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { + if (*source == '@') { + int l; + source++; /* skip the `@' */ + bufflen -= sizeof("file `...%s'"); + l = strlen(source); + if (l>bufflen) { + source += (l-bufflen); /* get last part of file name */ + sprintf(out, "file `...%.99s'", source); + } + else + sprintf(out, "file `%.99s'", source); + } + else { + int len = strcspn(source, "\n"); /* stop at first newline */ + bufflen -= sizeof("string \"%.*s...\""); + if (len > bufflen) len = bufflen; + if (source[len] != '\0') { /* must truncate? */ + strcpy(out, "string \""); + out += strlen(out); + strncpy(out, source, len); + strcpy(out+len, "...\""); + } + else + sprintf(out, "string \"%.99s\"", source); + } + } +} + +void lua_number2str(char *s,Number n) +{ + char cc[256]; + sprintf(s,"%s",n.ToString(cc)); +} diff --git a/liblua/lobject.h b/liblua/lobject.h new file mode 100644 index 0000000..2baa5f5 --- /dev/null +++ b/liblua/lobject.h @@ -0,0 +1,207 @@ +/* +** $Id: lobject.h,v 1.82 2000/10/30 17:49:19 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + +#ifndef lobject_h +#define lobject_h + +#include "lua.h" +#include "llimits.h" + + + +#ifdef LUA_DEBUG +#undef NDEBUG +#include +#define LUA_INTERNALERROR(s) assert(((void)s,0)) +#define LUA_ASSERT(c,s) assert(((void)s,(c))) +#else +#define LUA_INTERNALERROR(s) /* empty */ +#define LUA_ASSERT(c,s) /* empty */ +#endif + + +#ifdef LUA_DEBUG +/* to avoid warnings, and make sure value is really unused */ +#define UNUSED(x) (x=0, (void)(x)) +#else +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +/* mark for closures active in the stack */ +#define LUA_TMARK 6 + + +/* tags for values visible from Lua == first user-created tag */ +#define NUM_TAGS 6 + + +/* check whether `t' is a mark */ +#define is_T_MARK(t) ((t) == LUA_TMARK) + + +// typedef union { +typedef class { + public: + struct TString *ts; /* LUA_TSTRING, LUA_TUSERDATA */ + struct Closure *cl; /* LUA_TFUNCTION */ + struct Hash *a; /* LUA_TTABLE */ + struct CallInfo *i; /* LUA_TLMARK */ + Number n; /* LUA_TNUMBER */ +} Value; + + +/* Macros to access values */ +#define ttype(o) ((o)->ttype) +#define nvalue(o) ((o)->value.n) +#define tsvalue(o) ((o)->value.ts) +#define clvalue(o) ((o)->value.cl) +#define hvalue(o) ((o)->value.a) +#define infovalue(o) ((o)->value.i) +#define svalue(o) (tsvalue(o)->str) + + +typedef struct lua_TObject { + int ttype; + Value value; +} TObject; + + +/* +** String headers for string table +*/ + +/* +** most `malloc' libraries allocate memory in blocks of 8 bytes. TSPACK +** tries to make sizeof(TString) a multiple of this granularity, to reduce +** waste of space. +*/ +#define TSPACK ((int)sizeof(int)) + +typedef struct TString { + union { + struct { /* for strings */ + unsigned long hash; + int constindex; /* hint to reuse constants */ + } s; + struct { /* for userdata */ + int tag; + void *value; + } d; + } u; + size_t len; + struct TString *nexthash; /* chain for hash table */ + int marked; + char str[TSPACK]; /* variable length string!! must be the last field! */ +} TString; + + +/* +** Function Prototypes +*/ +typedef struct Proto { + Number *knum; /* Number numbers used by the function */ + int nknum; /* size of `knum' */ + struct TString **kstr; /* strings used by the function */ + int nkstr; /* size of `kstr' */ + struct Proto **kproto; /* functions defined inside the function */ + int nkproto; /* size of `kproto' */ + Instruction *code; + int ncode; /* size of `code'; when 0 means an incomplete `Proto' */ + short numparams; + short is_vararg; + short maxstacksize; + short marked; + struct Proto *next; + /* debug information */ + int *lineinfo; /* map from opcodes to source lines */ + int nlineinfo; /* size of `lineinfo' */ + int nlocvars; + struct LocVar *locvars; /* information about local variables */ + int lineDefined; + TString *source; +} Proto; + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + +/* +** Closures +*/ +typedef struct Closure { + union { + lua_CFunction c; /* C functions */ + struct Proto *l; /* Lua functions */ + } f; + struct Closure *next; + struct Closure *mark; /* marked closures (point to itself when not marked) */ + short isC; /* 0 for Lua functions, 1 for C functions */ + short nupvalues; + TObject upvalue[1]; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) + + +typedef struct Node { + TObject key; + TObject val; + struct Node *next; /* for chaining */ +} Node; + +typedef struct Hash { + Node *node; + int htag; + int size; + Node *firstfree; /* this position is free; all positions after it are full */ + struct Hash *next; + struct Hash *mark; /* marked tables (point to itself when not marked) */ +} Hash; + + +/* unmarked tables and closures are represented by pointing `mark' to +** themselves +*/ +#define ismarked(x) ((x)->mark != (x)) + + +/* +** informations about a call (for debugging) +*/ +typedef struct CallInfo { + struct Closure *func; /* function being called */ + const Instruction **pc; /* current pc of called function */ + int lastpc; /* last pc traced */ + int line; /* current line */ + int refi; /* current index in `lineinfo' */ +} CallInfo; + + +// extern const TObject luaO_nilobject; +extern TObject luaO_nilobject; +extern const char *const luaO_typenames[]; + + +#define luaO_typename(o) (luaO_typenames[ttype(o)]) + + +lint32 luaO_power2 (lint32 n); +char *luaO_openspace (lua_State *L, size_t n); + +int luaO_equalObj (const TObject *t1, const TObject *t2); +int luaO_str2d (const char *s, Number *result); + +void luaO_verror (lua_State *L, const char *fmt, ...); +void luaO_chunkid (char *out, const char *source, int len); + + +#endif diff --git a/liblua/lopcodes.h b/liblua/lopcodes.h new file mode 100644 index 0000000..48f7d00 --- /dev/null +++ b/liblua/lopcodes.h @@ -0,0 +1,169 @@ +/* +** $Id: lopcodes.h,v 1.68 2000/10/24 16:05:59 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. Moreover, + an instruction can have 0, 1, or 2 arguments. Instructions can + have the following types: + type 0: no arguments + type 1: 1 unsigned argument in the higher bits (called `U') + type 2: 1 signed argument in the higher bits (`S') + type 3: 1st unsigned argument in the higher bits (`A') + 2nd unsigned argument in the middle bits (`B') + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. + + The size of each argument is defined in `llimits.h'. The usual is an + instruction with 32 bits, U arguments with 26 bits (32-6), B arguments + with 9 bits, and A arguments with 17 bits (32-6-9). For small + installations, the instruction size can be 16, so U has 10 bits, + and A and B have 5 bits each. +===========================================================================*/ + + + + +/* creates a mask with `n' 1 bits at position `p' */ +#define MASK1(n,p) ((~((~(Instruction)0)<>POS_U)) +#define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ + ((Instruction)(u)<>POS_A)) +#define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((Instruction)(a)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((Instruction)(b)<y)? PC+=s */ +OP_JMPGE,/* J y x - (x>=y)? PC+=s */ + +OP_JMPT,/* J x - (x~=nil)? PC+=s */ +OP_JMPF,/* J x - (x==nil)? PC+=s */ +OP_JMPONT,/* J x (x~=nil)? x : - (x~=nil)? PC+=s */ +OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ +OP_JMP,/* J - - PC+=s */ + +OP_PUSHNILJMP,/* - - nil PC++; */ + +OP_FORPREP,/* J */ +OP_FORLOOP,/* J */ + +OP_LFORPREP,/* J */ +OP_LFORLOOP,/* J */ + +OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ + +} OpCode; + +#define NUM_OPCODES ((int)OP_CLOSURE+1) + + +#define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) + + + +/* special code to fit a LUA_MULTRET inside an argB */ +#define MULT_RET 255 /* (<=MAXARG_B) */ +#if MULT_RET>MAXARG_B +#undef MULT_RET +#define MULT_RET MAXARG_B +#endif + + +#endif diff --git a/liblua/lparser.cpp b/liblua/lparser.cpp new file mode 100644 index 0000000..b792c95 --- /dev/null +++ b/liblua/lparser.cpp @@ -0,0 +1,1124 @@ +/* +** $Id: lparser.c,v 1.116 2000/10/27 11:39:52 roberto Exp $ +** LL(1) Parser and code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#include "lua.h" + +#include "lcode.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" + + +/* +** Constructors descriptor: +** `n' indicates number of elements, and `k' signals whether +** it is a list constructor (k = 0) or a record constructor (k = 1) +** or empty (k = ';' or '}') +*/ +typedef struct Constdesc { + int n; + int k; +} Constdesc; + + +typedef struct Breaklabel { + struct Breaklabel *previous; /* chain */ + int breaklist; + int stacklevel; +} Breaklabel; + + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void body (LexState *ls, int needself, int line); +static void chunk (LexState *ls); +static void constructor (LexState *ls); +static void expr (LexState *ls, expdesc *v); +static void exp1 (LexState *ls); + + + +static void next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */ +} + + +static void lookahead (LexState *ls) { + LUA_ASSERT(ls->lookahead.token == TK_EOS, "two look-aheads"); + ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo); +} + + +static void error_expected (LexState *ls, int token) { + char buff[100], t[TOKEN_LEN]; + luaX_token2str(token, t); + sprintf(buff, "`%.20s' expected", t); + luaK_error(ls, buff); +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); + next(ls); +} + + +static void check_condition (LexState *ls, int c, const char *msg) { + if (!c) luaK_error(ls, msg); +} + + +static int optional (LexState *ls, int c) { + if (ls->t.token == c) { + next(ls); + return 1; + } + else return 0; +} + + +static void check_match (LexState *ls, int what, int who, int where) { + if (ls->t.token != what) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + char buff[100]; + char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; + luaX_token2str(what, t_what); + luaX_token2str(who, t_who); + sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", + t_what, t_who, where); + luaK_error(ls, buff); + } + } + next(ls); +} + + +static int string_constant (FuncState *fs, TString *s) { + Proto *f = fs->f; + int c = s->u.s.constindex; + if (c >= f->nkstr || f->kstr[c] != s) { + luaM_growvector(fs->L, f->kstr, f->nkstr, 1, TString *, + "constant table overflow", MAXARG_U); + c = f->nkstr++; + f->kstr[c] = s; + s->u.s.constindex = c; /* hint for next time */ + } + return c; +} + + +static void code_string (LexState *ls, TString *s) { + luaK_kstr(ls, string_constant(ls->fs, s)); +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check_condition(ls, (ls->t.token == TK_NAME), " expected"); + ts = ls->t.seminfo.ts; + next(ls); + return ts; +} + + +static int checkname (LexState *ls) { + return string_constant(ls->fs, str_checkname(ls)); +} + + +static int luaI_registerlocalvar (LexState *ls, TString *varname) { + Proto *f = ls->fs->f; + luaM_growvector(ls->L, f->locvars, f->nlocvars, 1, LocVar, "", MAX_INT); + f->locvars[f->nlocvars].varname = varname; + return f->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaX_checklimit(ls, fs->nactloc+n+1, MAXLOCALS, "local variables"); + fs->actloc[fs->nactloc+n] = luaI_registerlocalvar(ls, name); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + while (nvars--) + fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc; +} + + +static void removelocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + while (nvars--) + fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; +} + + +static void new_localvarstr (LexState *ls, const char *name, int n) { + new_localvar(ls, luaS_newfixed(ls->L, name), n); +} + + +static int search_local (LexState *ls, TString *n, expdesc *var) { + FuncState *fs; + int level = 0; + for (fs=ls->fs; fs; fs=fs->prev) { + int i; + for (i=fs->nactloc-1; i >= 0; i--) { + if (n == fs->f->locvars[fs->actloc[i]].varname) { + var->k = VLOCAL; + var->u.index = i; + return level; + } + } + level++; /* `var' not found; check outer level */ + } + var->k = VGLOBAL; /* not found in any level; must be global */ + return -1; +} + + +static void singlevar (LexState *ls, TString *n, expdesc *var) { + int level = search_local(ls, n, var); + if (level >= 1) /* neither local (0) nor global (-1)? */ + luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); + else if (level == -1) /* global? */ + var->u.index = string_constant(ls->fs, n); +} + + +static int indexupvalue (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs; + int i; + for (i=0; inupvalues; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.index == v->u.index) + return i; + } + /* new one */ + luaX_checklimit(ls, fs->nupvalues+1, MAXUPVALUES, "upvalues"); + fs->upvalues[fs->nupvalues] = *v; + return fs->nupvalues++; +} + + +static void pushupvalue (LexState *ls, TString *n) { + FuncState *fs = ls->fs; + expdesc v; + int level = search_local(ls, n, &v); + if (level == -1) { /* global? */ + if (fs->prev == NULL) + luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); + v.u.index = string_constant(fs->prev, n); + } + else if (level != 1) + luaX_syntaxerror(ls, + "upvalue must be global or local to immediately outer scope", n->str); + luaK_code1(fs, OP_PUSHUPVALUE, indexupvalue(ls, &v)); +} + + +static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { + FuncState *fs = ls->fs; + int diff = nexps - nvars; + if (nexps > 0 && luaK_lastisopen(fs)) { /* list ends in a function call */ + diff--; /* do not count function call itself */ + if (diff <= 0) { /* more variables than values? */ + luaK_setcallreturns(fs, -diff); /* function call provide extra values */ + diff = 0; /* no more difference */ + } + else /* more values than variables */ + luaK_setcallreturns(fs, 0); /* call should provide no value */ + } + /* push or pop eventual difference between list lengths */ + luaK_adjuststack(fs, diff); +} + + +static void code_params (LexState *ls, int nparams, int dots) { + FuncState *fs = ls->fs; + adjustlocalvars(ls, nparams); + luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); + fs->f->numparams = fs->nactloc; /* `self' could be there already */ + fs->f->is_vararg = dots; + if (dots) { + new_localvarstr(ls, "arg", 0); + adjustlocalvars(ls, 1); + } + luaK_deltastack(fs, fs->nactloc); /* count parameters in the stack */ +} + + +static void enterbreak (FuncState *fs, Breaklabel *bl) { + bl->stacklevel = fs->stacklevel; + bl->breaklist = NO_JUMP; + bl->previous = fs->bl; + fs->bl = bl; +} + + +static void leavebreak (FuncState *fs, Breaklabel *bl) { + fs->bl = bl->previous; + LUA_ASSERT(bl->stacklevel == fs->stacklevel, "wrong levels"); + luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); +} + + +static void pushclosure (LexState *ls, FuncState *func) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int i; + for (i=0; inupvalues; i++) + luaK_tostack(ls, &func->upvalues[i], 1); + luaM_growvector(ls->L, f->kproto, f->nkproto, 1, Proto *, + "constant table overflow", MAXARG_A); + f->kproto[f->nkproto++] = func->f; + luaK_code2(fs, OP_CLOSURE, f->nkproto-1, func->nupvalues); +} + + +static void open_func (LexState *ls, FuncState *fs) { + Proto *f = luaF_newproto(ls->L); + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = ls->L; + ls->fs = fs; + fs->stacklevel = 0; + fs->nactloc = 0; + fs->nupvalues = 0; + fs->bl = NULL; + fs->f = f; + f->source = ls->source; + fs->pc = 0; + fs->lasttarget = 0; + fs->lastline = 0; + fs->jlt = NO_JUMP; + f->code = NULL; + f->maxstacksize = 0; + f->numparams = 0; /* default for main chunk */ + f->is_vararg = 0; /* default for main chunk */ +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaK_code0(fs, OP_END); + luaK_getlabel(fs); /* close eventual list of pending jumps */ + luaM_reallocvector(L, f->code, fs->pc, Instruction); + luaM_reallocvector(L, f->kstr, f->nkstr, TString *); + luaM_reallocvector(L, f->knum, f->nknum, Number); + luaM_reallocvector(L, f->kproto, f->nkproto, Proto *); + removelocalvars(ls, fs->nactloc); + luaM_reallocvector(L, f->locvars, f->nlocvars, LocVar); + luaM_reallocvector(L, f->lineinfo, f->nlineinfo+1, int); + f->lineinfo[f->nlineinfo++] = MAX_INT; /* end flag */ + luaF_protook(L, f, fs->pc); /* proto is ok now */ + ls->fs = fs->prev; + LUA_ASSERT(fs->bl == NULL, "wrong list end"); +} + + +Proto *luaY_parser (lua_State *L, ZIO *z) { + struct LexState lexstate; + struct FuncState funcstate; + luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); + open_func(&lexstate, &funcstate); + next(&lexstate); /* read first token */ + chunk(&lexstate); + check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); + close_func(&lexstate); + LUA_ASSERT(funcstate.prev == NULL, "wrong list end"); + LUA_ASSERT(funcstate.nupvalues == 0, "no upvalues in main"); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static int explist1 (LexState *ls) { + /* explist1 -> expr { ',' expr } */ + int n = 1; /* at least one expression */ + expdesc v; + expr(ls, &v); + while (ls->t.token == ',') { + luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ + next(ls); /* skip comma */ + expr(ls, &v); + n++; + } + luaK_tostack(ls, &v, 0); /* keep open number of values of last expression */ + return n; +} + + +static void funcargs (LexState *ls, int slf) { + FuncState *fs = ls->fs; + int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ + switch (ls->t.token) { + case '(': { /* funcargs -> '(' [ explist1 ] ')' */ + int line = ls->linenumber; + int nargs = 0; + next(ls); + if (ls->t.token != ')') /* arg list not empty? */ + nargs = explist1(ls); + check_match(ls, ')', '(', line); +#ifdef LUA_COMPAT_ARGRET + if (nargs > 0) /* arg list is not empty? */ + luaK_setcallreturns(fs, 1); /* last call returns only 1 value */ +#else + UNUSED(nargs); /* to avoid warnings */ +#endif + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ + next(ls); + break; + } + default: { + luaK_error(ls, "function arguments expected"); + break; + } + } + fs->stacklevel = slevel; /* call will remove function and arguments */ + luaK_code2(fs, OP_CALL, slevel, MULT_RET); +} + + +static void var_or_func_tail (LexState *ls, expdesc *v) { + for (;;) { + switch (ls->t.token) { + case '.': { /* var_or_func_tail -> '.' NAME */ + next(ls); + luaK_tostack(ls, v, 1); /* `v' must be on stack */ + luaK_kstr(ls, checkname(ls)); + v->k = VINDEXED; + break; + } + case '[': { /* var_or_func_tail -> '[' exp1 ']' */ + next(ls); + luaK_tostack(ls, v, 1); /* `v' must be on stack */ + v->k = VINDEXED; + exp1(ls); + check(ls, ']'); + break; + } + case ':': { /* var_or_func_tail -> ':' NAME funcargs */ + int name; + next(ls); + name = checkname(ls); + luaK_tostack(ls, v, 1); /* `v' must be on stack */ + luaK_code1(ls->fs, OP_PUSHSELF, name); + funcargs(ls, 1); + v->k = VEXP; + v->u.l.t = v->u.l.f = NO_JUMP; + break; + } + case '(': case TK_STRING: case '{': { /* var_or_func_tail -> funcargs */ + luaK_tostack(ls, v, 1); /* `v' must be on stack */ + funcargs(ls, 0); + v->k = VEXP; + v->u.l.t = v->u.l.f = NO_JUMP; + break; + } + default: return; /* should be follow... */ + } + } +} + + +static void var_or_func (LexState *ls, expdesc *v) { + /* var_or_func -> ['%'] NAME var_or_func_tail */ + if (optional(ls, '%')) { /* upvalue? */ + pushupvalue(ls, str_checkname(ls)); + v->k = VEXP; + v->u.l.t = v->u.l.f = NO_JUMP; + } + else /* variable name */ + singlevar(ls, str_checkname(ls), v); + var_or_func_tail(ls, v); +} + + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +static void recfield (LexState *ls) { + /* recfield -> (NAME | '['exp1']') = exp1 */ + switch (ls->t.token) { + case TK_NAME: { + luaK_kstr(ls, checkname(ls)); + break; + } + case '[': { + next(ls); + exp1(ls); + check(ls, ']'); + break; + } + default: luaK_error(ls, " or `[' expected"); + } + check(ls, '='); + exp1(ls); +} + + +static int recfields (LexState *ls) { + /* recfields -> recfield { ',' recfield } [','] */ + FuncState *fs = ls->fs; + int n = 1; /* at least one element */ + recfield(ls); + while (ls->t.token == ',') { + next(ls); + if (ls->t.token == ';' || ls->t.token == '}') + break; + recfield(ls); + n++; + if (n%RFIELDS_PER_FLUSH == 0) + luaK_code1(fs, OP_SETMAP, RFIELDS_PER_FLUSH); + } + luaK_code1(fs, OP_SETMAP, n%RFIELDS_PER_FLUSH); + return n; +} + + +static int listfields (LexState *ls) { + /* listfields -> exp1 { ',' exp1 } [','] */ + FuncState *fs = ls->fs; + int n = 1; /* at least one element */ + exp1(ls); + while (ls->t.token == ',') { + next(ls); + if (ls->t.token == ';' || ls->t.token == '}') + break; + exp1(ls); + n++; + luaX_checklimit(ls, n/LFIELDS_PER_FLUSH, MAXARG_A, + "`item groups' in a list initializer"); + if (n%LFIELDS_PER_FLUSH == 0) + luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); + } + luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); + return n; +} + + + +static void constructor_part (LexState *ls, Constdesc *cd) { + switch (ls->t.token) { + case ';': case '}': { /* constructor_part -> empty */ + cd->n = 0; + cd->k = ls->t.token; + break; + } + case TK_NAME: { /* may be listfields or recfields */ + lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + goto case_default; + /* else go through to recfields */ + } + case '[': { /* constructor_part -> recfields */ + cd->n = recfields(ls); + cd->k = 1; /* record */ + break; + } + default: { /* constructor_part -> listfields */ + case_default: + cd->n = listfields(ls); + cd->k = 0; /* list */ + break; + } + } +} + + +static void constructor (LexState *ls) { + /* constructor -> '{' constructor_part [';' constructor_part] '}' */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_code1(fs, OP_CREATETABLE, 0); + int nelems; + Constdesc cd; + check(ls, '{'); + constructor_part(ls, &cd); + nelems = cd.n; + if (optional(ls, ';')) { + Constdesc other_cd; + constructor_part(ls, &other_cd); + check_condition(ls, (cd.k != other_cd.k), "invalid constructor syntax"); + nelems += other_cd.n; + } + check_match(ls, '}', '{', line); + luaX_checklimit(ls, nelems, MAXARG_U, "elements in a table constructor"); + SETARG_U(fs->f->code[pc], nelems); /* set initial table size */ +} + +/* }====================================================================== */ + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void simpleexp (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs; + switch (ls->t.token) { + case TK_NUMBER: { /* simpleexp -> NUMBER */ + Number r = ls->t.seminfo.r; + next(ls); + luaK_number(fs, r); + break; + } + case TK_STRING: { /* simpleexp -> STRING */ + code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ + next(ls); + break; + } + case TK_NIL: { /* simpleexp -> NIL */ + luaK_adjuststack(fs, -1); + next(ls); + break; + } + case '{': { /* simpleexp -> constructor */ + constructor(ls); + break; + } + case TK_FUNCTION: { /* simpleexp -> FUNCTION body */ + next(ls); + body(ls, 0, ls->linenumber); + break; + } + case '(': { /* simpleexp -> '(' expr ')' */ + next(ls); + expr(ls, v); + check(ls, ')'); + return; + } + case TK_NAME: case '%': { + var_or_func(ls, v); + return; + } + default: { + luaK_error(ls, " expected"); + return; + } + } + v->k = VEXP; + v->u.l.t = v->u.l.f = NO_JUMP; +} + + +static void exp1 (LexState *ls) { + expdesc v; + expr(ls, &v); + luaK_tostack(ls, &v, 1); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MULT; + case '/': return OPR_DIV; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + char left; /* left priority for each binary operator */ + char right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {5, 5}, {5, 5}, {6, 6}, {6, 6}, /* arithmetic */ + {9, 8}, {4, 3}, /* power and concat (right associative) */ + {2, 2}, {2, 2}, /* equality */ + {2, 2}, {2, 2}, {2, 2}, {2, 2}, /* order */ + {1, 1}, {1, 1} /* logical */ +}; + +#define UNARY_PRIORITY 7 /* priority for unary operators */ + + +/* +** subexpr -> (simplexep | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + next(ls); + luaK_infix(ls, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls, op, v, &v2); + op = nextop; + } + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, -1); +} + +/* }==================================================================== */ + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + int nactloc = fs->nactloc; + chunk(ls); + luaK_adjuststack(fs, fs->nactloc - nactloc); /* remove local variables */ + removelocalvars(ls, fs->nactloc - nactloc); +} + + +static int assignment (LexState *ls, expdesc *v, int nvars) { + int left = 0; /* number of values left in the stack after assignment */ + luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); + if (ls->t.token == ',') { /* assignment -> ',' NAME assignment */ + expdesc nv; + next(ls); + var_or_func(ls, &nv); + check_condition(ls, (nv.k != VEXP), "syntax error"); + left = assignment(ls, &nv, nvars+1); + } + else { /* assignment -> '=' explist1 */ + int nexps; + check(ls, '='); + nexps = explist1(ls); + adjust_mult_assign(ls, nvars, nexps); + } + if (v->k != VINDEXED) + luaK_storevar(ls, v); + else { /* there may be garbage between table-index and value */ + luaK_code2(ls->fs, OP_SETTABLE, left+nvars+2, 1); + left += 2; + } + return left; +} + + +static void cond (LexState *ls, expdesc *v) { + /* cond -> exp */ + expr(ls, v); /* read condition */ + luaK_goiftrue(ls->fs, v, 0); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int while_init = luaK_getlabel(fs); + expdesc v; + Breaklabel bl; + enterbreak(fs, &bl); + next(ls); + cond(ls, &v); + check(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), while_init); + luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); + check_match(ls, TK_END, TK_WHILE, line); + leavebreak(fs, &bl); +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + expdesc v; + Breaklabel bl; + enterbreak(fs, &bl); + next(ls); + block(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + cond(ls, &v); + luaK_patchlist(fs, v.u.l.f, repeat_init); + leavebreak(fs, &bl); +} + + +static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { + /* forbody -> DO block END */ + FuncState *fs = ls->fs; + int prep = luaK_code1(fs, prepfor, NO_JUMP); + int blockinit = luaK_getlabel(fs); + check(ls, TK_DO); + adjustlocalvars(ls, nvar); /* scope for control variables */ + block(ls); + luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); + luaK_patchlist(fs, prep, luaK_getlabel(fs)); + removelocalvars(ls, nvar); +} + + +static void fornum (LexState *ls, TString *varname) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + check(ls, '='); + exp1(ls); /* initial value */ + check(ls, ','); + exp1(ls); /* limit */ + if (optional(ls, ',')) + exp1(ls); /* optional step */ + else + luaK_code1(fs, OP_PUSHINT, 1); /* default step */ + new_localvar(ls, varname, 0); + new_localvarstr(ls, "(limit)", 1); + new_localvarstr(ls, "(step)", 2); + forbody(ls, 3, OP_FORPREP, OP_FORLOOP); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME,NAME IN exp1 forbody */ + TString *valname; + check(ls, ','); + valname = str_checkname(ls); + /* next test is dirty, but avoids `in' being a reserved word */ + check_condition(ls, + (ls->t.token == TK_NAME && ls->t.seminfo.ts == luaS_new(ls->L, "in")), + "`in' expected"); + next(ls); /* skip `in' */ + exp1(ls); /* table */ + new_localvarstr(ls, "(table)", 0); + new_localvar(ls, indexname, 1); + new_localvar(ls, valname, 2); + forbody(ls, 3, OP_LFORPREP, OP_LFORLOOP); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> fornum | forlist */ + FuncState *fs = ls->fs; + TString *varname; + Breaklabel bl; + enterbreak(fs, &bl); + next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname); break; + case ',': forlist(ls, varname); break; + default: luaK_error(ls, "`=' or `,' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leavebreak(fs, &bl); +} + + +static void test_then_block (LexState *ls, expdesc *v) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + next(ls); /* skip IF or ELSEIF */ + cond(ls, v); + check(ls, TK_THEN); + block(ls); /* `then' part */ +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + expdesc v; + int escapelist = NO_JUMP; + test_then_block(ls, &v); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); + test_then_block(ls, &v); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); + next(ls); /* skip ELSE */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, v.u.l.f); + luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {',' NAME} ['=' explist1] */ + int nvars = 0; + int nexps; + do { + next(ls); /* skip LOCAL or ',' */ + new_localvar(ls, str_checkname(ls), nvars++); + } while (ls->t.token == ','); + if (optional(ls, '=')) + nexps = explist1(ls); + else + nexps = 0; + adjust_mult_assign(ls, nvars, nexps); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME [':' NAME | '.' NAME] */ + int needself = 0; + singlevar(ls, str_checkname(ls), v); + if (ls->t.token == ':' || ls->t.token == '.') { + needself = (ls->t.token == ':'); + next(ls); + luaK_tostack(ls, v, 1); + luaK_kstr(ls, checkname(ls)); + v->k = VINDEXED; + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v; + next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, needself, line); + luaK_storevar(ls, &v); +} + + +static void namestat (LexState *ls) { + /* stat -> func | ['%'] NAME assignment */ + FuncState *fs = ls->fs; + expdesc v; + var_or_func(ls, &v); + if (v.k == VEXP) { /* stat -> func */ + check_condition(ls, luaK_lastisopen(fs), "syntax error"); /* an upvalue? */ + luaK_setcallreturns(fs, 0); /* call statement uses no results */ + } + else { /* stat -> ['%'] NAME assignment */ + int left = assignment(ls, &v, 1); + luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + next(ls); /* skip RETURN */ + if (!block_follow(ls->t.token)) + explist1(ls); /* optional return values */ + luaK_code1(fs, OP_RETURN, ls->fs->nactloc); + fs->stacklevel = fs->nactloc; /* removes all temp values */ +} + + +static void breakstat (LexState *ls) { + /* stat -> BREAK [NAME] */ + FuncState *fs = ls->fs; + int currentlevel = fs->stacklevel; + Breaklabel *bl = fs->bl; + if (!bl) + luaK_error(ls, "no loop to break"); + next(ls); /* skip BREAK */ + luaK_adjuststack(fs, currentlevel - bl->stacklevel); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); + /* correct stack for compiler and symbolic execution */ + luaK_adjuststack(fs, bl->stacklevel - currentlevel); +} + + +static int stat (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + localstat(ls); + return 0; + } + case TK_NAME: case '%': { /* stat -> namestat */ + namestat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + luaK_error(ls, " expected"); + return 0; /* to avoid warnings */ + } + } +} + + +static void parlist (LexState *ls) { + /* parlist -> [ param { ',' param } ] */ + int nparams = 0; + int dots = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_DOTS: next(ls); dots = 1; break; + case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; + default: luaK_error(ls, " or `...' expected"); + } + } while (!dots && optional(ls, ',')); + } + code_params(ls, nparams, dots); +} + + +static void body (LexState *ls, int needself, int line) { + /* body -> '(' parlist ')' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->lineDefined = line; + check(ls, '('); + if (needself) { + new_localvarstr(ls, "self", 0); + adjustlocalvars(ls, 1); + } + parlist(ls); + check(ls, ')'); + chunk(ls); + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs); +} + + +/* }====================================================================== */ + + +static void chunk (LexState *ls) { + /* chunk -> { stat [';'] } */ + int islast = 0; + while (!islast && !block_follow(ls->t.token)) { + islast = stat(ls); + optional(ls, ';'); + LUA_ASSERT(ls->fs->stacklevel == ls->fs->nactloc, + "stack size != # local vars"); + } +} + diff --git a/liblua/lparser.h b/liblua/lparser.h new file mode 100644 index 0000000..445acea --- /dev/null +++ b/liblua/lparser.h @@ -0,0 +1,60 @@ +/* +** $Id: lparser.h,v 1.26 2000/10/09 13:47:46 roberto Exp $ +** LL(1) Parser and code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VGLOBAL, + VLOCAL, + VINDEXED, + VEXP +} expkind; + +typedef struct expdesc { + expkind k; + union { + int index; /* VGLOBAL: `kstr' index of global name; VLOCAL: stack index */ + struct { + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ + } l; + } u; +} expdesc; + + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + int pc; /* next position to code */ + int lasttarget; /* `pc' of last `jump target' */ + int jlt; /* list of jumps to `lasttarget' */ + short stacklevel; /* number of values on activation register */ + short nactloc; /* number of active local variables */ + short nupvalues; /* number of upvalues */ + int lastline; /* line where last `lineinfo' was generated */ + struct Breaklabel *bl; /* chain of breakable blocks */ + expdesc upvalues[MAXUPVALUES]; /* upvalues */ + int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */ +} FuncState; + + +Proto *luaY_parser (lua_State *L, ZIO *z); + + +#endif diff --git a/liblua/lstate.cpp b/liblua/lstate.cpp new file mode 100644 index 0000000..1f0242d --- /dev/null +++ b/liblua/lstate.cpp @@ -0,0 +1,136 @@ +/* +** $Id: lstate.c,v 1.48 2000/10/30 16:29:59 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#ifdef LUA_DEBUG +static lua_State *lua_state = NULL; +void luaB_opentests (lua_State *L); +#endif + +extern TObject luaO_nilobject; + +//luaO_nilobject.ttype = 1; +//luaO_nilobject.Value = {NULL}; +/* +** built-in implementation for ERRORMESSAGE. In a "correct" environment +** ERRORMESSAGE should have an external definition, and so this function +** would not be used. +*/ +static int errormessage (lua_State *L) { + const char *s = lua_tostring(L, 1); + if (s == NULL) s = "(no message)"; + fprintf(stderr, "error: %s\n", s); + return 0; +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + luaO_nilobject.ttype = LUA_TNIL; +// luaO_nilobject.value = NULL; + + int stacksize = *(int *)ud; + if (stacksize == 0) + stacksize = DEFAULT_STACK_SIZE; + else + stacksize += LUA_MINSTACK; + L->gt = luaH_new(L, 10); /* table of globals */ + luaD_init(L, stacksize); + luaS_init(L); + luaX_init(L); + luaT_init(L); + lua_newtable(L); + lua_ref(L, 1); /* create registry */ + lua_register(L, LUA_ERRORMESSAGE, errormessage); +#ifdef LUA_DEBUG + luaB_opentests(L); + if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ +#endif + LUA_ASSERT(lua_gettop(L) == 0, "wrong API stack"); +} + + +LUA_API lua_State *lua_open (int stacksize) { + + + + + lua_State *L = luaM_new(NULL, lua_State); + + + if (L == NULL) return NULL; /* memory allocation error */ + L->stack = NULL; + L->strt.size = L->udt.size = 0; + L->strt.nuse = L->udt.nuse = 0; + L->strt.hash = NULL; + L->udt.hash = NULL; + L->Mbuffer = NULL; + L->Mbuffsize = 0; + L->rootproto = NULL; + L->rootcl = NULL; + L->roottable = NULL; + L->TMtable = NULL; + L->last_tag = -1; + L->refArray = NULL; + L->refSize = 0; + L->refFree = NONEXT; + L->nblocks = sizeof(lua_State); + L->GCthreshold = MAX_INT; /* to avoid GC during pre-definitions */ + L->callhook = NULL; + L->linehook = NULL; + L->allowhooks = 1; + L->errorJmp = NULL; + if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) { + /* memory allocation error: free partial state */ + lua_close(L); + return NULL; + } + L->GCthreshold = 2*L->nblocks; + + + + return L; +} + + +LUA_API void lua_close (lua_State *L) { + LUA_ASSERT(L != lua_state || lua_gettop(L) == 0, "garbage in C stack"); + luaC_collect(L, 1); /* collect all elements */ + LUA_ASSERT(L->rootproto == NULL, "list should be empty"); + LUA_ASSERT(L->rootcl == NULL, "list should be empty"); + LUA_ASSERT(L->roottable == NULL, "list should be empty"); + luaS_freeall(L); + if (L->stack) + L->nblocks -= (L->stack_last - L->stack + 1)*sizeof(TObject); + luaM_free(L, L->stack); + L->nblocks -= (L->last_tag+1)*sizeof(struct TM); + luaM_free(L, L->TMtable); + L->nblocks -= (L->refSize)*sizeof(struct Ref); + luaM_free(L, L->refArray); + L->nblocks -= (L->Mbuffsize)*sizeof(char); + luaM_free(L, L->Mbuffer); + LUA_ASSERT(L->nblocks == sizeof(lua_State), "wrong count for nblocks"); + luaM_free(L, L); + LUA_ASSERT(L != lua_state || memdebug_numblocks == 0, "memory leak!"); + LUA_ASSERT(L != lua_state || memdebug_total == 0,"memory leak!"); +} + diff --git a/liblua/lstate.h b/liblua/lstate.h new file mode 100644 index 0000000..0c8f552 --- /dev/null +++ b/liblua/lstate.h @@ -0,0 +1,77 @@ +/* +** $Id: lstate.h,v 1.41 2000/10/05 13:00:17 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lobject.h" +#include "lua.h" +#include "luadebug.h" + + + +typedef TObject *StkId; /* index to stack elements */ + + +/* +** marks for Reference array +*/ +#define NONEXT -1 /* to end the free list */ +#define HOLD -2 +#define COLLECTED -3 +#define LOCK -4 + + +struct Ref { + TObject o; + int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */ +}; + + +struct lua_longjmp; /* defined in ldo.c */ +struct TM; /* defined in ltm.h */ + + +typedef struct stringtable { + int size; + lint32 nuse; /* number of elements */ + TString **hash; +} stringtable; + + + +struct lua_State { + /* thread-specific state */ + StkId top; /* first free slot in the stack */ + StkId stack; /* stack base */ + StkId stack_last; /* last free slot in the stack */ + int stacksize; + StkId Cbase; /* base for current C function */ + struct lua_longjmp *errorJmp; /* current error recover point */ + char *Mbuffer; /* global buffer */ + size_t Mbuffsize; /* size of Mbuffer */ + /* global state */ + Proto *rootproto; /* list of all prototypes */ + Closure *rootcl; /* list of all closures */ + Hash *roottable; /* list of all tables */ + stringtable strt; /* hash table for strings */ + stringtable udt; /* hash table for udata */ + Hash *gt; /* table for globals */ + struct TM *TMtable; /* table for tag methods */ + int last_tag; /* last used tag in TMtable */ + struct Ref *refArray; /* locked objects */ + int refSize; /* size of refArray */ + int refFree; /* list of free positions in refArray */ + unsigned long GCthreshold; + unsigned long nblocks; /* number of `bytes' currently allocated */ + lua_Hook callhook; + lua_Hook linehook; + int allowhooks; +}; + + +#endif + diff --git a/liblua/lstring.cpp b/liblua/lstring.cpp new file mode 100644 index 0000000..e4c7e26 --- /dev/null +++ b/liblua/lstring.cpp @@ -0,0 +1,155 @@ +/* +** $Id: lstring.c,v 1.45 2000/10/30 17:49:19 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + +/* +** type equivalent to TString, but with maximum alignment requirements +*/ +union L_UTString { + TString ts; + union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ +}; + + + +void luaS_init (lua_State *L) { + L->strt.hash = luaM_newvector(L, 1, TString *); + L->udt.hash = luaM_newvector(L, 1, TString *); + L->nblocks += 2*sizeof(TString *); + L->strt.size = L->udt.size = 1; + L->strt.nuse = L->udt.nuse = 0; + L->strt.hash[0] = L->udt.hash[0] = NULL; +} + + +void luaS_freeall (lua_State *L) { + LUA_ASSERT(L->strt.nuse==0, "non-empty string table"); + L->nblocks -= (L->strt.size + L->udt.size)*sizeof(TString *); + luaM_free(L, L->strt.hash); + LUA_ASSERT(L->udt.nuse==0, "non-empty udata table"); + luaM_free(L, L->udt.hash); +} + + +static unsigned long hash_s (const char *s, size_t l) { + unsigned long h = l; /* seed */ + size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ + for (; l>=step; l-=step) + h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++)); + return h; +} + + +void luaS_resize (lua_State *L, stringtable *tb, int newsize) { + TString **newhash = luaM_newvector(L, newsize, TString *); + int i; + for (i=0; isize; i++) { + TString *p = tb->hash[i]; + while (p) { /* for each node in the list */ + TString *next = p->nexthash; /* save next */ + unsigned long h = (tb == &L->strt) ? p->u.s.hash : IntPoint(p->u.d.value); + int h1 = h&(newsize-1); /* new position */ + LUA_ASSERT(h%newsize == (h&(newsize-1)), + "a&(x-1) == a%x, for x power of 2"); + p->nexthash = newhash[h1]; /* chain it in new position */ + newhash[h1] = p; + p = next; + } + } + luaM_free(L, tb->hash); + L->nblocks += (newsize - tb->size)*sizeof(TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { + ts->nexthash = tb->hash[h]; /* chain new entry */ + tb->hash[h] = ts; + tb->nuse++; + if (tb->nuse > (lint32)tb->size && tb->size < MAX_INT/2) /* too crowded? */ + luaS_resize(L, tb, tb->size*2); +} + + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + unsigned long h = hash_s(str, l); + int h1 = h & (L->strt.size-1); + TString *ts; + for (ts = L->strt.hash[h1]; ts; ts = ts->nexthash) { + if (ts->len == l && (memcmp(str, ts->str, l) == 0)) + return ts; + } + /* not found */ + ts = (TString *)luaM_malloc(L, sizestring(l)); + ts->marked = 0; + ts->nexthash = NULL; + ts->len = l; + ts->u.s.hash = h; + ts->u.s.constindex = 0; + memcpy(ts->str, str, l); + ts->str[l] = 0; /* ending 0 */ + L->nblocks += sizestring(l); + newentry(L, &L->strt, ts, h1); /* insert it on table */ + return ts; +} + + +TString *luaS_newudata (lua_State *L, size_t s, void *udata) { + union L_UTString *uts = (union L_UTString *)luaM_malloc(L, + (lint32)sizeof(union L_UTString)+s); + TString *ts = &uts->ts; + ts->marked = 0; + ts->nexthash = NULL; + ts->len = s; + ts->u.d.tag = 0; + ts->u.d.value = (udata == NULL) ? uts+1 : udata; + L->nblocks += sizestring(s); + /* insert it on table */ + newentry(L, &L->udt, ts, IntPoint(ts->u.d.value) & (L->udt.size-1)); + return ts; +} + + +TString *luaS_createudata (lua_State *L, void *udata, int tag) { + int h1 = IntPoint(udata) & (L->udt.size-1); + TString *ts; + for (ts = L->udt.hash[h1]; ts; ts = ts->nexthash) { + if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) + return ts; + } + /* not found */ + ts = luaS_newudata(L, 0, udata); + if (tag != LUA_ANYTAG) + ts->u.d.tag = tag; + return ts; +} + + +TString *luaS_new (lua_State *L, const char *str) { + return luaS_newlstr(L, str, strlen(str)); +} + + +TString *luaS_newfixed (lua_State *L, const char *str) { + TString *ts = luaS_new(L, str); + if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ + return ts; +} + diff --git a/liblua/lstring.h b/liblua/lstring.h new file mode 100644 index 0000000..67ede68 --- /dev/null +++ b/liblua/lstring.h @@ -0,0 +1,37 @@ +/* +** $Id: lstring.h,v 1.24 2000/10/30 17:49:19 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lobject.h" +#include "lstate.h" + + +/* +** any TString with mark>=FIXMARK is never collected. +** Marks>=RESERVEDMARK are used to identify reserved words. +*/ +#define FIXMARK 2 +#define RESERVEDMARK 3 + + +#define sizestring(l) ((long)sizeof(TString) + \ + ((long)(l+1)-TSPACK)*(long)sizeof(char)) + + +void luaS_init (lua_State *L); +void luaS_resize (lua_State *L, stringtable *tb, int newsize); +TString *luaS_newudata (lua_State *L, size_t s, void *udata); +TString *luaS_createudata (lua_State *L, void *udata, int tag); +void luaS_freeall (lua_State *L); +TString *luaS_newlstr (lua_State *L, const char *str, size_t l); +TString *luaS_new (lua_State *L, const char *str); +TString *luaS_newfixed (lua_State *L, const char *str); + + +#endif diff --git a/liblua/lstrlib.cpp b/liblua/lstrlib.cpp new file mode 100644 index 0000000..2d3f1d5 --- /dev/null +++ b/liblua/lstrlib.cpp @@ -0,0 +1,632 @@ +/* +** $Id: lstrlib.c,v 1.56 2000/10/27 16:15:53 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static int str_len (lua_State *L) { + size_t l; + luaL_check_lstr(L, 1, &l); + lua_pushnumber(L, CComplex(l,0)); + return 1; +} + + +static long posrelat (long pos, size_t len) { + /* relative string position: negative means back from end */ + return (pos>=0) ? pos : (long)len+pos+1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_check_lstr(L, 1, &l); + long start = posrelat(luaL_check_long(L, 2), l); + long end = posrelat(luaL_opt_long(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (long)l) end = l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushstring(L, ""); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_check_lstr(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_check_lstr(L, 1, &l); + long pos = posrelat(luaL_opt_long(L, 2, 1), l); + luaL_arg_check(L, 0level && cap->capture[l].len != -1)) + lua_error(L, "invalid capture index"); + return l; +} + + +static int capture_to_close (lua_State *L, struct Capture *cap) { + int level = cap->level; + for (level--; level>=0; level--) + if (cap->capture[level].len == -1) return level; + lua_error(L, "invalid pattern capture"); + return 0; /* to avoid warnings */ +} + + +const char *luaI_classend (lua_State *L, const char *p) { + switch (*p++) { + case ESC: + if (*p == '\0') lua_error(L, "malformed pattern (ends with `%')"); + return p+1; + case '[': + if (*p == '^') p++; + do { /* look for a ']' */ + if (*p == '\0') lua_error(L, "malformed pattern (missing `]')"); + if (*(p++) == ESC && *p != '\0') p++; /* skip escapes (e.g. '%]') */ + } while (*p != ']'); + return p+1; + default: + return p; + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == '\0'); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + + +static int matchbracketclass (int c, const char *p, const char *endclass) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the '^' */ + } + while (++p < endclass) { + if (*p == ESC) { + p++; + if (match_class(c, (unsigned char)*p)) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < endclass)) { + p+=2; + if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p) + return sig; + } + else if ((int)(unsigned char)*p == c) return sig; + } + return !sig; +} + + + +int luaI_singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': /* matches any char */ + return 1; + case ESC: + return match_class(c, (unsigned char)*(p+1)); + case '[': + return matchbracketclass(c, p, ep-1); + default: + return ((unsigned char)*p == c); + } +} + + +static const char *match (lua_State *L, const char *s, const char *p, + struct Capture *cap); + + +static const char *matchbalance (lua_State *L, const char *s, const char *p, + struct Capture *cap) { + if (*p == 0 || *(p+1) == 0) + lua_error(L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < cap->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (lua_State *L, const char *s, const char *p, + const char *ep, struct Capture *cap) { + long i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && luaI_singlematch((unsigned char)*(s+i), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(L, (s+i), ep+1, cap); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (lua_State *L, const char *s, const char *p, + const char *ep, struct Capture *cap) { + for (;;) { + const char *res = match(L, s, ep+1, cap); + if (res != NULL) + return res; + else if (ssrc_end && luaI_singlematch((unsigned char)*s, p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (lua_State *L, const char *s, const char *p, + struct Capture *cap) { + const char *res; + int level = cap->level; + if (level >= MAX_CAPTURES) lua_error(L, "too many captures"); + cap->capture[level].init = s; + cap->capture[level].len = -1; + cap->level = level+1; + if ((res=match(L, s, p+1, cap)) == NULL) /* match failed? */ + cap->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (lua_State *L, const char *s, const char *p, + struct Capture *cap) { + int l = capture_to_close(L, cap); + const char *res; + cap->capture[l].len = s - cap->capture[l].init; /* close capture */ + if ((res = match(L, s, p+1, cap)) == NULL) /* match failed? */ + cap->capture[l].len = -1; /* undo capture */ + return res; +} + + +static const char *match_capture (lua_State *L, const char *s, int level, + struct Capture *cap) { + int l = check_capture(L, level, cap); + size_t len = cap->capture[l].len; + if ((size_t)(cap->src_end-s) >= len && + memcmp(cap->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (lua_State *L, const char *s, const char *p, + struct Capture *cap) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': /* start capture */ + return start_capture(L, s, p, cap); + case ')': /* end capture */ + return end_capture(L, s, p, cap); + case ESC: /* may be %[0-9] or %b */ + if (isdigit((unsigned char)(*(p+1)))) { /* capture? */ + s = match_capture(L, s, *(p+1), cap); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(L, s, p+2, cap) */ + } + else if (*(p+1) == 'b') { /* balanced string? */ + s = matchbalance(L, s, p+2, cap); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(L, s, p+4, cap); */ + } + else goto dflt; /* case default */ + case '\0': /* end of pattern */ + return s; /* match succeeded */ + case '$': + if (*(p+1) == '\0') /* is the '$' the last char in pattern? */ + return (s == cap->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + default: dflt: { /* it is a pattern item */ + const char *ep = luaI_classend(L, p); /* points to what is next */ + int m = ssrc_end && luaI_singlematch((unsigned char)*s, p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(L, s+1, ep+1, cap)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(L, s, ep+1, cap); */ + } + case '*': /* 0 or more repetitions */ + return max_expand(L, s, p, ep, cap); + case '+': /* 1 or more repetitions */ + return (m ? max_expand(L, s+1, p, ep, cap) : NULL); + case '-': /* 0 or more repetitions (minimum) */ + return min_expand(L, s, p, ep, cap); + default: + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(L, s+1, ep, cap); */ + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static int push_captures (lua_State *L, struct Capture *cap) { + int i; + luaL_checkstack(L, cap->level, "too many captures"); + for (i=0; ilevel; i++) { + int l = cap->capture[i].len; + if (l == -1) lua_error(L, "unfinished capture"); + lua_pushlstring(L, cap->capture[i].init, l); + } + return cap->level; /* number of strings pushed */ +} + + +static int str_find (lua_State *L) { + size_t l1, l2; + const char *s = luaL_check_lstr(L, 1, &l1); + const char *p = luaL_check_lstr(L, 2, &l2); + long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1; + struct Capture cap; + luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range"); + if (lua_gettop(L) > 3 || /* extra argument? */ + strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushnumber(L, CComplex(s2-s+1,0)); + lua_pushnumber(L, CComplex(s2-s+l2,0)); + return 2; + } + } + else { + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + cap.src_end = s+l1; + do { + const char *res; + cap.level = 0; + if ((res=match(L, s1, p, &cap)) != NULL) { + lua_pushnumber(L, s1-s+1); /* start */ + lua_pushnumber(L, res-s); /* end */ + return push_captures(L, &cap) + 2; + } + } while (s1++capture[level].init, cap->capture[level].len); + } + } + } + } + else { /* is a function */ + int n; + lua_pushvalue(L, 3); + n = push_captures(L, cap); + lua_rawcall(L, n, 1); + if (lua_isstring(L, -1)) + luaL_addvalue(b); /* add return to accumulated result */ + else + lua_pop(L, 1); /* function result is not a string: pop it */ + } +} + + +static int str_gsub (lua_State *L) { + size_t srcl; + const char *src = luaL_check_lstr(L, 1, &srcl); + const char *p = luaL_check_string(L, 2); + int max_s = luaL_opt_int(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + struct Capture cap; + luaL_Buffer b; + luaL_arg_check(L, + lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), + 3, "string or function expected"); + luaL_buffinit(L, &b); + cap.src_end = src+srcl; + while (n < max_s) { + const char *e; + cap.level = 0; + e = match(L, src, p, &cap); + if (e) { + n++; + add_s(L, &b, &cap); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < cap.src_end) + luaL_putchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, cap.src_end-src); + luaL_pushresult(&b); + lua_pushnumber(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_check_lstr(L, arg, &l); + luaL_putchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': + luaL_putchar(b, '\\'); + luaL_putchar(b, *s); + break; + case '\0': luaL_addlstring(b, "\\000", 4); break; + default: luaL_putchar(b, *s); + } + s++; + } + luaL_putchar(b, '"'); +} + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* maximum size of each format specification (such as '%-099.99d') */ +#define MAX_FORMAT 20 + +static int str_format (lua_State *L) { + int arg = 1; + const char *strfrmt = luaL_check_string(L, arg); + luaL_Buffer b; + luaL_buffinit(L, &b); + + while (*strfrmt) { + if (*strfrmt != '%') + luaL_putchar(&b, *strfrmt++); + else if (*++strfrmt == '%') + luaL_putchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + CComplex q; + struct Capture cap; + char form[MAX_FORMAT]; /* to store the format ('%...') */ + char complexForm[3*MAX_FORMAT]; + char buff[MAX_ITEM]; /* to store the formatted item */ + const char *initf = strfrmt; + form[0] = '%'; + if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { + arg = *initf - '0'; + initf += 2; /* skip the 'n$' */ + } + arg++; + cap.src_end = strfrmt+strlen(strfrmt)+1; + cap.level = 0; + strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap); + if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */ + strfrmt-initf > MAX_FORMAT-2) + lua_error(L, "invalid format (width or precision too long)"); + strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ + form[strfrmt-initf+2] = 0; + switch (*strfrmt++) { + case 'c': case 'd': case 'i': + sprintf(buff, form, luaL_check_int(L, arg)); + break; + case 'o': case 'u': case 'x': case 'X': + sprintf(buff, form, (unsigned int) Re(luaL_check_number(L, arg))); + break; + case 'e': case 'E': case 'f': case 'g': case 'G': + q=luaL_check_number(L, arg); + if (Im(q)==0) sprintf(buff, form, Re(q)); + else + { + if(Im(q)>0) sprintf(complexForm,"%s+I*%s",form,form); + else sprintf(complexForm,"%s-I*%s",form,form); + sprintf(buff, complexForm, Re(q), fabs(Im(q))); + } + break; + case 'q': + luaI_addquoted(L, &b, arg); + continue; /* skip the "addsize" at the end */ + case 's': { + size_t l; + const char *s = luaL_check_lstr(L, arg, &l); + if (cap.capture[1].len == 0 && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the "addsize" at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: /* also treat cases 'pnLlh' */ + lua_error(L, "invalid option in `format'"); + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const struct luaL_reg strlib[] = { +{"strlen", str_len}, +{"strsub", str_sub}, +{"strlower", str_lower}, +{"strupper", str_upper}, +{"strchar", str_char}, +{"strrep", str_rep}, +{"ascii", str_byte}, /* for compatibility with 3.0 and earlier */ +{"strbyte", str_byte}, +{"format", str_format}, +{"strfind", str_find}, +{"gsub", str_gsub} +}; + + +/* +** Open string library +*/ +LUALIB_API void lua_strlibopen (lua_State *L) { + luaL_openl(L, strlib); +} diff --git a/liblua/ltable.cpp b/liblua/ltable.cpp new file mode 100644 index 0000000..8bde5d0 --- /dev/null +++ b/liblua/ltable.cpp @@ -0,0 +1,303 @@ +/* +** $Id: ltable.c,v 1.58 2000/10/26 12:47:05 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables); +** uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** In other words, there are collisions only when two elements have the +** same main position (i.e. the same hash values for that table size). +** Because of that, the load factor of these tables can be 100% without +** performance penalties. +*/ + + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + +#define gcsize(L, n) (sizeof(Hash)+(n)*sizeof(Node)) + + + +#define TagDefault LUA_TTABLE + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +Node *luaH_mainposition (const Hash *t, const TObject *key) { + unsigned long h; + switch (ttype(key)) { + case LUA_TNUMBER: + h = (unsigned long)(long)Re(nvalue(key)); + break; + case LUA_TSTRING: + h = tsvalue(key)->u.s.hash; + break; + case LUA_TUSERDATA: + h = IntPoint(tsvalue(key)); + break; + case LUA_TTABLE: + h = IntPoint(hvalue(key)); + break; + case LUA_TFUNCTION: + h = IntPoint(clvalue(key)); + break; + default: + return NULL; /* invalid key */ + } + LUA_ASSERT(h%(unsigned int)t->size == (h&((unsigned int)t->size-1)), + "a&(x-1) == a%x, for x power of 2"); + return &t->node[h&(t->size-1)]; +} + + +static const TObject *luaH_getany (lua_State *L, const Hash *t, + const TObject *key) { + Node *n = luaH_mainposition(t, key); + if (!n) + lua_error(L, "table index is nil"); + else do { + if (luaO_equalObj(key, &n->key)) + return &n->val; + n = n->next; + } while (n); + return &luaO_nilobject; /* key not found */ +} + + +/* specialized version for numbers */ +const TObject *luaH_getnum (const Hash *t, Number key) { + Node *n = &t->node[(unsigned long)(long)Re(key)&(t->size-1)]; + do { + if (ttype(&n->key) == LUA_TNUMBER && nvalue(&n->key) == key) + return &n->val; + n = n->next; + } while (n); + return &luaO_nilobject; /* key not found */ +} + + +/* specialized version for strings */ +const TObject *luaH_getstr (const Hash *t, TString *key) { + Node *n = &t->node[key->u.s.hash&(t->size-1)]; + do { + if (ttype(&n->key) == LUA_TSTRING && tsvalue(&n->key) == key) + return &n->val; + n = n->next; + } while (n); + return &luaO_nilobject; /* key not found */ +} + + +const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { + switch (ttype(key)) { + case LUA_TNUMBER: return luaH_getnum(t, nvalue(key)); + case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); + default: return luaH_getany(L, t, key); + } +} + + +Node *luaH_next (lua_State *L, const Hash *t, const TObject *key) { + int i; + if (ttype(key) == LUA_TNIL) + i = 0; /* first iteration */ + else { + const TObject *v = luaH_get(L, t, key); + if (v == &luaO_nilobject) + lua_error(L, "invalid key for `next'"); + i = (int)(((const char *)v - + (const char *)(&t->node[0].val)) / sizeof(Node)) + 1; + } + for (; isize; i++) { + Node *n = node(t, i); + if (ttype(val(n)) != LUA_TNIL) + return n; + } + return NULL; /* no more elements */ +} + + +/* +** try to remove a key without value from a table. To avoid problems with +** hash, change `key' for a number with the same hash. +*/ +void luaH_remove (Hash *t, TObject *key) { + if (ttype(key) == LUA_TNUMBER || + (ttype(key) == LUA_TSTRING && tsvalue(key)->len <= 30)) + return; /* do not remove numbers nor small strings */ + else { + /* try to find a number `n' with the same hash as `key' */ + Node *mp = luaH_mainposition(t, key); + int n = mp - &t->node[0]; + /* make sure `n' is not in `t' */ + while (luaH_getnum(t, n) != &luaO_nilobject) { + if (n >= MAX_INT - t->size) + return; /* give up; (to avoid overflow) */ + n += t->size; + } + ttype(key) = LUA_TNUMBER; + nvalue(key) = n; + LUA_ASSERT(luaH_mainposition(t, key) == mp, "cannot change hash"); + } +} + + +static void setnodevector (lua_State *L, Hash *t, lint32 size) { + int i; + if (size > MAX_INT) + lua_error(L, "table overflow"); + t->node = luaM_newvector(L, size, Node); + for (i=0; i<(int)size; i++) { + ttype(&t->node[i].key) = ttype(&t->node[i].val) = LUA_TNIL; + t->node[i].next = NULL; + } + L->nblocks += gcsize(L, size) - gcsize(L, t->size); + t->size = size; + t->firstfree = &t->node[size-1]; /* first free position to be used */ +} + + +Hash *luaH_new (lua_State *L, int size) { + Hash *t = luaM_new(L, Hash); + t->htag = TagDefault; + t->next = L->roottable; + L->roottable = t; + t->mark = t; + t->size = 0; + L->nblocks += gcsize(L, 0); + t->node = NULL; + setnodevector(L, t, luaO_power2(size)); + return t; +} + + +void luaH_free (lua_State *L, Hash *t) { + L->nblocks -= gcsize(L, t->size); + luaM_free(L, t->node); + luaM_free(L, t); +} + + +static int numuse (const Hash *t) { + Node *v = t->node; + int size = t->size; + int realuse = 0; + int i; + for (i=0; isize; + Node *nold = t->node; + int nelems = numuse(t); + int i; + LUA_ASSERT(nelems<=oldsize, "wrong count"); + if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */ + setnodevector(L, t, (lint32)oldsize*2); + else if (nelems <= oldsize/4 && /* less than 1/4? */ + oldsize > MINPOWER2) + setnodevector(L, t, oldsize/2); + else + setnodevector(L, t, oldsize); + for (i=0; ival) != LUA_TNIL) + *luaH_set(L, t, &old->key) = old->val; + } + luaM_free(L, nold); /* free old array */ +} + + +/* +** inserts a key into a hash table; first, check whether key is +** already present; if not, check whether key's main position is free; +** if not, check whether colliding node is in its main position or not; +** if it is not, move colliding node to an empty place and put new key +** in its main position; otherwise (colliding node is in its main position), +** new key goes to an empty position. +*/ +TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { + Node *mp = luaH_mainposition(t, key); + Node *n = mp; + if (!mp) + lua_error(L, "table index is nil"); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_equalObj(key, &n->key)) + return &n->val; /* that's all */ + else n = n->next; + } while (n); + /* `key' not found; must insert it */ + if (ttype(&mp->key) != LUA_TNIL) { /* main position is not free? */ + Node *othern; /* main position of colliding node */ + n = t->firstfree; /* get a free place */ + /* is colliding node out of its main position? (can only happens if + its position is after "firstfree") */ + if (mp > n && (othern=luaH_mainposition(t, &mp->key)) != mp) { + /* yes; move colliding node into free position */ + while (othern->next != mp) othern = othern->next; /* find previous */ + othern->next = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + mp->next = NULL; /* now `mp' is free */ + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + mp->key = *key; + for (;;) { /* correct `firstfree' */ + if (ttype(&t->firstfree->key) == LUA_TNIL) + return &mp->val; /* OK; table still has a free place */ + else if (t->firstfree == t->node) break; /* cannot decrement from here */ + else (t->firstfree)--; + } + rehash(L, t); /* no more free places */ + return luaH_set(L, t, key); /* `rehash' invalidates this insertion */ +} + + +TObject *luaH_setint (lua_State *L, Hash *t, int key) { + TObject index; + ttype(&index) = LUA_TNUMBER; + nvalue(&index) = key; + return luaH_set(L, t, &index); +} + + +void luaH_setstrnum (lua_State *L, Hash *t, TString *key, Number val) { + TObject *value, index; + ttype(&index) = LUA_TSTRING; + tsvalue(&index) = key; + value = luaH_set(L, t, &index); + ttype(value) = LUA_TNUMBER; + nvalue(value) = val; +} + + +const TObject *luaH_getglobal (lua_State *L, const char *name) { + return luaH_getstr(L->gt, luaS_new(L, name)); +} + diff --git a/liblua/ltable.h b/liblua/ltable.h new file mode 100644 index 0000000..8ee41a8 --- /dev/null +++ b/liblua/ltable.h @@ -0,0 +1,34 @@ +/* +** $Id: ltable.h,v 1.24 2000/08/31 14:08:27 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define node(t,i) (&(t)->node[i]) +#define key(n) (&(n)->key) +#define val(n) (&(n)->val) + +Hash *luaH_new (lua_State *L, int nhash); +void luaH_free (lua_State *L, Hash *t); +const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key); +const TObject *luaH_getnum (const Hash *t, Number key); +const TObject *luaH_getstr (const Hash *t, TString *key); +void luaH_remove (Hash *t, TObject *key); +TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); +Node * luaH_next (lua_State *L, const Hash *t, const TObject *r); +TObject *luaH_setint (lua_State *L, Hash *t, int key); +void luaH_setstrnum (lua_State *L, Hash *t, TString *key, Number val); +unsigned long luaH_hash (lua_State *L, const TObject *key); +const TObject *luaH_getglobal (lua_State *L, const char *name); + +/* exported only for debugging */ +Node *luaH_mainposition (const Hash *t, const TObject *key); + + +#endif diff --git a/liblua/ltests.cpp b/liblua/ltests.cpp new file mode 100644 index 0000000..c27c7c8 --- /dev/null +++ b/liblua/ltests.cpp @@ -0,0 +1,543 @@ +/* +** $Id: ltests.c,v 1.54 2000/10/31 13:10:24 roberto Exp $ +** Internal Module for Debugging of the Lua Implementation +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + + +#include "lua.h" + +#include "lapi.h" +#include "lauxlib.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "luadebug.h" +#include "lualib.h" + + +void luaB_opentests (lua_State *L); + + +/* +** The whole module only makes sense with LUA_DEBUG on +*/ +#ifdef LUA_DEBUG + + + +static void setnameval (lua_State *L, const char *name, int val) { + lua_pushstring(L, name); + lua_pushnumber(L, val); + lua_settable(L, -3); +} + + +/* +** {====================================================== +** Disassembler +** ======================================================= +*/ + + +static const char *const instrname[NUM_OPCODES] = { + "END", "RETURN", "CALL", "TAILCALL", "PUSHNIL", "POP", "PUSHINT", + "PUSHSTRING", "PUSHNUM", "PUSHNEGNUM", "PUSHUPVALUE", "GETLOCAL", + "GETGLOBAL", "GETTABLE", "GETDOTTED", "GETINDEXED", "PUSHSELF", + "CREATETABLE", "SETLOCAL", "SETGLOBAL", "SETTABLE", "SETLIST", "SETMAP", + "ADD", "ADDI", "SUB", "MULT", "DIV", "POW", "CONCAT", "MINUS", "NOT", + "JMPNE", "JMPEQ", "JMPLT", "JMPLE", "JMPGT", "JMPGE", "JMPT", "JMPF", + "JMPONT", "JMPONF", "JMP", "PUSHNILJMP", "FORPREP", "FORLOOP", "LFORPREP", + "LFORLOOP", "CLOSURE" +}; + + +static int pushop (lua_State *L, Proto *p, int pc) { + char buff[100]; + Instruction i = p->code[pc]; + OpCode o = GET_OPCODE(i); + const char *name = instrname[o]; + sprintf(buff, "%5d - ", luaG_getline(p->lineinfo, pc, 1, NULL)); + switch ((enum Mode)luaK_opproperties[o].mode) { + case iO: + sprintf(buff+8, "%-12s", name); + break; + case iU: + sprintf(buff+8, "%-12s%4u", name, GETARG_U(i)); + break; + case iS: + sprintf(buff+8, "%-12s%4d", name, GETARG_S(i)); + break; + case iAB: + sprintf(buff+8, "%-12s%4d %4d", name, GETARG_A(i), GETARG_B(i)); + break; + } + lua_pushstring(L, buff); + return (o != OP_END); +} + + +static int listcode (lua_State *L) { + int pc; + Proto *p; + int res; + luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(luaA_index(L, 1))->f.l; + lua_newtable(L); + setnameval(L, "maxstack", p->maxstacksize); + setnameval(L, "numparams", p->numparams); + pc = 0; + do { + lua_pushnumber(L, pc+1); + res = pushop(L, p, pc++); + lua_settable(L, -3); + } while (res); + return 1; +} + + +static int liststrings (lua_State *L) { + Proto *p; + int i; + luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(luaA_index(L, 1))->f.l; + lua_newtable(L); + for (i=0; inkstr; i++) { + lua_pushnumber(L, i+1); + lua_pushstring(L, p->kstr[i]->str); + lua_settable(L, -3); + } + return 1; +} + + +static int listlocals (lua_State *L) { + Proto *p; + int pc = luaL_check_int(L, 2) - 1; + int i = 0; + const char *name; + luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(luaA_index(L, 1))->f.l; + while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) + lua_pushstring(L, name); + return i-1; +} + +/* }====================================================== */ + + + +static int get_limits (lua_State *L) { + lua_newtable(L); + setnameval(L, "BITS_INT", BITS_INT); + setnameval(L, "LFPF", LFIELDS_PER_FLUSH); + setnameval(L, "MAXARG_A", MAXARG_A); + setnameval(L, "MAXARG_B", MAXARG_B); + setnameval(L, "MAXARG_S", MAXARG_S); + setnameval(L, "MAXARG_U", MAXARG_U); + setnameval(L, "MAXLOCALS", MAXLOCALS); + setnameval(L, "MAXPARAMS", MAXPARAMS); + setnameval(L, "MAXSTACK", MAXSTACK); + setnameval(L, "MAXUPVALUES", MAXUPVALUES); + setnameval(L, "MAXVARSLH", MAXVARSLH); + setnameval(L, "RFPF", RFIELDS_PER_FLUSH); + setnameval(L, "SIZE_A", SIZE_A); + setnameval(L, "SIZE_B", SIZE_B); + setnameval(L, "SIZE_OP", SIZE_OP); + setnameval(L, "SIZE_U", SIZE_U); + return 1; +} + + +static int mem_query (lua_State *L) { + if (lua_isnull(L, 1)) { + lua_pushnumber(L, memdebug_total); + lua_pushnumber(L, memdebug_numblocks); + lua_pushnumber(L, memdebug_maxmem); + return 3; + } + else { + memdebug_memlimit = luaL_check_int(L, 1); + return 0; + } +} + + +static int hash_query (lua_State *L) { + if (lua_isnull(L, 2)) { + luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected"); + lua_pushnumber(L, tsvalue(luaA_index(L, 1))->u.s.hash); + } + else { + Hash *t; + luaL_checktype(L, 2, LUA_TTABLE); + t = hvalue(luaA_index(L, 2)); + lua_pushnumber(L, luaH_mainposition(t, luaA_index(L, 1)) - t->node); + } + return 1; +} + + +static int table_query (lua_State *L) { + const Hash *t; + int i = luaL_opt_int(L, 2, -1); + luaL_checktype(L, 1, LUA_TTABLE); + t = hvalue(luaA_index(L, 1)); + if (i == -1) { + lua_pushnumber(L, t->size); + lua_pushnumber(L, t->firstfree - t->node); + return 2; + } + else if (i < t->size) { + luaA_pushobject(L, &t->node[i].key); + luaA_pushobject(L, &t->node[i].val); + if (t->node[i].next) { + lua_pushnumber(L, t->node[i].next - t->node); + return 3; + } + else + return 2; + } + return 0; +} + + +static int string_query (lua_State *L) { + stringtable *tb = (*luaL_check_string(L, 1) == 's') ? &L->strt : &L->udt; + int s = luaL_opt_int(L, 2, 0) - 1; + if (s==-1) { + lua_pushnumber(L ,tb->nuse); + lua_pushnumber(L ,tb->size); + return 2; + } + else if (s < tb->size) { + TString *ts; + int n = 0; + for (ts = tb->hash[s]; ts; ts = ts->nexthash) { + ttype(L->top) = LUA_TSTRING; + tsvalue(L->top) = ts; + incr_top; + n++; + } + return n; + } + return 0; +} + + +static int tref (lua_State *L) { + luaL_checkany(L, 1); + lua_pushvalue(L, 1); + lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1))); + return 1; +} + +static int getref (lua_State *L) { + if (lua_getref(L, luaL_check_int(L, 1))) + return 1; + else + return 0; +} + +static int unref (lua_State *L) { + lua_unref(L, luaL_check_int(L, 1)); + return 0; +} + +static int newuserdata (lua_State *L) { + if (lua_isnumber(L, 2)) + lua_pushusertag(L, (void *)luaL_check_int(L, 1), luaL_check_int(L, 2)); + else + lua_newuserdata(L, luaL_check_int(L, 1)); + return 1; +} + +static int udataval (lua_State *L) { + luaL_checktype(L, 1, LUA_TUSERDATA); + lua_pushnumber(L, (int)lua_touserdata(L, 1)); + return 1; +} + +static int newstate (lua_State *L) { + lua_State *L1 = lua_open(luaL_check_int(L, 1)); + if (L1) + lua_pushuserdata(L, L1); + else + lua_pushnil(L); + return 1; +} + +static int loadlib (lua_State *L) { + lua_State *L1 = (lua_State *)lua_touserdata(L, 1); + switch (*luaL_check_string(L, 2)) { + case 'm': lua_mathlibopen(L1); break; + case 's': lua_strlibopen(L1); break; + case 'i': lua_iolibopen(L1); break; + case 'd': lua_dblibopen(L1); break; + case 'b': lua_baselibopen(L1); break; + default: luaL_argerror(L, 2, "invalid option"); + } + return 0; +} + +static int closestate (lua_State *L) { + luaL_checktype(L, 1, LUA_TUSERDATA); + lua_close((lua_State *)lua_touserdata(L, 1)); + return 0; +} + +static int doremote (lua_State *L) { + lua_State *L1; + const char *code = luaL_check_string(L, 2); + int status; + luaL_checktype(L, 1, LUA_TUSERDATA); + L1 = (lua_State *)lua_touserdata(L, 1); + status = lua_dostring(L1, code); + if (status != 0) { + lua_pushnil(L); + lua_pushnumber(L, status); + return 2; + } + else { + int i = 0; + while (!lua_isnull(L1, ++i)) + lua_pushstring(L, lua_tostring(L1, i)); + return i-1; + } +} + +static int settagmethod (lua_State *L) { + int tag = luaL_check_int(L, 1); + const char *event = luaL_check_string(L, 2); + luaL_checkany(L, 3); + lua_gettagmethod(L, tag, event); + lua_pushvalue(L, 3); + lua_settagmethod(L, tag, event); + return 1; +} + +static int pushbool (lua_State *L, int b) { + if (b) lua_pushnumber(L, 1); + else lua_pushnil(L); + return 1; +} + +static int equal (lua_State *L) { + return pushbool(L, lua_equal(L, 1, 2)); +} + + + +/* +** {====================================================== +** function to test the API with C. It interprets a kind of "assembler" +** language with calls to the API, so the test can be driven by Lua code +** ======================================================= +*/ + +static const char *const delimits = " \t\n,;"; + +static void skip (const char **pc) { + while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; +} + +static int getnum (lua_State *L, const char **pc) { + int res = 0; + int sig = 1; + skip(pc); + if (**pc == '.') { + res = (int)lua_tonumber(L, -1); + lua_pop(L, 1); + (*pc)++; + return res; + } + else if (**pc == '-') { + sig = -1; + (*pc)++; + } + while (isdigit(**pc)) res = res*10 + (*(*pc)++) - '0'; + return sig*res; +} + +static const char *getname (char *buff, const char **pc) { + int i = 0; + skip(pc); + while (**pc != '\0' && !strchr(delimits, **pc)) + buff[i++] = *(*pc)++; + buff[i] = '\0'; + return buff; +} + + +#define EQ(s1) (strcmp(s1, inst) == 0) + +#define getnum ((getnum)(L, &pc)) +#define getname ((getname)(buff, &pc)) + + +static int testC (lua_State *L) { + char buff[30]; + const char *pc = luaL_check_string(L, 1); + for (;;) { + const char *inst = getname; + if EQ("") return 0; + else if EQ("isnumber") { + lua_pushnumber(L, lua_isnumber(L, getnum)); + } + else if EQ("isstring") { + lua_pushnumber(L, lua_isstring(L, getnum)); + } + else if EQ("istable") { + lua_pushnumber(L, lua_istable(L, getnum)); + } + else if EQ("iscfunction") { + lua_pushnumber(L, lua_iscfunction(L, getnum)); + } + else if EQ("isfunction") { + lua_pushnumber(L, lua_isfunction(L, getnum)); + } + else if EQ("isuserdata") { + lua_pushnumber(L, lua_isuserdata(L, getnum)); + } + else if EQ("isnil") { + lua_pushnumber(L, lua_isnil(L, getnum)); + } + else if EQ("isnull") { + lua_pushnumber(L, lua_isnull(L, getnum)); + } + else if EQ("tonumber") { + lua_pushnumber(L, lua_tonumber(L, getnum)); + } + else if EQ("tostring") { + lua_pushstring(L, lua_tostring(L, getnum)); + } + else if EQ("tonumber") { + lua_pushnumber(L, lua_tonumber(L, getnum)); + } + else if EQ("strlen") { + lua_pushnumber(L, lua_strlen(L, getnum)); + } + else if EQ("tocfunction") { + lua_pushcfunction(L, lua_tocfunction(L, getnum)); + } + else if EQ("return") { + return getnum; + } + else if EQ("gettop") { + lua_pushnumber(L, lua_gettop(L)); + } + else if EQ("settop") { + lua_settop(L, getnum); + } + else if EQ("pop") { + lua_pop(L, getnum); + } + else if EQ("pushnum") { + lua_pushnumber(L, getnum); + } + else if EQ("pushvalue") { + lua_pushvalue(L, getnum); + } + else if EQ("remove") { + lua_remove(L, getnum); + } + else if EQ("insert") { + lua_insert(L, getnum); + } + else if EQ("gettable") { + lua_gettable(L, getnum); + } + else if EQ("settable") { + lua_settable(L, getnum); + } + else if EQ("next") { + lua_next(L, -2); + } + else if EQ("concat") { + lua_concat(L, getnum); + } + else if EQ("rawcall") { + int narg = getnum; + int nres = getnum; + lua_rawcall(L, narg, nres); + } + else if EQ("call") { + int narg = getnum; + int nres = getnum; + lua_call(L, narg, nres); + } + else if EQ("dostring") { + lua_dostring(L, luaL_check_string(L, getnum)); + } + else if EQ("settagmethod") { + int tag = getnum; + const char *event = getname; + lua_settagmethod(L, tag, event); + } + else if EQ("gettagmethod") { + int tag = getnum; + const char *event = getname; + lua_gettagmethod(L, tag, event); + } + else if EQ("type") { + lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); + } + else luaL_verror(L, "unknown instruction %.30s", buff); + } + return 0; +} + +/* }====================================================== */ + + + +static const struct luaL_reg tests_funcs[] = { + {"hash", hash_query}, + {"limits", get_limits}, + {"listcode", listcode}, + {"liststrings", liststrings}, + {"listlocals", listlocals}, + {"loadlib", loadlib}, + {"querystr", string_query}, + {"querytab", table_query}, + {"testC", testC}, + {"ref", tref}, + {"getref", getref}, + {"unref", unref}, + {"newuserdata", newuserdata}, + {"udataval", udataval}, + {"newstate", newstate}, + {"closestate", closestate}, + {"doremote", doremote}, + {"settagmethod", settagmethod}, + {"equal", equal}, + {"totalmem", mem_query} +}; + + +void luaB_opentests (lua_State *L) { + lua_newtable(L); + lua_getglobals(L); + lua_pushvalue(L, -2); + lua_setglobals(L); + luaL_openl(L, tests_funcs); /* open functions inside new table */ + lua_setglobals(L); /* restore old table of globals */ + lua_setglobal(L, "T"); /* set new table as global T */ +} + +#endif diff --git a/liblua/ltm.cpp b/liblua/ltm.cpp new file mode 100644 index 0000000..a20909a --- /dev/null +++ b/liblua/ltm.cpp @@ -0,0 +1,163 @@ +/* +** $Id: ltm.c,v 1.56 2000/10/31 13:10:24 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltm.h" + + +const char *const luaT_eventname[] = { /* ORDER TM */ + "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub", + "mul", "div", "pow", "unm", "lt", "concat", "gc", "function", + "le", "gt", "ge", /* deprecated options!! */ + NULL +}; + + +static int findevent (const char *name) { + int i; + for (i=0; luaT_eventname[i]; i++) + if (strcmp(luaT_eventname[i], name) == 0) + return i; + return -1; /* name not found */ +} + + +static int luaI_checkevent (lua_State *L, const char *name, int t) { + int e = findevent(name); + if (e >= TM_N) + luaO_verror(L, "event `%.50s' is deprecated", name); + if (e == TM_GC && t == LUA_TTABLE) + luaO_verror(L, "event `gc' for tables is deprecated"); + if (e < 0) + luaO_verror(L, "`%.50s' is not a valid event name", name); + return e; +} + + + +/* events in LUA_TNIL are all allowed, since this is used as a +* 'placeholder' for "default" fallbacks +*/ +/* ORDER LUA_T, ORDER TM */ +static const char luaT_validevents[NUM_TAGS][TM_N] = { + {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ + {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */ + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */ + {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */ + {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */ +}; + +int luaT_validevent (int t, int e) { /* ORDER LUA_T */ + return (t >= NUM_TAGS) ? 1 : luaT_validevents[t][e]; +} + + +static void init_entry (lua_State *L, int tag) { + int i; + for (i=0; iTMtable[tag].collected = NULL; +} + + +void luaT_init (lua_State *L) { + int t; + luaM_growvector(L, L->TMtable, 0, NUM_TAGS, struct TM, "", MAX_INT); + L->nblocks += NUM_TAGS*sizeof(struct TM); + L->last_tag = NUM_TAGS-1; + for (t=0; t<=L->last_tag; t++) + init_entry(L, t); +} + + +LUA_API int lua_newtag (lua_State *L) { + luaM_growvector(L, L->TMtable, L->last_tag, 1, struct TM, + "tag table overflow", MAX_INT); + L->nblocks += sizeof(struct TM); + L->last_tag++; + init_entry(L, L->last_tag); + return L->last_tag; +} + + +static void checktag (lua_State *L, int tag) { + if (!(0 <= tag && tag <= L->last_tag)) + luaO_verror(L, "%d is not a valid tag", tag); +} + +void luaT_realtag (lua_State *L, int tag) { + if (!validtag(tag)) + luaO_verror(L, "tag %d was not created by `newtag'", tag); +} + + +LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) { + int e; + checktag(L, tagto); + checktag(L, tagfrom); + for (e=0; eu.d.tag; + case LUA_TTABLE: return hvalue(o)->htag; + default: return t; + } +} + + +LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) { + int e; + e = luaI_checkevent(L, event, t); + checktag(L, t); + if (luaT_validevent(t, e) && luaT_gettm(L, t, e)) { + clvalue(L->top) = luaT_gettm(L, t, e); + ttype(L->top) = LUA_TFUNCTION; + } + else + ttype(L->top) = LUA_TNIL; + incr_top; +} + + +LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) { + int e = luaI_checkevent(L, event, t); + checktag(L, t); + if (!luaT_validevent(t, e)) + luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s", + luaT_eventname[e], luaO_typenames[t], + (t == LUA_TTABLE || t == LUA_TUSERDATA) ? + " with default tag" : ""); + switch (ttype(L->top - 1)) { + case LUA_TNIL: + luaT_gettm(L, t, e) = NULL; + break; + case LUA_TFUNCTION: + luaT_gettm(L, t, e) = clvalue(L->top - 1); + break; + default: + lua_error(L, "tag method must be a function (or nil)"); + } + L->top--; +} + diff --git a/liblua/ltm.h b/liblua/ltm.h new file mode 100644 index 0000000..3bd8e82 --- /dev/null +++ b/liblua/ltm.h @@ -0,0 +1,59 @@ +/* +** $Id: ltm.h,v 1.18 2000/10/05 13:00:17 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" +#include "lstate.h" + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_GETTABLE = 0, + TM_SETTABLE, + TM_INDEX, + TM_GETGLOBAL, + TM_SETGLOBAL, + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_POW, + TM_UNM, + TM_LT, + TM_CONCAT, + TM_GC, + TM_FUNCTION, + TM_N /* number of elements in the enum */ +} TMS; + + +struct TM { + Closure *method[TM_N]; + TString *collected; /* list of garbage-collected udata with this tag */ +}; + + +#define luaT_gettm(L,tag,event) (L->TMtable[tag].method[event]) +#define luaT_gettmbyObj(L,o,e) (luaT_gettm((L),luaT_tag(o),(e))) + + +#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag) + +extern const char *const luaT_eventname[]; + + +void luaT_init (lua_State *L); +void luaT_realtag (lua_State *L, int tag); +int luaT_tag (const TObject *o); +int luaT_validevent (int t, int e); /* used by compatibility module */ + + +#endif diff --git a/liblua/lua.h b/liblua/lua.h new file mode 100644 index 0000000..b10f757 --- /dev/null +++ b/liblua/lua.h @@ -0,0 +1,249 @@ +/* +** $Id: lua.h,v 1.79 2000/10/31 12:44:07 roberto Exp $ +** Lua - An Extensible Extension Language +** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil +** e-mail: lua@tecgraf.puc-rio.br +** www: http://www.tecgraf.puc-rio.br/lua/ +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include "complex.h" + +/* definition of `size_t' */ +#include + + +/* mark for all API functions */ +#ifndef LUA_API +#define LUA_API extern +#endif + + +#define LUA_VERSION "Lua 4.0" +#define LUA_COPYRIGHT "Copyright (C) 1994-2000 TeCGraf, PUC-Rio" +#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" + + +/* name of global variable with error handler */ +#define LUA_ERRORMESSAGE "_ERRORMESSAGE" + + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) +#define LUA_REFREGISTRY 0 + +/* pre-defined tags */ +#define LUA_ANYTAG (-1) +#define LUA_NOTAG (-2) + + +/* option for multiple returns in lua_call */ +#define LUA_MULTRET (-1) + + +/* minimum stack available for a C function */ +#define LUA_MINSTACK 20 + + +/* error codes for lua_do* */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + +/* +** types returned by `lua_type' +*/ +#define LUA_TNONE (-1) + +#define LUA_TUSERDATA 0 +#define LUA_TNIL 1 +#define LUA_TNUMBER 2 +#define LUA_TSTRING 3 +#define LUA_TTABLE 4 +#define LUA_TFUNCTION 5 + + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (int stacksize); +LUA_API void lua_close (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int index); +LUA_API void lua_pushvalue (lua_State *L, int index); +LUA_API void lua_remove (lua_State *L, int index); +LUA_API void lua_insert (lua_State *L, int index); +LUA_API int lua_stackspace (lua_State *L); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_type (lua_State *L, int index); +LUA_API const char *lua_typename (lua_State *L, int t); +LUA_API int lua_isnumber (lua_State *L, int index); +LUA_API int lua_isstring (lua_State *L, int index); +LUA_API int lua_iscfunction (lua_State *L, int index); +LUA_API int lua_tag (lua_State *L, int index); + +LUA_API int lua_equal (lua_State *L, int index1, int index2); +LUA_API int lua_lessthan (lua_State *L, int index1, int index2); + +LUA_API CComplex lua_tonumber (lua_State *L, int index); +LUA_API const char *lua_tostring (lua_State *L, int index); +LUA_API size_t lua_strlen (lua_State *L, int index); +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); +LUA_API void *lua_touserdata (lua_State *L, int index); +LUA_API const void *lua_topointer (lua_State *L, int index); + + +/* +** push functions (C -> stack) +*/ +LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushnumber (lua_State *L, CComplex n); +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); +LUA_API void lua_pushstring (lua_State *L, const char *s); +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushusertag (lua_State *L, void *u, int tag); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_getglobal (lua_State *L, const char *name); +LUA_API void lua_gettable (lua_State *L, int index); +LUA_API void lua_rawget (lua_State *L, int index); +LUA_API void lua_rawgeti (lua_State *L, int index, int n); +LUA_API void lua_getglobals (lua_State *L); +LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_getref (lua_State *L, int ref); +LUA_API void lua_newtable (lua_State *L); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_setglobal (lua_State *L, const char *name); +LUA_API void lua_settable (lua_State *L, int index); +LUA_API void lua_rawset (lua_State *L, int index); +LUA_API void lua_rawseti (lua_State *L, int index, int n); +LUA_API void lua_setglobals (lua_State *L); +LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); +LUA_API int lua_ref (lua_State *L, int lock); + + +/* +** "do" functions (run Lua code) +*/ +LUA_API int lua_call (lua_State *L, int nargs, int nresults); +LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults); +LUA_API int lua_dofile (lua_State *L, const char *filename); +LUA_API int lua_dostring (lua_State *L, const char *str); +LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name); + +/* +** Garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ +LUA_API int lua_newtag (lua_State *L); +LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); +LUA_API void lua_settag (lua_State *L, int tag); + +LUA_API void lua_error (lua_State *L, const char *s); + +LUA_API void lua_unref (lua_State *L, int ref); + +LUA_API int lua_next (lua_State *L, int index); +LUA_API int lua_getn (lua_State *L, int index); + +LUA_API void lua_concat (lua_State *L, int n); + +LUA_API void *lua_newuserdata (lua_State *L, size_t size); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) +#define lua_pushuserdata(L,u) lua_pushusertag(L, u, 0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) +#define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) + +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) + +#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) + +#endif + + + +/****************************************************************************** +* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, without written agreement and without license +* or royalty fees, to use, copy, modify, and distribute this software and its +* documentation for any purpose, including commercial applications, subject to +* the following conditions: +* +* - The above copyright notice and this permission notice shall appear in all +* copies or substantial portions of this software. +* +* - The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software in a +* product, an acknowledgment in the product documentation would be greatly +* appreciated (but it is not required). +* +* - Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* +* The authors specifically disclaim any warranties, including, but not limited +* to, the implied warranties of merchantability and fitness for a particular +* purpose. The software provided hereunder is on an "as is" basis, and the +* authors have no obligation to provide maintenance, support, updates, +* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the +* authors be held liable to any party for direct, indirect, special, +* incidental, or consequential damages arising out of the use of this software +* and its documentation. +* +* The Lua language and this implementation have been entirely designed and +* written by Waldemar Celes Filho, Roberto Ierusalimschy and +* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. +* +* This implementation contains no third-party code. +******************************************************************************/ + diff --git a/liblua/luadebug.h b/liblua/luadebug.h new file mode 100644 index 0000000..77753d3 --- /dev/null +++ b/liblua/luadebug.h @@ -0,0 +1,46 @@ +/* +** $Id: luadebug.h,v 1.17 2000/10/30 12:38:50 roberto Exp $ +** Debugging API +** See Copyright Notice in lua.h +*/ + + +#ifndef luadebug_h +#define luadebug_h + + +#include "lua.h" + +typedef struct lua_Debug lua_Debug; /* activation record */ +typedef struct lua_Localvar lua_Localvar; + +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); + +LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); +LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + const char *event; /* `call', `return' */ + int currentline; /* (l) */ + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `tag method', `local', `field' */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ + const char *source; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct lua_TObject *_func; /* active function */ +}; + + +#endif diff --git a/liblua/lualib.h b/liblua/lualib.h new file mode 100644 index 0000000..81a98e2 --- /dev/null +++ b/liblua/lualib.h @@ -0,0 +1,33 @@ +/* +** $Id: lualib.h,v 1.14 2000/10/27 16:15:53 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + +#ifndef LUALIB_API +#define LUALIB_API extern +#endif + + +#define LUA_ALERT "_ALERT" + +LUALIB_API void lua_baselibopen (lua_State *L); +LUALIB_API void lua_iolibopen (lua_State *L); +LUALIB_API void lua_strlibopen (lua_State *L); +LUALIB_API void lua_mathlibopen (lua_State *L); +LUALIB_API void lua_dblibopen (lua_State *L); + + + +/* Auxiliary functions (private) */ + +const char *luaI_classend (lua_State *L, const char *p); +int luaI_singlematch (int c, const char *p, const char *ep); + +#endif diff --git a/liblua/lundump.cpp b/liblua/lundump.cpp new file mode 100644 index 0000000..b648d10 --- /dev/null +++ b/liblua/lundump.cpp @@ -0,0 +1,244 @@ +/* +** $Id: lundump.c,v 1.33 2000/10/31 16:57:23 lhf Exp $ +** load bytecodes from files +** See Copyright Notice in lua.h +*/ + +#include +#include + +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#define LoadByte ezgetc + +static const char* ZNAME (ZIO* Z) +{ + const char* s=zname(Z); + return (*s=='@') ? s+1 : s; +} + +static void unexpectedEOZ (lua_State* L, ZIO* Z) +{ + luaO_verror(L,"unexpected end of file in `%.99s'",ZNAME(Z)); +} + +static int ezgetc (lua_State* L, ZIO* Z) +{ + int c=zgetc(Z); + if (c==EOZ) unexpectedEOZ(L,Z); + return c; +} + +static void ezread (lua_State* L, ZIO* Z, void* b, int n) +{ + int r=zread(Z,b,n); + if (r!=0) unexpectedEOZ(L,Z); +} + +static void LoadBlock (lua_State* L, void* b, size_t size, ZIO* Z, int swap) +{ + if (swap) + { + char *p=(char *) b+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(L,Z); + } + else + ezread(L,Z,b,size); +} + +static void LoadVector (lua_State* L, void* b, int m, size_t size, ZIO* Z, int swap) +{ + if (swap) + { + char *q=(char *) b; + while (m--) + { + char *p=q+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(L,Z); + q+=size; + } + } + else + ezread(L,Z,b,m*size); +} + +static int LoadInt (lua_State* L, ZIO* Z, int swap) +{ + int x; + LoadBlock(L,&x,sizeof(x),Z,swap); + return x; +} + +static size_t LoadSize (lua_State* L, ZIO* Z, int swap) +{ + size_t x; + LoadBlock(L,&x,sizeof(x),Z,swap); + return x; +} + +static Number LoadNumber (lua_State* L, ZIO* Z, int swap) +{ + Number x; + LoadBlock(L,&x,sizeof(x),Z,swap); + return x; +} + +static TString* LoadString (lua_State* L, ZIO* Z, int swap) +{ + size_t size=LoadSize(L,Z,swap); + if (size==0) + return NULL; + else + { + char* s=luaO_openspace(L,size); + LoadBlock(L,s,size,Z,0); + return luaS_newlstr(L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode (lua_State* L, Proto* tf, ZIO* Z, int swap) +{ + int size=LoadInt(L,Z,swap); + tf->code=luaM_newvector(L,size,Instruction); + LoadVector(L,tf->code,size,sizeof(*tf->code),Z,swap); + if (tf->code[size-1]!=OP_END) luaO_verror(L,"bad code in `%.99s'",ZNAME(Z)); + luaF_protook(L,tf,size); +} + +static void LoadLocals (lua_State* L, Proto* tf, ZIO* Z, int swap) +{ + int i,n; + tf->nlocvars=n=LoadInt(L,Z,swap); + tf->locvars=luaM_newvector(L,n,LocVar); + for (i=0; ilocvars[i].varname=LoadString(L,Z,swap); + tf->locvars[i].startpc=LoadInt(L,Z,swap); + tf->locvars[i].endpc=LoadInt(L,Z,swap); + } +} + +static void LoadLines (lua_State* L, Proto* tf, ZIO* Z, int swap) +{ + int n; + tf->nlineinfo=n=LoadInt(L,Z,swap); + tf->lineinfo=luaM_newvector(L,n,int); + LoadVector(L,tf->lineinfo,n,sizeof(*tf->lineinfo),Z,swap); +} + +static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap); + +static void LoadConstants (lua_State* L, Proto* tf, ZIO* Z, int swap) +{ + int i,n; + tf->nkstr=n=LoadInt(L,Z,swap); + tf->kstr=luaM_newvector(L,n,TString*); + for (i=0; ikstr[i]=LoadString(L,Z,swap); + tf->nknum=n=LoadInt(L,Z,swap); + tf->knum=luaM_newvector(L,n,Number); + LoadVector(L,tf->knum,n,sizeof(*tf->knum),Z,swap); + tf->nkproto=n=LoadInt(L,Z,swap); + tf->kproto=luaM_newvector(L,n,Proto*); + for (i=0; ikproto[i]=LoadFunction(L,Z,swap); +} + +static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap) +{ + Proto* tf=luaF_newproto(L); + tf->source=LoadString(L,Z,swap); + tf->lineDefined=LoadInt(L,Z,swap); + tf->numparams=LoadInt(L,Z,swap); + tf->is_vararg=LoadByte(L,Z); + tf->maxstacksize=LoadInt(L,Z,swap); + LoadLocals(L,tf,Z,swap); + LoadLines(L,tf,Z,swap); + LoadConstants(L,tf,Z,swap); + LoadCode(L,tf,Z,swap); + return tf; +} + +static void LoadSignature (lua_State* L, ZIO* Z) +{ + const char* s=SIGNATURE; + while (*s!=0 && ezgetc(L,Z)==*s) + ++s; + if (*s!=0) luaO_verror(L,"bad signature in `%.99s'",ZNAME(Z)); +} + +static void TestSize (lua_State* L, int s, const char* what, ZIO* Z) +{ + int r=ezgetc(L,Z); + if (r!=s) + luaO_verror(L,"virtual machine mismatch in `%.99s':\n" + " %.20s is %d but read %d",ZNAME(Z),what,s,r); +} + +#define TESTSIZE(s) TestSize(L,s,#s,Z) +#define V(v) v/16,v%16 + +static int LoadHeader (lua_State* L, ZIO* Z) +{ + int version,swap; + Number f=0,tf=TEST_NUMBER; + LoadSignature(L,Z); + version=ezgetc(L,Z); + if (version>VERSION) + luaO_verror(L,"`%.99s' too new:\n" + " read version %d.%d; expected at most %d.%d", + ZNAME(Z),V(version),V(VERSION)); + if (version" +#define SOURCE tf->lineDefined,tf->source->str +#define IN_FMT " in %p " SOURCE_FMT +#define IN tf,SOURCE + +/* a multiple of PI for testing native format */ +/* multiplying by 1E8 gives non-trivial integer values */ +#define TEST_NUMBER 3.14159265358979323846E8 + +#endif diff --git a/liblua/lvm.cpp b/liblua/lvm.cpp new file mode 100644 index 0000000..578b2cc --- /dev/null +++ b/liblua/lvm.cpp @@ -0,0 +1,710 @@ +/* +** $Id: lvm.c,v 1.146 2000/10/26 12:47:05 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +#ifdef OLD_ANSI +#define strcoll(a,b) strcmp(a,b) +#endif + + + +/* +** Extra stack size to run a function: +** TAG_LINE(1), NAME(1), TM calls(3) (plus some extra...) +*/ +#define EXTRA_STACK 8 + + + +int luaV_tonumber (TObject *obj) { + if (ttype(obj) != LUA_TSTRING) + return 1; + else { + if (!luaO_str2d(svalue(obj), &nvalue(obj))) + return 2; + ttype(obj) = LUA_TNUMBER; + return 0; + } +} + + +int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */ + if (ttype(obj) != LUA_TNUMBER) + return 1; + else { + char s[256]; /* 16 digits, sign, point and \0 (+ some extra...) */ + lua_number2str(s, nvalue(obj)); /* convert `s' to number */ + tsvalue(obj) = luaS_new(L, s); + ttype(obj) = LUA_TSTRING; + return 0; + } +} + + +static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) { + CallInfo *ci = infovalue(base-1); + int *lineinfo = ci->func->f.l->lineinfo; + int pc = (*ci->pc - ci->func->f.l->code) - 1; + int newline; + if (pc == 0) { /* may be first time? */ + ci->line = 1; + ci->refi = 0; + ci->lastpc = pc+1; /* make sure it will call linehook */ + } + newline = luaG_getline(lineinfo, pc, ci->line, &ci->refi); + /* calls linehook when enters a new line or jumps back (loop) */ + if (newline != ci->line || pc <= ci->lastpc) { + ci->line = newline; + L->top = top; + luaD_lineHook(L, base-1, newline, linehook); + } + ci->lastpc = pc; +} + + +static Closure *luaV_closure (lua_State *L, int nelems) { + Closure *c = luaF_newclosure(L, nelems); + L->top -= nelems; + while (nelems--) + c->upvalue[nelems] = *(L->top+nelems); + clvalue(L->top) = c; + ttype(L->top) = LUA_TFUNCTION; + incr_top; + return c; +} + + +void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems) { + Closure *cl = luaV_closure(L, nelems); + cl->f.c = c; + cl->isC = 1; +} + + +void luaV_Lclosure (lua_State *L, Proto *l, int nelems) { + Closure *cl = luaV_closure(L, nelems); + cl->f.l = l; + cl->isC = 0; +} + + +/* +** Function to index a table. +** Receives the table at `t' and the key at top. +*/ +const TObject *luaV_gettable (lua_State *L, StkId t) { + Closure *tm; + int tg; + if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ + ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ + luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */ + /* do a primitive get */ + const TObject *h = luaH_get(L, hvalue(t), L->top-1); + /* result is no nil or there is no `index' tag method? */ + if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL)) + return h; /* return result */ + /* else call `index' tag method */ + } + else { /* try a `gettable' tag method */ + tm = luaT_gettmbyObj(L, t, TM_GETTABLE); + } + if (tm != NULL) { /* is there a tag method? */ + luaD_checkstack(L, 2); + *(L->top+1) = *(L->top-1); /* key */ + *L->top = *t; /* table */ + clvalue(L->top-1) = tm; /* tag method */ + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 2; + luaD_call(L, L->top - 3, 1); + return L->top - 1; /* call result */ + } + else { /* no tag method */ + luaG_typeerror(L, t, "index"); + return NULL; /* to avoid warnings */ + } +} + + +/* +** Receives table at `t', key at `key' and value at top. +*/ +void luaV_settable (lua_State *L, StkId t, StkId key) { + int tg; + if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ + ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ + luaT_gettm(L, tg, TM_SETTABLE) == NULL)) /* or no TM? */ + *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */ + else { /* try a `settable' tag method */ + Closure *tm = luaT_gettmbyObj(L, t, TM_SETTABLE); + if (tm != NULL) { + luaD_checkstack(L, 3); + *(L->top+2) = *(L->top-1); + *(L->top+1) = *key; + *(L->top) = *t; + clvalue(L->top-1) = tm; + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 3; + luaD_call(L, L->top - 4, 0); /* call `settable' tag method */ + } + else /* no tag method... */ + luaG_typeerror(L, t, "index"); + } +} + + +const TObject *luaV_getglobal (lua_State *L, TString *s) { + const TObject *value = luaH_getstr(L->gt, s); + Closure *tm = luaT_gettmbyObj(L, value, TM_GETGLOBAL); + if (tm == NULL) /* is there a tag method? */ + return value; /* default behavior */ + else { /* tag method */ + luaD_checkstack(L, 3); + clvalue(L->top) = tm; + ttype(L->top) = LUA_TFUNCTION; + tsvalue(L->top+1) = s; /* global name */ + ttype(L->top+1) = LUA_TSTRING; + *(L->top+2) = *value; + L->top += 3; + luaD_call(L, L->top - 3, 1); + return L->top - 1; + } +} + + +void luaV_setglobal (lua_State *L, TString *s) { + const TObject *oldvalue = luaH_getstr(L->gt, s); + Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL); + if (tm == NULL) { /* is there a tag method? */ + if (oldvalue != &luaO_nilobject) { + /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */ + *(TObject *)oldvalue = *(L->top - 1); + } + else { + TObject key; + ttype(&key) = LUA_TSTRING; + tsvalue(&key) = s; + *luaH_set(L, L->gt, &key) = *(L->top - 1); + } + } + else { + luaD_checkstack(L, 3); + *(L->top+2) = *(L->top-1); /* new value */ + *(L->top+1) = *oldvalue; + ttype(L->top) = LUA_TSTRING; + tsvalue(L->top) = s; + clvalue(L->top-1) = tm; + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 3; + luaD_call(L, L->top - 4, 0); + } +} + + +static int call_binTM (lua_State *L, StkId top, TMS event) { + /* try first operand */ + Closure *tm = luaT_gettmbyObj(L, top-2, event); + L->top = top; + if (tm == NULL) { + tm = luaT_gettmbyObj(L, top-1, event); /* try second operand */ + if (tm == NULL) { + tm = luaT_gettm(L, 0, event); /* try a `global' method */ + if (tm == NULL) + return 0; /* error */ + } + } + lua_pushstring(L, luaT_eventname[event]); + luaD_callTM(L, tm, 3, 1); + return 1; +} + + +static void call_arith (lua_State *L, StkId top, TMS event) { + if (!call_binTM(L, top, event)) + luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on"); +} + + +static int luaV_strcomp (const TString *ls, const TString *rs) { + const char *l = ls->str; + size_t ll = ls->len; + const char *r = rs->str; + size_t lr = rs->len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == ll) /* l is finished? */ + return (len == lr) ? 0 : -1; /* l is equal or smaller than r */ + else if (len == lr) /* r is finished? */ + return 1; /* l is greater than r (because l is not finished) */ + /* both strings longer than `len'; go on comparing (after the '\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) { + if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) + return (Re(nvalue(l)) < Re(nvalue(r))); + else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) + return (luaV_strcomp(tsvalue(l), tsvalue(r)) < 0); + else { /* call TM */ + luaD_checkstack(L, 2); + *top++ = *l; + *top++ = *r; + if (!call_binTM(L, top, TM_LT)) + luaG_ordererror(L, top-2); + L->top--; + return (ttype(L->top) != LUA_TNIL); + } +} + + +void luaV_strconc (lua_State *L, int total, StkId top) { + do { + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (tostring(L, top-2) || tostring(L, top-1)) { + if (!call_binTM(L, top, TM_CONCAT)) + luaG_binerror(L, top-2, LUA_TSTRING, "concat"); + } + else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ + /* at least two string values; get as many as possible */ + lint32 tl = (lint32)tsvalue(top-1)->len + + (lint32)tsvalue(top-2)->len; + char *buffer; + int i; + while (n < total && !tostring(L, top-n-1)) { /* collect total length */ + tl += tsvalue(top-n-1)->len; + n++; + } + if (tl > MAX_SIZET) lua_error(L, "string size overflow"); + buffer = luaO_openspace(L, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, tsvalue(top-i)->str, l); + tl += l; + } + tsvalue(top-n) = luaS_newlstr(L, buffer, tl); + } + total -= n-1; /* got `n' strings to create 1 new */ + top -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void luaV_pack (lua_State *L, StkId firstelem) { + int i; + Hash *htab = luaH_new(L, 0); + for (i=0; firstelem+itop; i++) + *luaH_setint(L, htab, i+1) = *(firstelem+i); + /* store counter in field `n' */ + luaH_setstrnum(L, htab, luaS_new(L, "n"), i); + L->top = firstelem; /* remove elements from the stack */ + ttype(L->top) = LUA_TTABLE; + hvalue(L->top) = htab; + incr_top; +} + + +static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { + int nvararg = (L->top-base) - nfixargs; + if (nvararg < 0) + luaD_adjusttop(L, base, nfixargs); + luaV_pack(L, base+nfixargs); +} + + + +#define dojump(pc, i) { int d = GETARG_S(i); pc += d; } + +/* +** Executes the given Lua function. Parameters are between [base,top). +** Returns n such that the the results are between [n,top). +*/ +StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { + const Proto *const tf = cl->f.l; + StkId top; /* keep top local, for performance */ + const Instruction *pc = tf->code; + TString **const kstr = tf->kstr; + const lua_Hook linehook = L->linehook; + infovalue(base-1)->pc = &pc; + luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); + if (tf->is_vararg) /* varargs? */ + adjust_varargs(L, base, tf->numparams); + else + luaD_adjusttop(L, base, tf->numparams); + top = L->top; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + if (linehook) + traceexec(L, base, top, linehook); + switch (GET_OPCODE(i)) { + case OP_END: { + L->top = top; + return top; + } + case OP_RETURN: { + L->top = top; + return base+GETARG_U(i); + } + case OP_CALL: { + int nres = GETARG_B(i); + if (nres == MULT_RET) nres = LUA_MULTRET; + L->top = top; + luaD_call(L, base+GETARG_A(i), nres); + top = L->top; + break; + } + case OP_TAILCALL: { + L->top = top; + luaD_call(L, base+GETARG_A(i), LUA_MULTRET); + return base+GETARG_B(i); + } + case OP_PUSHNIL: { + int n = GETARG_U(i); + LUA_ASSERT(n>0, "invalid argument"); + do { + ttype(top++) = LUA_TNIL; + } while (--n > 0); + break; + } + case OP_POP: { + top -= GETARG_U(i); + break; + } + case OP_PUSHINT: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = (Number)GETARG_S(i); + top++; + break; + } + case OP_PUSHSTRING: { + ttype(top) = LUA_TSTRING; + tsvalue(top) = kstr[GETARG_U(i)]; + top++; + break; + } + case OP_PUSHNUM: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = tf->knum[GETARG_U(i)]; + top++; + break; + } + case OP_PUSHNEGNUM: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = -tf->knum[GETARG_U(i)]; + top++; + break; + } + case OP_PUSHUPVALUE: { + *top++ = cl->upvalue[GETARG_U(i)]; + break; + } + case OP_GETLOCAL: { + *top++ = *(base+GETARG_U(i)); + break; + } + case OP_GETGLOBAL: { + L->top = top; + *top = *luaV_getglobal(L, kstr[GETARG_U(i)]); + top++; + break; + } + case OP_GETTABLE: { + L->top = top; + top--; + *(top-1) = *luaV_gettable(L, top-1); + break; + } + case OP_GETDOTTED: { + ttype(top) = LUA_TSTRING; + tsvalue(top) = kstr[GETARG_U(i)]; + L->top = top+1; + *(top-1) = *luaV_gettable(L, top-1); + break; + } + case OP_GETINDEXED: { + *top = *(base+GETARG_U(i)); + L->top = top+1; + *(top-1) = *luaV_gettable(L, top-1); + break; + } + case OP_PUSHSELF: { + TObject receiver; + receiver = *(top-1); + ttype(top) = LUA_TSTRING; + tsvalue(top++) = kstr[GETARG_U(i)]; + L->top = top; + *(top-2) = *luaV_gettable(L, top-2); + *(top-1) = receiver; + break; + } + case OP_CREATETABLE: { + L->top = top; + luaC_checkGC(L); + hvalue(top) = luaH_new(L, GETARG_U(i)); + ttype(top) = LUA_TTABLE; + top++; + break; + } + case OP_SETLOCAL: { + *(base+GETARG_U(i)) = *(--top); + break; + } + case OP_SETGLOBAL: { + L->top = top; + luaV_setglobal(L, kstr[GETARG_U(i)]); + top--; + break; + } + case OP_SETTABLE: { + StkId t = top-GETARG_A(i); + L->top = top; + luaV_settable(L, t, t+1); + top -= GETARG_B(i); /* pop values */ + break; + } + case OP_SETLIST: { + int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; + int n = GETARG_B(i); + Hash *arr = hvalue(top-n-1); + L->top = top-n; /* final value of `top' (in case of errors) */ + for (; n; n--) + *luaH_setint(L, arr, n+aux) = *(--top); + break; + } + case OP_SETMAP: { + int n = GETARG_U(i); + StkId finaltop = top-2*n; + Hash *arr = hvalue(finaltop-1); + L->top = finaltop; /* final value of `top' (in case of errors) */ + for (; n; n--) { + top-=2; + *luaH_set(L, arr, top) = *(top+1); + } + break; + } + case OP_ADD: { + if (tonumber(top-2) || tonumber(top-1)) + call_arith(L, top, TM_ADD); + else + nvalue(top-2) += nvalue(top-1); + top--; + break; + } + case OP_ADDI: { + if (tonumber(top-1)) { + ttype(top) = LUA_TNUMBER; + nvalue(top) = (Number)GETARG_S(i); + call_arith(L, top+1, TM_ADD); + } + else + nvalue(top-1) += (Number)GETARG_S(i); + break; + } + case OP_SUB: { + if (tonumber(top-2) || tonumber(top-1)) + call_arith(L, top, TM_SUB); + else + nvalue(top-2) -= nvalue(top-1); + top--; + break; + } + case OP_MULT: { + if (tonumber(top-2) || tonumber(top-1)) + call_arith(L, top, TM_MUL); + else + nvalue(top-2) *= nvalue(top-1); + top--; + break; + } + case OP_DIV: { + if (tonumber(top-2) || tonumber(top-1)) + call_arith(L, top, TM_DIV); + else + nvalue(top-2) /= nvalue(top-1); + top--; + break; + } + case OP_POW: { + if (!call_binTM(L, top, TM_POW)) + lua_error(L, "undefined operation"); + top--; + break; + } + case OP_CONCAT: { + int n = GETARG_U(i); + luaV_strconc(L, n, top); + top -= n-1; + L->top = top; + luaC_checkGC(L); + break; + } + case OP_MINUS: { + if (tonumber(top-1)) { + ttype(top) = LUA_TNIL; + call_arith(L, top+1, TM_UNM); + } + else + nvalue(top-1) = -nvalue(top-1); + break; + } + case OP_NOT: { + ttype(top-1) = + (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; + nvalue(top-1) = 1; + break; + } + case OP_JMPNE: { + top -= 2; + if (!luaO_equalObj(top, top+1)) dojump(pc, i); + break; + } + case OP_JMPEQ: { + top -= 2; + if (luaO_equalObj(top, top+1)) dojump(pc, i); + break; + } + case OP_JMPLT: { + top -= 2; + if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); + break; + } + case OP_JMPLE: { /* a <= b === !(b b === (b= b === !(a 0 ? + nvalue(top-3) > nvalue(top-2) : + nvalue(top-3) < nvalue(top-2)) { /* `empty' loop? */ + top -= 3; /* remove control variables */ + dojump(pc, i); /* jump to loop end */ + } + break; + } + case OP_FORLOOP: { + LUA_ASSERT(ttype(top-1) == LUA_TNUMBER, "invalid step"); + LUA_ASSERT(ttype(top-2) == LUA_TNUMBER, "invalid limit"); + if (ttype(top-3) != LUA_TNUMBER) + lua_error(L, "`for' index must be a number"); + nvalue(top-3) += nvalue(top-1); /* increment index */ + if (nvalue(top-1) > 0 ? + nvalue(top-3) > nvalue(top-2) : + nvalue(top-3) < nvalue(top-2)) + top -= 3; /* end loop: remove control variables */ + else + dojump(pc, i); /* repeat loop */ + break; + } + case OP_LFORPREP: { + Node *node; + if (ttype(top-1) != LUA_TTABLE) + lua_error(L, "`for' table must be a table"); + node = luaH_next(L, hvalue(top-1), &luaO_nilobject); + if (node == NULL) { /* `empty' loop? */ + top--; /* remove table */ + dojump(pc, i); /* jump to loop end */ + } + else { + top += 2; /* index,value */ + *(top-2) = *key(node); + *(top-1) = *val(node); + } + break; + } + case OP_LFORLOOP: { + Node *node; + LUA_ASSERT(ttype(top-3) == LUA_TTABLE, "invalid table"); + node = luaH_next(L, hvalue(top-3), top-2); + if (node == NULL) /* end loop? */ + top -= 3; /* remove table, key, and value */ + else { + *(top-2) = *key(node); + *(top-1) = *val(node); + dojump(pc, i); /* repeat loop */ + } + break; + } + case OP_CLOSURE: { + L->top = top; + luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); + top = L->top; + luaC_checkGC(L); + break; + } + } + } +} diff --git a/liblua/lvm.h b/liblua/lvm.h new file mode 100644 index 0000000..ace07c8 --- /dev/null +++ b/liblua/lvm.h @@ -0,0 +1,32 @@ +/* +** $Id: lvm.h,v 1.27 2000/10/05 12:14:08 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tonumber(o) ((ttype(o) != LUA_TNUMBER) && (luaV_tonumber(o) != 0)) +#define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) + + +int luaV_tonumber (TObject *obj); +int luaV_tostring (lua_State *L, TObject *obj); +const TObject *luaV_gettable (lua_State *L, StkId t); +void luaV_settable (lua_State *L, StkId t, StkId key); +const TObject *luaV_getglobal (lua_State *L, TString *s); +void luaV_setglobal (lua_State *L, TString *s); +StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); +void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems); +void luaV_Lclosure (lua_State *L, Proto *l, int nelems); +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top); +void luaV_strconc (lua_State *L, int total, StkId top); + +#endif diff --git a/liblua/lzio.cpp b/liblua/lzio.cpp new file mode 100644 index 0000000..c958fe4 --- /dev/null +++ b/liblua/lzio.cpp @@ -0,0 +1,84 @@ +/* +** $Id: lzio.c,v 1.13 2000/06/12 13:52:05 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + + +#include +#include + +#include "lua.h" + +#include "lzio.h" + + + +/* ----------------------------------------------------- memory buffers --- */ + +static int zmfilbuf (ZIO* z) { + (void)z; /* to avoid warnings */ + return EOZ; +} + + +ZIO* zmopen (ZIO* z, const char* b, size_t size, const char *name) { + if (b==NULL) return NULL; + z->n = size; + z->p = (const unsigned char *)b; + z->filbuf = zmfilbuf; + z->u = NULL; + z->name = name; + return z; +} + +/* ------------------------------------------------------------ strings --- */ + +ZIO* zsopen (ZIO* z, const char* s, const char *name) { + if (s==NULL) return NULL; + return zmopen(z, s, strlen(s), name); +} + +/* -------------------------------------------------------------- FILEs --- */ + +static int zffilbuf (ZIO* z) { + size_t n; + if (feof((FILE *)z->u)) return EOZ; + n = fread(z->buffer, 1, ZBSIZE, (FILE *)z->u); + if (n==0) return EOZ; + z->n = n-1; + z->p = z->buffer; + return *(z->p++); +} + + +ZIO* zFopen (ZIO* z, FILE* f, const char *name) { + if (f==NULL) return NULL; + z->n = 0; + z->p = z->buffer; + z->filbuf = zffilbuf; + z->u = f; + z->name = name; + return z; +} + + +/* --------------------------------------------------------------- read --- */ +size_t zread (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { + if (z->filbuf(z) == EOZ) + return n; /* return number of missing bytes */ + zungetc(z); /* put result from `filbuf' in the buffer */ + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} diff --git a/liblua/lzio.h b/liblua/lzio.h new file mode 100644 index 0000000..5f4b43d --- /dev/null +++ b/liblua/lzio.h @@ -0,0 +1,53 @@ +/* +** $Id: lzio.h,v 1.7 2000/10/20 16:36:32 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include + + + +/* For Lua only */ +#define zFopen luaZ_Fopen +#define zsopen luaZ_sopen +#define zmopen luaZ_mopen +#define zread luaZ_read + +#define EOZ (-1) /* end of stream */ + +typedef struct zio ZIO; + +ZIO* zFopen (ZIO* z, FILE* f, const char *name); /* open FILEs */ +ZIO* zsopen (ZIO* z, const char* s, const char *name); /* string */ +ZIO* zmopen (ZIO* z, const char* b, size_t size, const char *name); /* memory */ + +size_t zread (ZIO* z, void* b, size_t n); /* read next n bytes */ + +#define zgetc(z) (((z)->n--)>0 ? ((int)*(z)->p++): (z)->filbuf(z)) +#define zungetc(z) (++(z)->n,--(z)->p) +#define zname(z) ((z)->name) + + + +/* --------- Private Part ------------------ */ + +#ifndef ZBSIZE +#define ZBSIZE 256 /* buffer size */ +#endif + +struct zio { + size_t n; /* bytes still unread */ + const unsigned char* p; /* current position in buffer */ + int (*filbuf)(ZIO* z); + void* u; /* additional data */ + const char *name; + unsigned char buffer[ZBSIZE]; /* buffer */ +}; + + +#endif diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..5d33c0d --- /dev/null +++ b/license.txt @@ -0,0 +1,412 @@ + +Finite Element Method Magnetics is distributed under +the terms of the Aladdin Free Public License: + +------------------------------------------------------ + +Aladdin Free Public License +(Version 8, November 18, 1999) +Copyright (C) 1994, 1995, 1997, 1998, 1999 +Aladdin Enterprises,Menlo Park, California, U.S.A. +All rights reserved. + +NOTE: This License is not the same as any of the GNU +Licenses published by the Free Software Foundation. +Its terms are substantially different from those of +the GNU Licenses. If you are familiar with the GNU +Licenses, please read this license with extra care. + +Aladdin Enterprises hereby grants to anyone the +permission to apply this License to their own work, +as long as the entire License (including the above +notices and this paragraph) is copied with no +changes, additions, or deletions except for changing +the first paragraph of Section 0 to include a +suitable description of the work to which the +license is being applied and of the person or entity +that holds the copyright in the work, and, if the +License is being applied to a work created in a +country other than the United States, replacing the +first paragraph of Section 6 with an appropriate +reference to the laws of the appropriate country. + +0. Subject Matter + +This License applies to the computer program known +as "Finite Element Method Magnetics." The "Program", +below, refers to such program. The Program is a +copyrighted work whose copyright is held by David C. +Meeker of Natick, MA, dmeeker@ieee.org (the +"Licensor"). Please note that the program Triangle, +written by Jonathan Shewchuk and used by FEMM +for the purposes of mesh generation is NOT covered +by this license and is subject to its own licensure terms. +The licensure terms for Triangle are attached after +this license. The Lua scripting language used by +FEMM is also distributed under its own licensing +terms. The licensing terms of Lua are also attached. + +A "work based on the Program" means either the +Program or any derivative work of the Program, as +defined in the United States Copyright Act of 1976, +such as a translation or a modification. + +BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY +WORK BASED ON THE PROGRAM), YOU INDICATE YOUR +ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL ITS +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR +MODIFYING THE PROGRAM OR WORKS BASED ON IT. NOTHING +OTHER THAN THIS LICENSE GRANTS YOU PERMISSION TO +MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE +WORKS. THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU +DO NOT ACCEPT THESE TERMS AND CONDITIONS, DO NOT +MODIFY OR DISTRIBUTE THE PROGRAM. + +1. Licenses. + +Licensor hereby grants you the following rights, +provided that you comply with all of the +restrictions set forth in this License and provided, +further, that you distribute an unmodified copy of +this License with the Program: + +(a) You may copy and distribute literal (i.e., +verbatim) copies of the Program's source code as you +receive it throughout the world, in any medium. + +(b) You may modify the Program, create works based +on the Program and distribute copies of such +throughout the world, in any medium. + +2. Restrictions. + +This license is subject to the following restrictions: + +(a) Distribution of the Program or any work based on +the Program by a commercial organization to any +third party is prohibited if any payment is made in +connection with such distribution, whether directly +(as in payment for a copy of the Program) or +indirectly (as in payment for some service related +to the Program, or payment for some product or +service that includes a copy of the Program "without +charge"; these are only examples, and not an +exhaustive enumeration of prohibited activities). +The following methods of distribution involving +payment shall not in and of themselves be a +violation of this restriction: + +(i) Posting the Program on a public access + information storage and retrieval service for + which a fee is received for retrieving + information (such as an on-line service), + provided that the fee is not content- dependent + (i.e., the fee would be the same for retrieving + the same volume of information consisting of + random data) and that access to the service and + to the Program is available independent of any + other product or service. An example of a + service that does not fall under this section + is an on-line service that is operated by a + company and that is only available to customers + of that company. (This is not an exhaustive + enumeration.) + +(ii) Distributing the Program on removable + computer-readable media, provided that the + files containing the Program are reproduced + entirely and verbatim on such media, that all + information on such media be redistributable + for non-commercial purposes without charge, and + that such media are distributed by themselves + (except for accompanying documentation) + independent of any other product or service. + Examples of such media include CD-ROM, magnetic + tape, and optical storage media. (This is not + intended to be an exhaustive list.) An example + of a distribution that does not fall under this + section is a CD-ROM included in a book or + magazine. (This is not an exhaustive + enumeration.) + +(b) Activities other than copying, distribution and +modification of the Program are not subject to this +License and they are outside its scope. Functional +use (running) of the Program is not restricted, and +any output produced through the use of the Program +is subject to this license only if its contents +constitute a work based on the Program (independent +of having been made by running the Program). + +(c) You must meet all of the following conditions +with respect to any work that you distribute or +publish that in whole or in part contains or is +derived from the Program or any part thereof ("the +Work"): + +(i) If you have modified the Program, you must cause + the Work to carry prominent notices stating + that you have modified the Program's files and + the date of any change. In each source file + that you have modified, you must include a + prominent notice that you have modified the + file, including your name, your e-mail address + (if any), and the date and purpose of the + change; + +(ii) You must cause the Work to be licensed as a + whole and at no charge to all third parties + under the terms of this License; + +(iii) If the Work normally reads commands + interactively when run, you must cause it, at + each time the Work commences operation, to + print or display an announcement including an + appropriate copyright notice and a notice that + there is no warranty (or else, saying that you + provide a warranty). Such notice must also + state that users may redistribute the Work only + under the conditions of this License and tell + the user how to view the copy of this License + included with the Work. (Exceptions: if the + Program is interactive but normally prints or + displays such an announcement only at the + request of a user, such as in an "About box", + the Work is required to print or display the + notice only under the same circumstances; if + the Program itself is interactive but does not + normally print such an announcement, the Work + is not required to print an announcement.); + +(iv) You must accompany the Work with the complete + corresponding machine-readable source code, + delivered on a medium customarily used for + software interchange. The source code for a + work means the preferred form of the work for + making modifications to it. For an executable + work, complete source code means all the source + code for all modules it contains, plus any + associated interface definition files, plus the + scripts used to control compilation and + installation of the executable code. If you + distribute with the Work any component that is + normally distributed (in either source or + binary form) with the major components + (compiler, kernel, and so on) of the operating + system on which the executable runs, you must + also distribute the source code of that + component if you have it and are allowed to do + so; + +(v) If you distribute any written or printed + material at all with the Work, such material + must include either a written copy of this + License, or a prominent written indication that + the Work is covered by this License and written + instructions for printing and/or displaying the + copy of the License on the distribution medium; + +(vi) You may not impose any further restrictions on + the recipient's exercise of the rights granted + herein. If distribution of executable or + object code is made by offering the equivalent + ability to copy from a designated place, then + offering equivalent ability to copy the source + code from the same place counts as distribution + of the source code, even though third parties + are not compelled to copy the source code along + with the object code. + +3. Reservation of Rights. + +No rights are granted to the Program except as +expressly set forth herein. You may not copy, +modify, sublicense, or distribute the Program except +as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense or +distribute the Program is void, and will +automatically terminate your rights under this +License. However, parties who have received copies, +or rights, from you under this License will not have +their licenses terminated so long as such parties +remain in full compliance. + +4. Other Restrictions. + +If the distribution and/or use of the Program is +restricted in certain countries for any reason, +Licensor may add an explicit geographical +distribution limitation excluding those countries, +so that distribution is permitted only in or among +countries not thus excluded. In such case, this +License incorporates the limitation as if written in +the body of this License. + +5. Limitations. + +THE PROGRAM IS PROVIDED TO YOU "AS IS," WITHOUT +WARRANTY. THERE IS NO WARRANTY FOR THE PROGRAM, +EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR +AGREED TO IN WRITING WILL LICENSOR, OR ANY OTHER +PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT +LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH +ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +6. General. + +This License is governed by the laws of the +Commonwealth of Massachusetts, U.S.A., excluding +choice of law rules. + +If any part of this License is found to be in +conflict with the law, that part shall be +interpreted in its broadest meaning consistent with +the law, and no other parts of the License shall be +affected. + +For United States Government users, the Program is +provided with RESTRICTED RIGHTS. If you are a unit +or agency of the United States Government or are +acquiring the Program for any such unit or agency, +the following apply: + +If the unit or agency is the Department of Defense +("DOD"), the Program and its documentation are +classified as "commercial computer software" and +"commercial computer software documentation" +respectively and, pursuant to DFAR Section 227.7202, +the Government is acquiring the Program and its +documentation in accordance with the terms of this +License. If the unit or agency is other than DOD, +the Program and its documentation are classified as +"commercial computer software" and "commercial +computer software documentation" respectively and, +pursuant to FAR Section 12.212, the Government is +acquiring the Program and its documentation in +accordance with the terms of this License. + +------------------------------------------------------ + +Triangle +A Two-Dimensional Quality Mesh Generator +and Delaunay Triangulator. +Version 1.3 + +Copyright 1996 Jonathan Richard Shewchuk +School of Computer Science +Carnegie Mellon University +5000 Forbes Avenue +Pittsburgh, Pennsylvania 15213-3891 +Please send bugs and comments to jrs@cs.cmu.edu + +Created as part of the Archimedes project (tools for +parallel FEM). Supported in part by NSF Grant +CMS-9318163 and an NSERC 1967 Scholarship. There is +no warranty whatsoever. Use at your own risk. + +Triangle generates exact Delaunay triangulations, +constrained Delaunay triangulations, and quality +conforming Delaunay triangulations. The latter can +be generated with no small angles, and are thus +suitable for finite element analysis. + +Information on the algorithms used by Triangle, +including complete references, can be found in the +comments at the beginning of the triangle.c source +file. Another listing of these references, with +PostScript copies of some of the papers, is available +from the Web page + +http://www.cs.cmu.edu/~quake/triangle.research.html + +[Triangle] may be freely redistributed under the +condition that the copyright notices (including the +copy of this notice in the code comments and the +copyright notice printed when the `-h' switch is +selected) are not removed, and no compensation is +received. Private, research, and institutional use +is free. You may distribute modified versions of +this code UNDER THE CONDITION THAT THIS CODE AND ANY +MODIFICATIONS MADE TO IT IN THE SAME FILE REMAIN +UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE +AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT +CHARGE, AND CLEAR NOTICE IS GIVEN OF THE +MODIFICATIONS. Distribution of this code as part of +a commercial system is permissible ONLY BY DIRECT +ARRANGEMENT WITH THE AUTHOR. (If you are not +directly supplying this code to a customer, and you +are instead telling them how they can obtain it for +free, then you are not required to make any +arrangement with [JRS].) + +If you use Triangle, and especially if you use it to +accomplish real work, I would like very much to hear +from you. A short letter or email (to +jrs@cs.cmu.edu) describing how you use Triangle will +mean a lot to me. The more people I know are using +this program, the more easily I can justify spending +time on improvements and on the three-dimensional +successor to Triangle, which in turn will benefit +you. Also, I can put you on a list to receive email +whenever a new version of Triangle is available. + +If you use a mesh generated by Triangle, please +include an acknowledgment as well. + +Jonathan Richard Shewchuk +July 20, 1996 + +------------------------------------------------------ + +Lua Copyright Notice + +Copyright © 1994-2000 TeCGraf, PUC-Rio. All rights reserved. + +Permission is hereby granted, without written agreement +and without license or royalty fees, to use, copy, modify, +translate, and distribute this software and its documentation +(hereby called the "package") for any purpose, including +commercial applications, subject to the following conditions: + +* The above copyright notice and this permission notice shall + appear in all copies or substantial portions of this package. +* The origin of this package must not be misrepresented; + you must not claim that you wrote the original package. + If you use this package in a product, an acknowledgment + in the product documentation would be greatly appreciated + (but it is not required). +* Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original package. + +The authors specifically disclaim any warranties, including, +but not limited to, the implied warranties of merchantability +and fitness for a particular purpose. The package provided +hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, +enhancements, or modifications. In no event shall TeCGraf, +PUC-Rio, or the authors be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising +out of the use of this package and its documentation. + +The Lua language and this implementation have been entirely +designed and written by Waldemar Celes, Roberto Ierusalimschy +and Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio in Brazil. + +This implementation contains no third-party code. diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..43cf3b7 --- /dev/null +++ b/readme.txt @@ -0,0 +1,288 @@ +FEMM 4.2 21Apr2019 +David Meeker +dmeeker@ieee.org + +21Apr2019: (Test Build) + +* Start from previous solution for magnetics problems. To use this, specify a + file name in "Previous Solution" edit box in the Problem Definition dialog. + Specify the "Prev Type" to be "None". This works if the mesh has not changed + from the last solution. Good rotating problems with the "sliding band" + boundary connecting the rotor and stator. These problems often involve + consideration of a sequence of problems with slightly different rotor angles + and currents. The "sliding band" approach lets the rotor move without + modifying the mesh. +* Updated materials library for heat flow problems (thanks to Daniel Gheorghe) +* Updated hard magnetic materials in magnetics materials library (thanks to + Mike Devine). Includes new definitions for Sintered NdFeB, Bonded NdFeB, + Sintered SmCo, and Alnico. See explanatory webpages on femm.info for sources + and rationale. +* Fixed precision in exported DXF so that no precision is lost in DXF exports. +* Changed the algorithm that identifies limits for plotting flux density so that + exterior regions (both Kelvin Transformation and IABC) are not considered. + These exterior regions can have high flux densities that mask the flux density + variations in the interior region of interest. + +06Oct2018: (Test Build) + +* Fixed the cause of an occasional error that happens running many runs in + Mathematica. Fkn.exe occasionally could not open a *.ans file to write over + older results. The fix adds a retry if the file can't be opened. +* Fixed a bug with the computation of the "sliding band" incremental torque + integral. The "previous solution" used to calculate the integral was not + obtained correctly. +* For incremental runs, mesh temporary files never got deleted, leaving extra, + spurious files hanging around. Code has been added to get rid of these + files when they're not needed any more. + +25Feb2018: + +* Added an "air gap boundary condition" that allows the rotor to be continuously + moved without the mesh changing with rotor position. A number of new scripting + functions have been added to calculate forces, torques, and field values of + associated with an analytical solution in the air gap between the rotor and + stator. Detailed examples to follow. +* Added file-by-file smartmesh attribute along with scripting commands for each + input file type (mi_smartmesh, ei_smartmesh, hi_smartmesh, ci_smartmesh) + to turn smartmesh on or off for a particular file. The global smartmesh + scripting function still works to turn smartmesh on or off across all problem + types for a particular session. +* Moved to console version of Triangle 1.6 made from directly compiling Triangle + source rather than wrapping it with a dialog. + +03Dec2017: (Test Build) + +* Fixed one more focus-stealing hole that took away focus during Lua + script execution. As noted at https://tinyurl.com/y9uggja3 the OnInitDialog + functions of triangle.exe, fkn.exe, belasolv.exe, csolv.exe, and hsolve.exe + must return FALSE instead of TRUE, or else focus might be stolen. + +24Nov2017: (Test Build) + +* Changed to Triangle 1.6 instead of Triangle 1.3. Version 1.6 is more + robust and usually does not hang / crash if there are small angles + in the input geometry. +* In cases where Triangle previously hung (displaying an error message) + when an error occured, the program now terminates and indicates that + an error has occured. This is especially useful for Matlab/Octave + scripts, which now get passed the error indication rather than having + the script hang on the meshing error. +* Fixed a number of additional instances of focus-stealing during script + execution. This makes it possible to do other things while FEMM is + running a long (Matlab/Octave or Mathematica) script. +* Added a new optional parameter to openfemm in Matlab/Octave/Mathematica + and Scilab scripting. openfemm(1) starts FEMM fully minimized. +* Calls to the analysis (mi_analyze, etc.) assume the state of the main + window. For example, if a scripting run is started minimized with + openfemm(1), subsequent mi_analyze() calls will also be run + minimized automatically. +* Fixed SciFEMM interface so that it works with Scilab 6.0.0 + +24Sep2017: (Test Build) + +* Fixed mi_attachdefault, ei_attachdefault, hi_attachdefault, and + ci_attachdefault functions, which didn't work correctly. + +23Jun2016: (Test Build) + +* Fixed sign error with off-diagonal term in permeability tensor for + incremental permeability problems. + +14Jun2016: (Test Build) + +* Added a "frozen permeability" problem type that can be used to split up + field contributions between various excitation sources for nonlinear DC + problems. Also extends the "incremental permeability" formulation to DC + problems. The DC incremental results can be used as part of a general + time-transient solver, essentially providing the derivatives of flux + linkage with respect to incremental changes in current and with + respect to small changes in position / orientation of moving parts. +* Dropped support for versions of Mathematica before version 5.0. Versions + prior to 5.0 do not include .NET/Link for interprocess communications, + +12Jan2016: + +* Fixed bug added in 01Nov2015 that messed up the reported permeability and + field intensity for nonlinear time harmonic problems. + +01Nov2015: + +* Adds "incremental permeability" AC solver. An example application for + this functionality is the analysis of the frequency-dependent impedance + of speaker drivers about the DC operating point established by the + speaker's permanent magnet. + - DC operating point specified as the "Previous Solution" in the problem + definition or via the mi_setprevious(filename) command in Lua. +* Adds 10% and 15% Copper Clad Aluminum magnet wire material types. The + material definition is intended to provide accurate estimates of proximity + and skin effect losses across a wide range of frequencies with a bulk + wire model (i.e. not every turn has to be individually modeled). +* Changes to some of the issues pointed out over the last couple years, e.g. + - Change to InTriangle test to fix the issues that could occur if a + specified point is exactly on the line between two elements + - Lua command to programmatically turn off "smart mesh" with the + smartmesh(state) Lua command. State is 0 for no "smart mesh" and 1 + for "smart mesh". Function has the same name in the Matlab interface + and is named SmartMesh in the Mathematica implementation + - Fixed bug where "mo_zoom", "eo_zoom", etc. didn't work right + - Fixed an issue where the right energy / flux linkage was not reported + for wound coils in AC magnetic problems if the frequency is very + small (e.g. <1μHz) +* For increased compatibility with Mathematica 10, the Mathematica interface + has been changed to use .NET/Link when it is available (instead of + MathLink). .NET/Link invokes FEMM as an out-of-proc ActiveX server + (the same way that FEMM communicates with Matlab). + +15Nov2013: + +* Changed the way that errors are trapped in Matlab/Octave and Scilab + implementations so that errors that would normally display as message + boxes in a normal GUI session instead get returned as errors to + Matlab/Octave or Scilab. Errors can then be trapped, e.g. by using a + try/catch block. + +07Nov2013: + +* Fixed instances of GetWindowLong and SetWindowLong which caused the x64 + build to crash when running on Linux via Wine. +* Fixes to eo_blockintegral and co_blockintegral functions. Previously wouldn't + allow integration (e.g. for Weighted Stress Tensor force) if the only selected + area was a conductor surface. + +25Aug2013: + +* Changed IABCs to support either a Dirichlet or Neumann outer edge. This + is useful for electrostatic problems. + +04Aug2013: + +* Added mi_selectcircle, mi_selectrectangle and friends to programmatically + select regions. +* Changed .dxf import so that objects assigned layers are imported as + grouped being in the same group. +* Added new "Improvised Asymptotic Boundary Condition" button and mi_makeABC + and friends Lua funtions as an alternate way of solving unbounded + problems. + +11Apr2012: + +* Can turn off "smart meshing" via a Preferences selection on the "General Attributes" + tab by unchecking "use smart meshing" +* Fixed a newly introduced bug where an erroneous resistive loss is computed for AC + problems in regions where conductivity = 0 +* Fixed mi_readdxf problem described as Bug 18 in the bug tracker. + +01Oct2011: + +* Fixed error in reported flux linkage. Flux linkage for stranded regions + carrying zero current is not reported correctly for AC problems. +* The Lua "format" command did not work properly with complex number--it + stripped off the imaginary part of the number. This is now fixed. +* The units reported for some heat flow block integral results were erroneous. + This has now been rectified. +* 64-bit version of FEMM 4.2 is now available. +* FEMM has been modified to allow multiple instance of FEMM to run at the + same time via ActiveX. For example, This allows multiple instance of FEMM + to be controlled by one instance of Matlab or Octave. +* FEMM 42 09Nov2010 asks for Mathematica integration when using the silent + install method. The installer script has been modified so that the silent + install assumes that Mathematica is not available, letting the installation + complete without requiring operator intervention. +* Default material. A feature has been added which allows one block label to + be designated as the default block label. Any unlabeled blocks are then + assumed to be tagged by the default block label. +* In the current flow problem type, line plots of quantities normal and + tangential to a user-define contour were messed up because the normal + and tangential directions were computed incorrectly. This is now fixed. +* The "default" mesh size has been changed. In previous builds, using the + default mesh size nearly always resulted in a mesh that was too coarse to + give accurate results. The default mesh size has been changed so that + specifying the default mesh size is adequate for most applications. + Note: can use the and keys to uniformly refine and coarsen the + mesh for the entire model with one keystroke. +* Added automatic refinement of the mesh near corners. This refinement + improves convergence of results like force, stored energy, etc. +* Changed the way that the maximum flux density is computed for flux density + plotting purposes. With the automatic refinement of corners, small elements + with high flux densities can appear in corners. The modified algorithm + discounts these small corner elements when picking a maximum for the purposes + of picking plot contours. +* Changed the key that is used to break out of Lua scripts to ESC from BREAK. + Many keyboards don't have a BREAK key anymore, so it made sense to make this + change. +* Changed the selection rectangle to a dotted line so that it would + render faster. +* Modified the DXF import to understand closed POLYLINE entities. Previously, + only open POLYLINE entities were supported. +* Fixed problem with functionality that creates rounded corners (i.e. + the functionality invoked by mi_createradius) where the program would not + allow a radius to be created if the intersection was between a line + segment and an arc segment if the line segment laid along a ling that + passed through the center of the circle associated with the arc segment. +* Default install directory changed to c:\femm42 to avoid directory + permissions problems in Windows 7. + +09Nov2010: + +* Added a set of Scilab functions for interfacing with FEMM. These + functions were tested using Scilab 5.2.2. The descriptions of these + functions are identical to those described in the OctaveFEMM + documentation. Example Scilab scripts are in the femm42/examples directory + and have a .sce file extension and can be run by typing: + exec('examplename.sce',-1) + at the Scilab commandline. If you did not install FEMM to the default + c:\Program Files\femm42 directory, you'll need to change the first line + of the *.sce files that loads the FEMM library so that it points to the + correct library location. + +11Oct2010: + +* Fixed bug in values of |H| reported in the Output Window for time harmonic + magnetic problems. +* Fixed bug where in some plots, units of H given as A/m^2 instead of A/m +* Fixed error in mo_showvectorplot Matlab/Octave function. Also fixed + similar errors in co_showvectorplot, ho_showvectorplot, eo_showvectorplot +* Fixed messed-up definitions of the Lua functions ei_defineouterspace, + ei_attachouterspace, and ei_detachouterspace +* Installer now prompts for whether or not Mathetmatica support is to be + included. If Mathematica support is selected, a version of FEMM is + installed that assumes the availability of ML32I2.DLL, a DLL installed by + Mathematica. Otherwise, a version of FEMM is installed that doesn't need + the Mathlink DLL. +* Re-wrote the GetIntersection routine that finds intersections between two + line segments. In some uncommon circumstances, the routine could create + extra points when the geometry was moved or rotated. +* Added extra Lua functions mi_getmaterial, ei_getmaterial, hi_getmaterial, + and ci_getmaterial to fetch material definitions from the materials + library on disk. Analogous functions were also added to the Matlab/Octave + and Mathematica interfaces. + +02Nov2009: + +* Added the Lua commands mi_setgroup, ei_setgroup, hi_setgroup, ci_setgroup + that assign all selected items to the group number specified by the + argument to the function. +* Fixed a bug that caused an incorrect permeability to be reported for + nonlinear materials at points where the flux density is less than 10nT. +* Fixed bugs with ci_addconductor and ci_modifyconductor Lua functions. +* Fixed bug with CIAddMaterial function in MathFEMM + +15Jul2009: Several minor changes have been made versus the 01Apr2009 release: + +* Added the following Lua commands that allow direct access to finite + element mesh information: + mo_numnodes, mo_numelements, mo_getnode, mo_getelement, + eo_numnodes, eo_numelements, eo_getnode, eo_getelement, + ho_numnodes, ho_numelements, ho_getnode, ho_getelement, + co_numnodes, co_numelements, co_getnode, co_getelement. + There are Matlab/Octave and Mathematica analogs of these commands, too. +* Made a few more performance tweaks to the Mathematica interface. +* Fixed bug in computation of heat flux passing through a constant + temperature-type "conductor property" +* Included a new selection of soft magnetic materials in the magnetic + materials library. The BH curves for these materials were obtained by + digitizing the curves picutured in Figure 17, "Direct current + magnetization curves for various magnetic materials", Metals Handbook, + 8th ed, Vol. 1, p. 792. These curves represent a wide variety of + materials, and the curves are defined to very high flux levels at + which all materials are fully saturated. diff --git a/release/condlib.dat b/release/condlib.dat new file mode 100644 index 0000000..ed60bdd --- /dev/null +++ b/release/condlib.dat @@ -0,0 +1,20 @@ + + = "Copper" + = 58000000 + = 58000000 + = 1 + = 1 + = 0 + = 0 + + + + = "Aluminum" + = 37700000 + = 37700000 + = 1 + = 1 + = 0 + = 0 + + diff --git a/release/heatlib.dat b/release/heatlib.dat new file mode 100644 index 0000000..f7497fd --- /dev/null +++ b/release/heatlib.dat @@ -0,0 +1,1650 @@ + + = "Metallic Solids" + + = "Aluminum" + + = "Aluminum, Pure" + = 236 + = 236 + = 2.4500000000000002 + = 0 + = 4 + 273 236 + 473 238 + 673 228 + 873 215 + + + + = "Aluminum, 2024-T3" + = 121 + = 121 + = 2.4329999999999998 + = 0 + + + + = "Aluminum, 2024-O" + = 193 + = 193 + = 2.4329999999999998 + = 0 + + + + = "Aluminum, 2024-T351" + = 121 + = 121 + = 2.4329999999999998 + = 0 + + + + = "Aluminum, 2024-T4" + = 121 + = 121 + = 2.4329999999999998 + = 0 + + + + = "Aluminum, 2024-T6" + = 171 + = 171 + = 2.4329999999999998 + = 0 + = 2 + 273 171 + 473 186 + + + + = "Aluminum, 6061-T6" + = 167 + = 167 + = 2.419 + = 0 + + + + = "Aluminum, 6061-T651" + = 167 + = 167 + = 2.419 + = 0 + + + + = "Aluminum, 7075-T6" + = 130 + = 130 + = 2.698 + = 0 + + + + = "Aluminum, 7075-T651" + = 130 + = 130 + = 2.698 + = 0 + + + + + = "Beryllium" + = 218 + = 218 + = 3.4020000000000001 + = 0 + = 6 + 273 218 + 473 144 + 673 118 + 873 100 + 1073 83 + 1273 69 + + + + = "Boron" + = 31.699999999999999 + = 31.699999999999999 + = 2.8250000000000002 + = 0 + = 6 + 273 31.699999999999999 + 473 18.300000000000001 + 673 10 + 873 7.4000000000000004 + 1073 5.9000000000000004 + 1273 4.7999999999999998 + + + + = "Cadmium" + = 104 + = 104 + = 1.99 + = 0 + = 2 + 273 104 + 473 99 + + + + = "Chromium" + = 95 + = 95 + = 3.2570000000000001 + = 0 + = 6 + 273 95 + 473 86 + 673 77 + 873 69 + 1073 64 + 1273 62 + + + + = "Cobalt" + = 104 + = 104 + = 3.7480000000000002 + = 0 + + + + = "Copper" + + = "Constantan" + = 22 + = 22 + = 3.6579999999999999 + = 0 + = 2 + 273 22 + 473 26 + + + + = "Copper, Pure" + = 401 + = 401 + = 3.4380000000000002 + = 0 + = 6 + 273 401 + 473 389 + 673 378 + 873 366 + 1073 352 + 1273 336 + + + + = "Brass" + = 110 + = 110 + = 3.2810000000000001 + = 0 + = 3 + 273 110 + 473 142 + 673 151 + + + + = "Bronze" + = 49 + = 49 + = 3.696 + = 0 + = 3 + 273 49 + 473 54 + 673 61 + + + + + = "Core-materials" + = "Carpenter" + + = "HyMu80" + = 34.600000000000001 + = 34.600000000000001 + = 4.3209999999999997 + = 0 + + + + = "Carpenter49" + = 13 + = 13 + = 4.125 + = 0 + + + + + = "Germanium" + = 67 + = 67 + = 1.7150000000000001 + = 0 + = 4 + 273 67 + 473 40 + 673 19 + 873 17 + + + + = "Gold" + = 318 + = 318 + = 2.492 + = 0 + = 6 + 273 318 + 473 309 + 673 299 + 873 286 + 1073 273 + 1273 254 + + + + = "Iron" + + = "Iron, Wrought" + = 59 + = 59 + = 3.5419999999999998 + = 0 + = 4 + 273 59 + 473 52 + 673 45 + 873 33 + + + + = "Iron, Pure" + = 83 + = 83 + = 3.5299999999999998 + = 0 + = 6 + 273 83 + 473 66 + 673 53 + 873 41 + 1073 32 + 1273 30 + + + + = "Iron, Cast (4% C)" + = 52 + = 52 + = 3.0539999999999998 + = 0 + = 5 + 273 52 + 473 40 + 673 34 + 873 24 + 1073 21 + + + + = "Iron, Armco" + = 75 + = 75 + = 3.634 + = 0 + = 6 + 273 75 + 473 62 + 673 49 + 873 38 + 1073 29 + 1273 29 + + + + + = "Steels" + + = "Steel, 1% Chrome" + = 62 + = 62 + = 3.6160000000000001 + = 0 + = 5 + 273 62 + 473 52 + 673 42 + 873 36 + 1073 33 + + + + = "Steel, 1% Carbon" + = 43 + = 43 + = 3.6899999999999999 + = 0 + = 5 + 273 43 + 473 42 + 673 36 + 873 29 + 1073 28 + + + + = "347 Stainless Steel" + = 14 + = 14 + = 3.829 + = 0 + = 6 + 273 14 + 473 17 + 673 19 + 873 23 + 1073 25 + 1273 26 + + + + = "304 Stainless Steel" + = 14 + = 14 + = 3.768 + = 0 + = 5 + 273 14 + 473 18 + 673 21 + 873 24 + 1073 26 + + + + = "SST 17Cr-4Ni, Cond H900" + = 17.899999999999999 + = 17.899999999999999 + = 3.2679999999999998 + = 0 + = 4 + 422.14999999999998 17.899999999999999 + 533.14999999999998 19.5 + 733.14999999999998 22.5 + 755.14999999999998 22.600000000000001 + + + + + = "Lead" + = 36 + = 36 + = 1.478 + = 0 + = 2 + 273 36 + 473 33 + + + + = "Lithium" + = 79 + = 79 + = 1.863 + = 0 + + + + = "Magnesium" + = 157 + = 157 + = 1.786 + = 0 + = 4 + 273 157 + 473 151 + 673 147 + 873 145 + + + + = "Manganese" + = 7.7000000000000002 + = 7.7000000000000002 + = 3.5590000000000002 + = 0 + + + + = "Molybdenum" + = 139 + = 139 + = 2.5649999999999999 + = 0 + = 6 + 273 139 + 473 131 + 673 123 + 873 116 + 1073 109 + 1273 103 + + + + = "Nickel" + + = "Nickel, Pure" + = 94 + = 94 + = 3.9630000000000001 + = 0 + = 6 + 273 94 + 473 74 + 673 65 + 873 69 + 1073 73 + 1273 78 + + + + = "Nichrome" + = 12 + = 12 + = 3.6960000000000002 + = 0 + = 4 + 273 12 + 473 15 + 673 18 + 873 23 + + + + = "Inconel-X" + = 11 + = 11 + = 3.7610000000000001 + = 0 + = 6 + 273 11 + 473 14 + 673 18 + 873 22 + 1073 25 + 1273 29 + + + + + = "Platinum" + + = "Platnium, Pure" + = 72 + = 72 + = 2.8530000000000002 + = 0 + = 6 + 273 72 + 473 72 + 673 74 + 873 76 + 1073 80 + 1273 84 + + + + = "60% Pt, 40% Rh" + = 46 + = 46 + = 2.694 + = 0 + = 6 + 273 46 + 473 54 + 673 62 + 873 66 + 1073 70 + 1273 74 + + + + + = "Rhenium" + = 49 + = 49 + = 2.8980000000000001 + = 0 + = 6 + 273 49 + 473 45 + 673 44 + 873 44 + 1073 45 + 1273 46 + + + + = "Rhodium" + = 151 + = 151 + = 3.0129999999999999 + = 0 + = 6 + 273 151 + 473 141 + 673 132 + 873 125 + 1073 119 + 1273 113 + + + + = "Silicon" + = 168 + = 168 + = 1.6439999999999999 + = 0 + = 6 + 273 168 + 473 93 + 673 59 + 873 41 + 1073 30 + 1273 25 + + + + = "Silver" + = 428 + = 428 + = 2.484 + = 0 + = 6 + 273 428 + 473 415 + 673 399 + 873 383 + 1073 368 + 1273 355 + + + + = "Sodium" + = 135 + = 135 + = 1.177 + = 0 + + + + = "Tin" + = 68 + = 68 + = 1.659 + = 0 + = 2 + 273 68 + 473 60 + + + + = "Titanium" + = 22 + = 22 + = 2.3740000000000001 + = 0 + = 6 + 273 22 + 473 20 + 673 19 + 873 20 + 1073 21 + 1273 23 + + + + = "Tungsten" + = 182 + = 182 + = 2.5739999999999998 + = 0 + = 6 + 273 182 + 473 152 + 673 134 + 873 125 + 1073 118 + 1273 114 + + + + = "Uranium" + = 27 + = 27 + = 2.169 + = 0 + = 5 + 273 27 + 473 30 + 673 35 + 873 39 + 1073 45 + + + + = "Vanadium" + = 31 + = 31 + = 2.806 + = 0 + = 6 + 273 31 + 473 33 + 673 35 + 873 37 + 1073 40 + 1273 44 + + + + = "Zinc" + = 122 + = 122 + = 2.7719999999999998 + = 0 + = 3 + 273 122 + 473 112 + 673 102 + + + + = "Zirconium" + = 23 + = 23 + = 1.853 + = 0 + = 6 + 273 23 + 473 21 + 673 21 + 873 22 + 1073 24 + 1273 26 + + + + + = "Nonmetallic Solids" + + = "Aluminum Oxide" + = 40 + = 40 + = 3.0379999999999998 + = 0 + = 6 + 273 40 + 473 22 + 673 13 + 873 9.3000000000000007 + 1073 7.2999999999999998 + 1273 6.2000000000000002 + + + + = "Asbestos" + = 0.11 + = 0.11 + = 0.313 + = 0 + + + + = "Beryllium Oxide" + = 302 + = 302 + = 3.090 + = 0 + = 6 + 273 302 + 473 159 + 673 93 + 873 60 + 1073 41 + 1273 30 + + + + = "Bricks" + + = "Brick, Common" + = 0.69999999999999996 + = 0.69999999999999996 + = 1.3440000000000001 + = 0 + + + + = "Brick, Chrome" + = 2.2000000000000002 + = 2.2000000000000002 + = 2.52 + = 0 + = 5 + 273 2.2000000000000002 + 473 2.2999999999999998 + 673 2.3999999999999999 + 873 2.3999999999999999 + 1073 2.1000000000000001 + + + + = "Brick, Fireclay" + = 1 + = 1 + = 1.4490000000000001 + = 0 + = 2 + 273 1 + 1273 1.1000000000000001 + + + + = "Brick, Magnesite" + = 4 + = 4 + = 1.9199999999999999 + = 0 + = 6 + 273 4 + 473 3.6000000000000001 + 673 2.7999999999999998 + 873 2.3999999999999999 + 1073 2.1000000000000001 + 1273 1.8 + + + + = "Brick, Masonry" + = 0.66000000000000003 + = 0.66000000000000003 + = 1.6739999999999999 + = 0 + + + + = "Brick, Silica" + = 1.1000000000000001 + = 1.1000000000000001 + = 1.355 + = 0 + + + + + = "Carbon" + = 1.6000000000000001 + = 1.6000000000000001 + = 1.6020000000000001 + = 0 + = 6 + 273 1.6000000000000001 + 473 1.8999999999999999 + 673 2.2000000000000002 + 873 2.3999999999999999 + 1073 2.6000000000000001 + 1273 2.7999999999999998 + + + + = "Cement Mortar" + = 0.90000000000000002 + = 0.90000000000000002 + = 1.451 + = 0 + + + + = "Concrete" + = 1 + = 1 + = 1.5109999999999999 + = 0 + + + + = "Coal" + = 0.23999999999999999 + = 0.23999999999999999 + = 0.0016249999999999999 + = 0 + + + + = "Diamonds" + + = "Diamond Type I" + = 1000 + = 1000 + = 1.776 + = 0 + = 2 + 273 1000 + 473 300 + + + + = "Diamond Type IIa" + = 2650 + = 2650 + = 1.782 + = 0 + = 2 + 273 2650 + 473 1300 + + + + = "Diamond Type IIb" + = 1510 + = 1510 + = 1.6579999999999999 + = 0 + = 2 + 273 1510 + 473 780 + + + + + = "Earths" + + = "Clay" + = 1.3999999999999999 + = 1.3999999999999999 + = 1.2849999999999999 + = 0 + + + + = "Diatomaceous Earth" + = 1.3 + = 1.3 + = 0.34999999999999998 + = 0 + + + + = "Sand" + = 0.29999999999999999 + = 0.29999999999999999 + = 1.2050000000000001 + = 0 + + + + + = "Glasses" + + = "Corning Pyrex 7740" + = 1.1000000000000001 + = 1.1000000000000001 + = 1.616 + = 0 + = 4 + 273 1.1000000000000001 + 473 1.3 + 673 1.5 + 873 1.8999999999999999 + + + + = "Pyroceram" + = 4.0999999999999996 + = 4.0999999999999996 + = 2.0329999999999999 + = 0 + = 6 + 273 4.0999999999999996 + 473 3.6000000000000001 + 673 3.2000000000000002 + 873 3 + 1073 2.8999999999999999 + 1273 2.7999999999999998 + + + + = "Window" + = 0.83999999999999997 + = 0.83999999999999997 + = 2.2679999999999998 + = 0 + + + + + = "Ice" + = 2.2000000000000002 + = 2.2000000000000002 + = 1.756 + = 0 + + + + = "Insulations" + + = "Cork, granular" + = 0.044999999999999998 + = 0.044999999999999998 + = 0.30099999999999999 + = 0 + + + + = "Corkboard" + = 0.042999999999999997 + = 0.042999999999999997 + = 0.304 + = 0 + + + + = "Cellulose, loose" + = 0.037999999999999999 + = 0.037999999999999999 + = 0.093 + = 0 + + + + = "Feltboard" + = 0.1 + = 0.1 + = 0.179 + = 0 + + + + = "Glass Fiber" + = 0.035000000000000003 + = 0.035000000000000003 + = 0.026880000000000001 + = 0 + + + + = "Glass Wool" + = 0.037999999999999999 + = 0.037999999999999999 + = 0.016799999999999999 + = 0 + + + + = "Kapok" + = 0.035000000000000003 + = 0.035000000000000003 + = 0.207 + = 0 + + + + = "Magnesia, 85%" + = 0.065000000000000002 + = 0.065000000000000002 + = 0.179 + = 0 + = 2 + 273 0.065000000000000002 + 473 0.085000000000000006 + + + + = "Polystyrene" + = 0.025000000000000001 + = 0.025000000000000001 + = 0.051979999999999998 + = 0 + + + + = "Rubber, Foam" + = 0.029999999999999999 + = 0.029999999999999999 + = 0.2092 + = 0 + + + + = "Rock Wool" + = 0.058999999999999997 + = 0.058999999999999997 + = 0.084 + = 0 + + + + = "Sawdust" + = 0.058999999999999997 + = 0.058999999999999997 + = 0.336 + = 0 + + + + = "Vermiculite, loose" + = 0.058000000000000003 + = 0.058000000000000003 + = 0.16566 + = 0 + + + + + = "Magnesium Oxide" + = 53 + = 53 + = 3.1499999999999999 + = 0 + = 6 + 273 53 + 473 29 + 673 18 + 873 12 + 1073 8.8000000000000007 + 1273 7.2999999999999998 + + + + = "Plaster" + = 0.5 + = 0.5 + = 1.3600000000000001 + = 0 + + + + = "Quartz, fused" + = 1.3 + = 1.3 + = 1.639 + = 0 + = 6 + 273 1.3 + 473 1.6000000000000001 + 673 1.8999999999999999 + 873 2.2999999999999998 + 1073 3.2000000000000002 + 1273 3.7999999999999998 + + + + = "Rocks" + + = "Granite" + = 3 + = 3 + = 2.165 + = 0 + + + + = "Limestone" + = 2 + = 2 + = 2.0699999999999998 + = 0 + + + + = "Marble" + = 2.7000000000000002 + = 2.7000000000000002 + = 2.650 + = 0 + + + + = "Sandstone" + = 2.7999999999999998 + = 2.7999999999999998 + = 1.628 + = 0 + + + + + = "Rubber, hard" + = 0.16 + = 0.16 + = 2.3999999999999999 + = 0 + + + + = "Skin, human" + = 0.37 + = 0.37 + = 2.666 + = 0 + + + + = "Snow" + + = "Snow, loose" + = 0.050000000000000003 + = 0.050000000000000003 + = 0.2092 + = 0 + + + + = "Snow, packed" + = 0.19 + = 0.19 + = 1.151 + = 0 + + + + + = "Teflon-min-heat-capacity" + = 0.34999999999999998 + = 0.34999999999999998 + = 2.5800000000000001 + = 0 + + + + = "Teflon-max-heat-capacity" + = 0.34999999999999998 + = 0.34999999999999998 + = 3.2200000000000002 + = 0 + + + + = "Woods" + + = "Balsa-min-heat-capacity" + = 0.055 + = 0.055 + = 0.29913000000000001 + = 0 + + + + = "Balsa-max-heat-capacity" + = 0.055 + = 0.055 + = 0.73631999999999997 + = 0 + + + + = "Fir" + = 0.11 + = 0.11 + = 1.6319999999999999 + = 0 + + + + = "Cypress" + = 0.097000000000000003 + = 0.097000000000000003 + = 1.0580000000000001 + = 0 + + + + = "Maple" + = 0.17000000000000001 + = 0.17000000000000001 + = 1.6339999999999999 + = 0 + + + + = "Oak" + = 0.17000000000000001 + = 0.17000000000000001 + = 1.4339999999999999 + = 0 + + + + = "Pine, yellow" + = 0.14999999999999999 + = 0.14999999999999999 + = 1.7949999999999999 + = 0 + + + + = "Pine, white" + = 0.11 + = 0.11 + = 1.22 + = 0 + + + + = "Plywood" + = 0.12 + = 0.12 + = 0.66000000000000003 + = 0 + + + + + = "Wool" + = 0.037999999999999999 + = 0.037999999999999999 + = 0.041 + = 0 + + + + + = "Liquid Metals" + + = "Bismuth, liquid" + = 16.800000000000001 + = 16.800000000000001 + = 1.4199999999999999 + = 0 + = 6 + 545 16.800000000000001 + 600 16.399999999999999 + 700 15.6 + 800 15.6 + 900 15.6 + 1000 15.6 + + + + = "Lead, liquid" + = 15.5 + = 15.5 + = 1.601 + = 0 + = 5 + 601 15.5 + 700 17.399999999999999 + 800 19 + 900 20.300000000000001 + 1000 21.5 + + + + = "Mercury" + = 142 + = 142 + = 1.863 + = 0 + = 7 + 234 142 + 273 140 + 300 139 + 350 138 + 400 137 + 500 136 + 600 134 + + + + = "Lithium, liquid" + = 43 + = 43 + = 2.1469999999999998 + = 0 + = 7 + 454 43 + 500 44 + 600 48 + 700 51 + 800 54 + 900 57 + 1000 60 + + + + = "Potassium, liquid" + = 55 + = 55 + = 0.6724 + = 0 + = 8 + 337 55 + 400 52 + 500 48 + 600 44 + 700 40 + 800 37 + 900 34 + 1000 31 + + + + = "Sodium, liquid" + = 88 + = 88 + = 1.284 + = 0 + = 8 + 371 88 + 400 87 + 500 82 + 600 76 + 700 72 + 800 67 + 900 63 + 1000 58 + + + + + = "Saturated Liquids" + + = "Ammonia" + = 0.54600000000000004 + = 0.54600000000000004 + = 2.8799999999999999 + = 0 + = 5 + 233 0.54600000000000004 + 253 0.54600000000000004 + 273 0.54000000000000004 + 293 0.52100000000000002 + 313 0.49299999999999999 + + + + = "Ethyl Alcohol" + = 0.186 + = 0.186 + = 1.890 + = 0 + = 7 + 233 0.186 + 253 0.17899999999999999 + 273 0.17399999999999999 + 293 0.16800000000000001 + 313 0.16200000000000001 + 333 0.156 + 353 0.14999999999999999 + + + + = "Ethylene Glycol" + = 0.254 + = 0.254 + = 2.6600000000000001 + = 0 + = 6 + 273 0.254 + 293 0.25700000000000001 + 313 0.25900000000000001 + 333 0.26200000000000001 + 353 0.26500000000000001 + 373 0.26700000000000002 + + + + = "Freon-12" + = 0.069000000000000006 + = 0.069000000000000006 + = 1.296 + = 0 + = 5 + 233 0.069000000000000006 + 253 0.070999999999999994 + 273 0.072999999999999995 + 293 0.072999999999999995 + 313 0.069000000000000006 + + + + = "Glycerin" + = 0.28199999999999997 + = 0.28199999999999997 + = 3.016 + = 0 + = 4 + 253 0.28199999999999997 + 273 0.28399999999999997 + 293 0.28699999999999998 + 313 0.28999999999999998 + + + + = "Unused Engine Oil" + = 0.14699999999999999 + = 0.14699999999999999 + = 1.669 + = 0 + = 2 + 273 0.14699999999999999 + 433 0.13200000000000001 + + + + = "Water" + = 0.56399999999999995 + = 0.56399999999999995 + = 4.1840000000000002 + = 0 + = 12 + 273.19999999999999 0.56399999999999995 + 280 0.58199999999999996 + 300 0.60799999999999998 + 320 0.63700000000000001 + 340 0.65900000000000003 + 360 0.67400000000000004 + 373.19999999999999 0.68100000000000005 + 400 0.68600000000000005 + 450 0.67300000000000004 + 500 0.63500000000000001 + 550 0.57099999999999995 + 600 0.48099999999999998 + + + + + = "Gases at 1 atm" + + = "Air" + = 0.018100000000000002 + = 0.018100000000000002 + = 0.0011850000000000001 + = 0 + = 18 + 200 0.018100000000000002 + 250 0.0223 + 300 0.026100000000000002 + 350 0.029700000000000001 + 400 0.033099999999999997 + 450 0.036299999999999999 + 500 0.0395 + 550 0.042599999999999999 + 600 0.045600000000000002 + 700 0.051299999999999998 + 800 0.056899999999999999 + 900 0.0625 + 1000 0.067199999999999996 + 1200 0.075899999999999995 + 1400 0.083500000000000005 + 1600 0.090399999999999994 + 1800 0.097000000000000003 + 2000 0.1032 + + + + = "Ammonia" + = 0.015299999999999999 + = 0.015299999999999999 + = 0.0016827420000000001 + = 0 + = 9 + 200 0.015299999999999999 + 300 0.0246 + 400 0.036400000000000002 + 500 0.050599999999999999 + 600 0.065600000000000006 + 700 0.081100000000000005 + 800 0.097699999999999995 + 900 0.11459999999999999 + 1000 0.13170000000000001 + + + + = "Argon" + = 0.0124 + = 0.0124 + = 0.00084699999999999999 + = 0 + = 14 + 200 0.0124 + 300 0.0177 + 400 0.0223 + 500 0.0264 + 600 0.030099999999999998 + 700 0.033599999999999998 + 800 0.036900000000000002 + 900 0.039800000000000002 + 1000 0.042700000000000002 + 1200 0.048099999999999997 + 1400 0.053499999999999999 + 1600 0.058799999999999998 + 1800 0.064100000000000004 + 2000 0.069199999999999998 + + + + = "Carbon Dioxide" + = 0.0094999999999999998 + = 0.0094999999999999998 + = 0.0015330000000000001 + = 0 + = 7 + 200 0.0094999999999999998 + 500 0.032300000000000002 + 600 0.040300000000000002 + 800 0.056000000000000001 + 1000 0.068000000000000005 + 1200 0.078 + 1400 0.086699999999999999 + + + + = "Carbon Monoxide" + = 0.017500000000000002 + = 0.017500000000000002 + = 0.0011839999999999999 + = 0 + = 6 + 200 0.017500000000000002 + 400 0.032300000000000002 + 600 0.044400000000000002 + 800 0.054899999999999997 + 1000 0.064399999999999999 + 1200 0.073800000000000004 + + + + = "Helium" + = 0.115 + = 0.115 + = 0.00084400000000000002 + = 0 + = 6 + 200 0.115 + 400 0.17999999999999999 + 700 0.27800000000000002 + 1000 0.36299999999999999 + 1400 0.46899999999999997 + 2000 0.62 + + + + = "Hydrogen" + = 0.128 + = 0.128 + = 0.0011720000000000001 + = 0 + = 6 + 200 0.128 + 400 0.221 + 600 0.29099999999999998 + 900 0.39400000000000002 + 1000 0.42799999999999999 + 1200 0.495 + + + + = "Nitrogen" + = 0.0183 + = 0.0183 + = 0.0011846579999999999 + = 0 + = 7 + 200 0.0183 + 400 0.032500000000000001 + 600 0.0441 + 800 0.054100000000000002 + 1000 0.063100000000000003 + 1200 0.071300000000000002 + 1400 0.079699999999999993 + + + + = "Oxygen" + = 0.018200000000000001 + = 0.018200000000000001 + = 0.0011969999999999999 + = 0 + = 7 + 200 0.018200000000000001 + 400 0.034200000000000001 + 600 0.048000000000000001 + 800 0.060299999999999999 + 1000 0.0717 + 1200 0.082100000000000006 + 1400 0.092100000000000001 + + + + = "Steam at 373.15 K" + = 0.0264 + = 0.0264 + = 0.0012430080000000001 + = 0 + = 7 + 400 0.0264 + 500 0.035700000000000003 + 600 0.046399999999999997 + 700 0.057200000000000001 + 800 0.068599999999999994 + 900 0.078 + 1000 0.086999999999999994 + + + diff --git a/release/init.lua b/release/init.lua new file mode 100644 index 0000000..a7b62fa --- /dev/null +++ b/release/init.lua @@ -0,0 +1,679 @@ +-- Define some common quantities for use in Lua + + uo=PI*4.e-7; -- magnetic permeability of free space + eo=8.85418781762e-12; -- electrical permittivity of free space + Pi=PI; pi=PI; -- various ways that one might possibly denote PI + +-- Useful unit definitions + + meter=1; + meters=meter; Meter=meter; Meters=meter; + + inch=0.0254; + inches=inch; Inch=inch; Inches=inch; in=inch; + + cm=0.01; + centimeter=cm; centimeters=cm; Centimeters=cm; Centimeter=cm; + + mm=0.001; + millimeters=mm; millimeter=mm; Millimeter=mm; Millimeters=mm; milimeter=mm; milimeters=mm; + + um=0.000001; + micrometer=um; Micrometer=um; micrometers=um; Micrometers=um; + micron=um; Micron=um; microns=um; Microns=um; + + mil=0.001*inch; + mils=mil; Mils=mil; Mil=mil; + + Tesla = 1; + mTesla = 0.001; + Gauss = 0.0001; + kGauss = 0.1; + AmpMeter = 1; + kAmpMeter = 1000; + Oersted = 250/PI; + kOersted = 1000*Oersted; + +-- Useful functions + + -- Function to determine the diameter in mm of a specified AWG wire gauge + function AWG(awg) return 8.2514694*exp(-0.115943*awg) end + + -- Function to read in BH points for a material from a file + -- Contributed by Dr. Henning Kiel + function mi_setbhpointsfromfile(filename, materialname, unitb, unith, order) + fact_b = Tesla + fact_h = AmpMeter + bh = 1 + + if unitb ~= nil then + fact_b = unitb + end + if unith ~= nil then + fact_h = unith + end + if order == 1 then + bh = 0 + end + + bhfile = openfile(filename,"r") + if bhfile ~= nil then + mi_clearbhpoints(materialname) + if bh == 1 then + b, h = read(bhfile,"*n","*n") + else + h, b = read(bhfile,"*n","*n") + end + while b ~= nil do + mi_addbhpoint(materialname, b, h) + if bh == 1 then + b, h = read(bhfile,"*n","*n") + else + h, b = read(bhfile,"*n","*n") + end + end + closefile(bhfile) + end + end + + + +--permeability tables used to create asymptotic boundary conditions + uAx0 = {{10.06344410876133}, + {0.18870625462846807, 39.997500411566335}, + {4.374794457961015, 0.07511795918154143, 85.85566438727763}, + {0.28509610532711227, 12.493269046515916, 0.051874008856059424, 147.65207370446487}, + {3.0607674892527865, 0.11237818729856126, 22.026456394011774, 0.042316694272791736, 225.43020812455183}, + {0.3748159380792134, 8.172423914252851, 0.07400271964825651, 33.01915762825664, 0.037123381446484645, 319.2335657378115}, + {2.4089242666740582, 0.14929929105743517, 13.817592213008757, 0.05821722458526954, 45.655954531895645, 0.03386729523177279, 429.0464280099345}, + {0.4577193805314985, 6.152383059834071, 0.09519535460494778, 19.79502033933107, 0.04958213970480729, 60.00201778458946, 0.031639182082296755, 554.8893696637082}, + {2.0187133623041955, 0.1872419300750821, 10.322990689266506, 0.07322869764123259, 26.290072452745143, 0.0441395144643266, 76.08450824714102, 0.030019516604331355, 696.7499046385117}, + {0.5332409067449392, 4.931200653946399, 0.11642450959044752, 14.522111149156393, 0.0612363797098224, 33.37497351570902, 0.04039926157266519, 93.91981759395829, 0.028790057140879656, 854.6396765772441}, + {1.7619160942694887, 0.2265234822569949, 8.305694616317721, 0.08811132253969434, 18.911084918162924, 0.053672710920365976, 41.08415574149624, 0.03767250616088464, 113.51592772683063, 0.02782511889284403, 1028.551339640375}, + {0.6010640087773658, 4.100907065931257, 0.13795163994918203, 11.604922157909524, 0.07274062063786199, 23.5602014704398, 0.048468764953025635, 49.437385787628045, 0.035597711447375925, 134.87895858524496, 0.02704793878013551, 1218.4906640339432}}; + u2D0 = {{10.523809523809524}, + {0.14531359011819187, 32.14290974079077}, + {5.14939698507243, 0.053268993904189134, 54.10636468483519}, + {0.2419609512179885, 13.681253040072905, 0.03301443572330777, 76.07498920312688}, + {3.4661091134486472, 0.09209257399023746, 21.797339506447933, 0.02406322785653838, 98.05449854377491}, + {0.3336928992521675, 9.023667719158183, 0.05789695118959376, 29.573300006204246, 0.018966499540708268, 120.04039743815603}, + {2.649899689611667, 0.12953316809300527, 14.398967120915913, 0.04288257435633827, 37.197476986533054, 0.01566424606410637, 142.03015659052124}, + {0.4194212714207981, 6.739646495379991, 0.0807327554079406, 19.40925290947297, 0.034255287061558344, 44.73740232258131, 0.013346899201001426, 164.02239651319712}, + {2.1751715650719827, 0.16743379223593088, 10.885675868734184, 0.05987838745046158, 24.237375183864483, 0.028600398122246736, 52.225223074983184, 0.0116295354236669, 186.01632084646832}, + {0.4982294821100038, 5.3544134782776664, 0.10291820111116401, 14.696545405270147, 0.048003097591685244, 28.95632726953973, 0.024587012459820066, 59.67849241525681, 0.010305182059498453, 208.01143556937637}, + {1.8696806205952006, 0.2063934470334104, 8.775890039744148, 0.07607619682670601, 18.328256642424236, 0.04023921548166901, 33.60353647639198, 0.021581843440607016, 67.10765452494896, 0.009252450549701629, 230.0074236348898}, + {0.5695628007801712, 4.41799489542221, 0.12499429930905502, 11.902080658968998, 0.06098009575496433, 21.847988015751035, 0.03472775671050834, 38.20087849238854, 0.01924286302232932, 74.51932204012905, 0.00839537165467591, 252.00407064779833}}; + uAx1 = {{0.09090909090909091}, + {10.050515900211503, 0.04349612665401649}, + {0.16015012096541084, 31.212316587655547, 0.035617897941640685}, + {5.075223589959199, 0.06747975164123507, 58.83076738028796, 0.032496412704901965}, + {0.24983741484804536, 13.959519296714365, 0.04850942160789329, 93.62679411332631, 0.030834135426565015}, + {3.438673996192938, 0.10007632616355028, 23.68319910391683, 0.040588823403447945, 135.81886600712073, 0.029800226566381535}, + {0.33861114976053774, 9.11830816329029, 0.06748841981310061, 34.53152988922068, 0.03624009732510784, 185.4917052298402, 0.02909733301094425}, + {2.6364338943965455, 0.13486508168984512, 15.097445398169498, 0.05395605788825772, 46.75319306175651, 0.03349209595847733, 242.6651438041285, 0.028587355212278894}, + {0.4227311219273812, 6.773013674320017, 0.08745530894064872, 21.301429520550652, 0.04651420711694375, 60.44151623434645, 0.03160001126426384, 307.3631853353253, 0.028201318378415573}, + {2.1675591338727647, 0.171316009911807, 11.198891625678383, 0.0680375716016307, 27.948228063433724, 0.041804487302954434, 75.63799976250523, 0.030217675069207188, 379.586805599126, 0.027898435150547626}, + {0.5005548322806631, 5.365891158623955, 0.1079474936583888, 15.594898520264833, 0.05739172309462815, 35.12584682017268, 0.03855673261275498, 92.36682653198929, 0.029164062639383995, 459.3468429136272, 0.027654812310257123}, + {1.864938491614021, 0.20938145992414733, 8.933546101982833, 0.08240945574778373, 20.142380617987286, 0.05066029544301638, 42.87550155678245, 0.036182409831124134, 110.63472923382548, 0.0283338992149914, 546.6150102543896, 0.027453323354323905}}; + u2D1 = {{0.09502262443438914}, + {6.88166880459455, 0.031111060201589526}, + {0.19419749592018187, 18.77264665066931, 0.018482113995736214}, + {4.13289828365353, 0.07309272016758717, 30.28978015498877, 0.013144924639159823}, + {0.28850793996067764, 10.858638831248303, 0.04587715852680953, 41.55718451247941, 0.010198410219328852}, + {2.9967673937356176, 0.1108196834283798, 17.27206665382645, 0.0338142851758244, 52.724541914214335, 0.008330528899783033}, + {0.37737277525645235, 7.720030434644211, 0.0694494258951436, 23.31949550539958, 0.026883543752277105, 63.83965087550882, 0.0070407582729502555}, + {2.384237702546398, 0.14837573304995255, 12.386546277094604, 0.05152181760881001, 29.192574288770942, 0.022352660997929614, 74.923770274119, 0.006096728349565376}, + {0.45973385090978197, 5.972510009155741, 0.09186384125878651, 16.700516539917132, 0.04125859307841753, 34.96454824599637, 0.019147835875477914, 85.98795769304176, 0.005375872372109578}, + {2.007107238545973, 0.1867618188354154, 9.71645432200938, 0.06804320147518493, 20.83198897925314, 0.0345347664671527, 40.67187917337226, 0.01675645545872318, 97.03855732255441, 0.004807428001555607}, + {0.5348507060428623, 4.845115067234294, 0.11394855626850516, 13.144715978348659, 0.05456056293348216, 24.85137913425649, 0.029758772583431677, 46.33524484374972, 0.014901429756097718, 108.07947522964582, 0.004347685758123113}, + {1.755732640246568, 0.22634702476369292, 8.00036486086015, 0.08401892313227052, 16.39879353450492, 0.04577080504067754, 28.795410205618264, 0.026177408464552673, 51.96731893999375, 0.013419338402750022, 119.11324967287628, 0.003968189868637491}}; + +function mi_drawarc(x1,y1,x2,y2,tta,dtta) + mi_addnode(x1,y1); + mi_addnode(x2,y2); + mi_addarc(x1,y1,x2,y2,tta,dtta); +end + +function mi_drawline(x1,y1,x2,y2) + mi_addnode(x1,y1); + mi_addnode(x2,y2); + mi_addsegment(x1,y1,x2,y2); +end + +function mi_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R, n + + x0, x1, y0, y1 = mi_getboundingbox(); + flag, p1, p2, p3 = mi_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + bctype=0; + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + mi_drawarc(x, y + R, x, y - R, 180, 1); + else + mi_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + mi_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + mi_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + mi_addblocklabel(x+re(z),y+im(z)); + mi_selectlabel(x+re(z),y+im(z)); + mi_setblockprop("u" .. k, 1, 0, "", 0, 0, 1); + mi_clearselected(); + if(flag == 0) then + if (bctype==0) then + mi_addmaterial("u" .. k, u2D0[n][k]); + else + mi_addmaterial("u" .. k, u2D1[n][k]); + end + mi_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + mi_addmaterial("u" .. k, uAx0[n][k]); + else + mi_addmaterial("u" .. k, uAx1[n][k]); + end + end + end + + if (bctype==0) then + mi_addboundprop("A=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + mi_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + mi_selectarcsegment(-1.1*R+x, y); + end + mi_setarcsegmentprop(1, "A=0", 0, 0); + mi_clearselected(); + end + + mi_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for electrostatic problems + +function ei_drawarc(x1,y1,x2,y2,tta,dtta) + ei_addnode(x1,y1); + ei_addnode(x2,y2); + ei_addarc(x1,y1,x2,y2,tta,dtta); +end + +function ei_drawline(x1,y1,x2,y2) + ei_addnode(x1,y1); + ei_addnode(x2,y2); + ei_addsegment(x1,y1,x2,y2); +end + +function ei_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = ei_getboundingbox(); + flag, p1, p2, p3 = ei_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + ei_drawarc(x, y + R, x, y - R, 180, 1); + else + ei_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + ei_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + ei_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + ei_addblocklabel(x+re(z),y+im(z)); + ei_selectlabel(x+re(z),y+im(z)); + ei_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + ei_clearselected(); + if(flag == 0) then + if (bctype==0) then + ei_addmaterial("e" .. k, u2D1[n][k]); + else + ei_addmaterial("e" .. k, u2D0[n][k]); + end + ei_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + ei_addmaterial("e" .. k, uAx1[n][k]); + else + ei_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + ei_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + ei_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + ei_selectarcsegment(-1.1*R+x, y); + end + ei_setarcsegmentprop(1, "V=0", 0, 0); + ei_clearselected(); + end + + ei_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for current flow problems + +function ci_drawarc(x1,y1,x2,y2,tta,dtta) + ci_addnode(x1,y1); + ci_addnode(x2,y2); + ci_addarc(x1,y1,x2,y2,tta,dtta); +end + +function ci_drawline(x1,y1,x2,y2) + ci_addnode(x1,y1); + ci_addnode(x2,y2); + ci_addsegment(x1,y1,x2,y2); +end + +function ci_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = ci_getboundingbox(); + flag, p1, p2, p3 = ci_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + ci_drawarc(x, y + R, x, y - R, 180, 1); + else + ci_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + ci_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + ci_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + ci_addblocklabel(x+re(z),y+im(z)); + ci_selectlabel(x+re(z),y+im(z)); + ci_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + ci_clearselected(); + if(flag == 0) then + if (bctype==0) then + ci_addmaterial("e" .. k, u2D1[n][k]); + else + ci_addmaterial("e" .. k, u2D0[n][k]); + end + ci_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + ci_addmaterial("e" .. k, uAx1[n][k]); + else + ci_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + ci_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + ci_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + ci_selectarcsegment(-1.1*R+x, y); + end + ci_setarcsegmentprop(1, "V=0", 0, 0); + ci_clearselected(); + end + + ci_zoomnatural(); +end + +--functions used to create asymptotic boundary conditions for heat flow problems + +function hi_drawarc(x1,y1,x2,y2,tta,dtta) + hi_addnode(x1,y1); + hi_addnode(x2,y2); + hi_addarc(x1,y1,x2,y2,tta,dtta); +end + +function hi_drawline(x1,y1,x2,y2) + hi_addnode(x1,y1); + hi_addnode(x2,y2); + hi_addsegment(x1,y1,x2,y2); +end + +function hi_makeABC(enn,arr,ex,wye,bc) + + local k, d, dp, z, r, x0, x1, y0, y1, flag, p1, p2, p3, x, y, R + + x0, x1, y0, y1 = hi_getboundingbox(); + flag, p1, p2, p3 = hi_getprobleminfo(); + + -- unpack parameters; + if (enn == nil) then + n=7; + else + if (enn>12) then + n=12; + elseif (enn<1) then + n=1; + else + n=enn; + end + end + + if (bc == nil) then + if (flag == 0) then + -- if 2D, use Neumann-type BC by default + bctype=1; + else + -- if Axisymmetric, use Dirichlet-type BC by default + bctype=0; + end + else + bctype=bc; + end + + if(flag == 0) then -- 2D planar case + + if (arr == nil) then + R=(3/4)*abs((x0+I*y0)-(x1+I*y1)); + else + R = arr; + end + + if (ex == nil) then + x=(x0+x1)/2; + else + x=ex; + end + + if (wye == nil) then + y=(y0+y1)/2; + else + y=wye; + end + + else -- Axi case + x=0; + if (wye ~= nil) then + y=wye; + R=arr; + elseif (ex ~= nil) then + y=ex; + R=arr; + elseif (arr ~= nil) then + y=(y0+y1)/2; + R=arr; + else + y=(y0+y1)/2; + R=(3/2)*abs(x1+I*(y1-y0)/2); + end + end + + -- draw left boundary of interior domain + if (flag == 0) then + hi_drawarc(x, y + R, x, y - R, 180, 1); + else + hi_drawline(0, y-1.1*R, 0, y+1.1*R); + end + + -- draw right boundary of interior domain + hi_drawarc(x, y - R, x, y + R, 180, 1); + + d = 0.1*R/(2*n); + + for k = 1,n do + r = R*(1 + (2*k - 1)/(20*n)); + hi_drawarc(x, y - r - d, x, y + r + d, 180, 1); + z = r*exp(I*(90/(n+1))*k*Pi/180); + hi_addblocklabel(x+re(z),y+im(z)); + hi_selectlabel(x+re(z),y+im(z)); + hi_setblockprop("e" .. k, 1, 0, "", 0, 0, 1); + hi_clearselected(); + if(flag == 0) then + if (bctype==0) then + hi_addmaterial("e" .. k, u2D1[n][k]); + else + hi_addmaterial("e" .. k, u2D0[n][k]); + end + hi_drawarc(x, y + r + d, x, y - r - d, 180, 1); + else + if (bctype==0) then + hi_addmaterial("e" .. k, uAx1[n][k]); + else + hi_addmaterial("e" .. k, uAx0[n][k]); + end + end + end + + if (bctype==0) then + hi_addboundprop("V=0", 0, 0, 0, 0, 0, 0, 0, 0, 0); + hi_selectarcsegment(1.1*R+x, y); + if(flag == 0) then + hi_selectarcsegment(-1.1*R+x, y); + end + hi_setarcsegmentprop(1, "V=0", 0, 0); + hi_clearselected(); + end + + hi_zoomnatural(); +end + +-- convenience functions + +function mi_drawrectangle(x1,y1,x2,y2) + mi_drawline(x1,y1,x2,y1); + mi_drawline(x2,y1,x2,y2); + mi_drawline(x2,y2,x1,y2); + mi_drawline(x1,y2,x1,y1); +end + +function ei_drawrectangle(x1,y1,x2,y2) + ei_drawline(x1,y1,x2,y1); + ei_drawline(x2,y1,x2,y2); + ei_drawline(x2,y2,x1,y2); + ei_drawline(x1,y2,x1,y1); +end + +function ci_drawrectangle(x1,y1,x2,y2) + ci_drawline(x1,y1,x2,y1); + ci_drawline(x2,y1,x2,y2); + ci_drawline(x2,y2,x1,y2); + ci_drawline(x1,y2,x1,y1); +end + +function hi_drawrectangle(x1,y1,x2,y2) + hi_drawline(x1,y1,x2,y1); + hi_drawline(x2,y1,x2,y2); + hi_drawline(x2,y2,x1,y2); + hi_drawline(x1,y2,x1,y1); +end \ No newline at end of file diff --git a/release/license.txt b/release/license.txt new file mode 100644 index 0000000..5d33c0d --- /dev/null +++ b/release/license.txt @@ -0,0 +1,412 @@ + +Finite Element Method Magnetics is distributed under +the terms of the Aladdin Free Public License: + +------------------------------------------------------ + +Aladdin Free Public License +(Version 8, November 18, 1999) +Copyright (C) 1994, 1995, 1997, 1998, 1999 +Aladdin Enterprises,Menlo Park, California, U.S.A. +All rights reserved. + +NOTE: This License is not the same as any of the GNU +Licenses published by the Free Software Foundation. +Its terms are substantially different from those of +the GNU Licenses. If you are familiar with the GNU +Licenses, please read this license with extra care. + +Aladdin Enterprises hereby grants to anyone the +permission to apply this License to their own work, +as long as the entire License (including the above +notices and this paragraph) is copied with no +changes, additions, or deletions except for changing +the first paragraph of Section 0 to include a +suitable description of the work to which the +license is being applied and of the person or entity +that holds the copyright in the work, and, if the +License is being applied to a work created in a +country other than the United States, replacing the +first paragraph of Section 6 with an appropriate +reference to the laws of the appropriate country. + +0. Subject Matter + +This License applies to the computer program known +as "Finite Element Method Magnetics." The "Program", +below, refers to such program. The Program is a +copyrighted work whose copyright is held by David C. +Meeker of Natick, MA, dmeeker@ieee.org (the +"Licensor"). Please note that the program Triangle, +written by Jonathan Shewchuk and used by FEMM +for the purposes of mesh generation is NOT covered +by this license and is subject to its own licensure terms. +The licensure terms for Triangle are attached after +this license. The Lua scripting language used by +FEMM is also distributed under its own licensing +terms. The licensing terms of Lua are also attached. + +A "work based on the Program" means either the +Program or any derivative work of the Program, as +defined in the United States Copyright Act of 1976, +such as a translation or a modification. + +BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY +WORK BASED ON THE PROGRAM), YOU INDICATE YOUR +ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL ITS +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR +MODIFYING THE PROGRAM OR WORKS BASED ON IT. NOTHING +OTHER THAN THIS LICENSE GRANTS YOU PERMISSION TO +MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE +WORKS. THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU +DO NOT ACCEPT THESE TERMS AND CONDITIONS, DO NOT +MODIFY OR DISTRIBUTE THE PROGRAM. + +1. Licenses. + +Licensor hereby grants you the following rights, +provided that you comply with all of the +restrictions set forth in this License and provided, +further, that you distribute an unmodified copy of +this License with the Program: + +(a) You may copy and distribute literal (i.e., +verbatim) copies of the Program's source code as you +receive it throughout the world, in any medium. + +(b) You may modify the Program, create works based +on the Program and distribute copies of such +throughout the world, in any medium. + +2. Restrictions. + +This license is subject to the following restrictions: + +(a) Distribution of the Program or any work based on +the Program by a commercial organization to any +third party is prohibited if any payment is made in +connection with such distribution, whether directly +(as in payment for a copy of the Program) or +indirectly (as in payment for some service related +to the Program, or payment for some product or +service that includes a copy of the Program "without +charge"; these are only examples, and not an +exhaustive enumeration of prohibited activities). +The following methods of distribution involving +payment shall not in and of themselves be a +violation of this restriction: + +(i) Posting the Program on a public access + information storage and retrieval service for + which a fee is received for retrieving + information (such as an on-line service), + provided that the fee is not content- dependent + (i.e., the fee would be the same for retrieving + the same volume of information consisting of + random data) and that access to the service and + to the Program is available independent of any + other product or service. An example of a + service that does not fall under this section + is an on-line service that is operated by a + company and that is only available to customers + of that company. (This is not an exhaustive + enumeration.) + +(ii) Distributing the Program on removable + computer-readable media, provided that the + files containing the Program are reproduced + entirely and verbatim on such media, that all + information on such media be redistributable + for non-commercial purposes without charge, and + that such media are distributed by themselves + (except for accompanying documentation) + independent of any other product or service. + Examples of such media include CD-ROM, magnetic + tape, and optical storage media. (This is not + intended to be an exhaustive list.) An example + of a distribution that does not fall under this + section is a CD-ROM included in a book or + magazine. (This is not an exhaustive + enumeration.) + +(b) Activities other than copying, distribution and +modification of the Program are not subject to this +License and they are outside its scope. Functional +use (running) of the Program is not restricted, and +any output produced through the use of the Program +is subject to this license only if its contents +constitute a work based on the Program (independent +of having been made by running the Program). + +(c) You must meet all of the following conditions +with respect to any work that you distribute or +publish that in whole or in part contains or is +derived from the Program or any part thereof ("the +Work"): + +(i) If you have modified the Program, you must cause + the Work to carry prominent notices stating + that you have modified the Program's files and + the date of any change. In each source file + that you have modified, you must include a + prominent notice that you have modified the + file, including your name, your e-mail address + (if any), and the date and purpose of the + change; + +(ii) You must cause the Work to be licensed as a + whole and at no charge to all third parties + under the terms of this License; + +(iii) If the Work normally reads commands + interactively when run, you must cause it, at + each time the Work commences operation, to + print or display an announcement including an + appropriate copyright notice and a notice that + there is no warranty (or else, saying that you + provide a warranty). Such notice must also + state that users may redistribute the Work only + under the conditions of this License and tell + the user how to view the copy of this License + included with the Work. (Exceptions: if the + Program is interactive but normally prints or + displays such an announcement only at the + request of a user, such as in an "About box", + the Work is required to print or display the + notice only under the same circumstances; if + the Program itself is interactive but does not + normally print such an announcement, the Work + is not required to print an announcement.); + +(iv) You must accompany the Work with the complete + corresponding machine-readable source code, + delivered on a medium customarily used for + software interchange. The source code for a + work means the preferred form of the work for + making modifications to it. For an executable + work, complete source code means all the source + code for all modules it contains, plus any + associated interface definition files, plus the + scripts used to control compilation and + installation of the executable code. If you + distribute with the Work any component that is + normally distributed (in either source or + binary form) with the major components + (compiler, kernel, and so on) of the operating + system on which the executable runs, you must + also distribute the source code of that + component if you have it and are allowed to do + so; + +(v) If you distribute any written or printed + material at all with the Work, such material + must include either a written copy of this + License, or a prominent written indication that + the Work is covered by this License and written + instructions for printing and/or displaying the + copy of the License on the distribution medium; + +(vi) You may not impose any further restrictions on + the recipient's exercise of the rights granted + herein. If distribution of executable or + object code is made by offering the equivalent + ability to copy from a designated place, then + offering equivalent ability to copy the source + code from the same place counts as distribution + of the source code, even though third parties + are not compelled to copy the source code along + with the object code. + +3. Reservation of Rights. + +No rights are granted to the Program except as +expressly set forth herein. You may not copy, +modify, sublicense, or distribute the Program except +as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense or +distribute the Program is void, and will +automatically terminate your rights under this +License. However, parties who have received copies, +or rights, from you under this License will not have +their licenses terminated so long as such parties +remain in full compliance. + +4. Other Restrictions. + +If the distribution and/or use of the Program is +restricted in certain countries for any reason, +Licensor may add an explicit geographical +distribution limitation excluding those countries, +so that distribution is permitted only in or among +countries not thus excluded. In such case, this +License incorporates the limitation as if written in +the body of this License. + +5. Limitations. + +THE PROGRAM IS PROVIDED TO YOU "AS IS," WITHOUT +WARRANTY. THERE IS NO WARRANTY FOR THE PROGRAM, +EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR +AGREED TO IN WRITING WILL LICENSOR, OR ANY OTHER +PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT +LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH +ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +6. General. + +This License is governed by the laws of the +Commonwealth of Massachusetts, U.S.A., excluding +choice of law rules. + +If any part of this License is found to be in +conflict with the law, that part shall be +interpreted in its broadest meaning consistent with +the law, and no other parts of the License shall be +affected. + +For United States Government users, the Program is +provided with RESTRICTED RIGHTS. If you are a unit +or agency of the United States Government or are +acquiring the Program for any such unit or agency, +the following apply: + +If the unit or agency is the Department of Defense +("DOD"), the Program and its documentation are +classified as "commercial computer software" and +"commercial computer software documentation" +respectively and, pursuant to DFAR Section 227.7202, +the Government is acquiring the Program and its +documentation in accordance with the terms of this +License. If the unit or agency is other than DOD, +the Program and its documentation are classified as +"commercial computer software" and "commercial +computer software documentation" respectively and, +pursuant to FAR Section 12.212, the Government is +acquiring the Program and its documentation in +accordance with the terms of this License. + +------------------------------------------------------ + +Triangle +A Two-Dimensional Quality Mesh Generator +and Delaunay Triangulator. +Version 1.3 + +Copyright 1996 Jonathan Richard Shewchuk +School of Computer Science +Carnegie Mellon University +5000 Forbes Avenue +Pittsburgh, Pennsylvania 15213-3891 +Please send bugs and comments to jrs@cs.cmu.edu + +Created as part of the Archimedes project (tools for +parallel FEM). Supported in part by NSF Grant +CMS-9318163 and an NSERC 1967 Scholarship. There is +no warranty whatsoever. Use at your own risk. + +Triangle generates exact Delaunay triangulations, +constrained Delaunay triangulations, and quality +conforming Delaunay triangulations. The latter can +be generated with no small angles, and are thus +suitable for finite element analysis. + +Information on the algorithms used by Triangle, +including complete references, can be found in the +comments at the beginning of the triangle.c source +file. Another listing of these references, with +PostScript copies of some of the papers, is available +from the Web page + +http://www.cs.cmu.edu/~quake/triangle.research.html + +[Triangle] may be freely redistributed under the +condition that the copyright notices (including the +copy of this notice in the code comments and the +copyright notice printed when the `-h' switch is +selected) are not removed, and no compensation is +received. Private, research, and institutional use +is free. You may distribute modified versions of +this code UNDER THE CONDITION THAT THIS CODE AND ANY +MODIFICATIONS MADE TO IT IN THE SAME FILE REMAIN +UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE +AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT +CHARGE, AND CLEAR NOTICE IS GIVEN OF THE +MODIFICATIONS. Distribution of this code as part of +a commercial system is permissible ONLY BY DIRECT +ARRANGEMENT WITH THE AUTHOR. (If you are not +directly supplying this code to a customer, and you +are instead telling them how they can obtain it for +free, then you are not required to make any +arrangement with [JRS].) + +If you use Triangle, and especially if you use it to +accomplish real work, I would like very much to hear +from you. A short letter or email (to +jrs@cs.cmu.edu) describing how you use Triangle will +mean a lot to me. The more people I know are using +this program, the more easily I can justify spending +time on improvements and on the three-dimensional +successor to Triangle, which in turn will benefit +you. Also, I can put you on a list to receive email +whenever a new version of Triangle is available. + +If you use a mesh generated by Triangle, please +include an acknowledgment as well. + +Jonathan Richard Shewchuk +July 20, 1996 + +------------------------------------------------------ + +Lua Copyright Notice + +Copyright © 1994-2000 TeCGraf, PUC-Rio. All rights reserved. + +Permission is hereby granted, without written agreement +and without license or royalty fees, to use, copy, modify, +translate, and distribute this software and its documentation +(hereby called the "package") for any purpose, including +commercial applications, subject to the following conditions: + +* The above copyright notice and this permission notice shall + appear in all copies or substantial portions of this package. +* The origin of this package must not be misrepresented; + you must not claim that you wrote the original package. + If you use this package in a product, an acknowledgment + in the product documentation would be greatly appreciated + (but it is not required). +* Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original package. + +The authors specifically disclaim any warranties, including, +but not limited to, the implied warranties of merchantability +and fitness for a particular purpose. The package provided +hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, +enhancements, or modifications. In no event shall TeCGraf, +PUC-Rio, or the authors be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising +out of the use of this package and its documentation. + +The Lua language and this implementation have been entirely +designed and written by Waldemar Celes, Roberto Ierusalimschy +and Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio in Brazil. + +This implementation contains no third-party code. diff --git a/release/matlib.dat b/release/matlib.dat new file mode 100644 index 0000000..ed41a49 --- /dev/null +++ b/release/matlib.dat @@ -0,0 +1,7167 @@ + + = "Air" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Hard Magnetic Materials" + + = "Alnico Magnets" + + = "Legacy Alnico Definitions" + + = "Alnico 5" + = 1.5 + = 1.5 + = 50963 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.12561 253.85213400000001 + 0.30829000000000001 707.44372199999998 + 0.48333999999999999 1452.2888559999999 + 0.61734 2162.915677 + 0.75499000000000005 3024.739693 + 0.84413000000000005 3845.9792000000002 + 0.92927999999999999 5110.4652230000002 + 0.98077000000000003 6495.9090020000003 + 1.02467 8023.0006810000004 + 1.0464 9234.1697980000008 + 1.0714999999999999 11043.761501000001 + 1.0929 12850.170104999999 + 1.1068 14650.212512 + 1.1242000000000001 16900.663407 + 1.1378999999999999 19147.135429000002 + 1.1516999999999999 21245.593353 + 1.1652 23790.480893 + 1.175 26182.579688000002 + 1.1915 30071.530722 + 1.2045999999999999 33361.263396000002 + 1.2177 36650.996070000001 + 1.2273000000000001 39490.320254999999 + 1.2397 43971.486832000002 + 1.2487999999999999 47704.784332000003 + 1.2544 50988.028258999999 + + + + = "Alnico 6" + = 3.2999999999999998 + = 3.2999999999999998 + = 59907 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.10402 1131.5899999999999 + 0.18934000000000001 2098.46 + 0.26712000000000002 3207.77 + 0.33743000000000001 4310.71 + 0.40393000000000001 5560.0799999999999 + 0.47026000000000001 7106.2700000000004 + 0.52539000000000002 8643.7000000000007 + 0.57662999999999998 10475.6 + 0.63507999999999998 12760.200000000001 + 0.69674999999999998 15942.6 + 0.74002000000000001 18661.700000000001 + 0.78312000000000004 21679.299999999999 + 0.81535999999999997 24090.5 + 0.84031 26198.5 + 0.87238000000000004 28908.099999999999 + 0.90412000000000003 32213.799999999999 + 0.92864999999999998 35065.800000000003 + 0.95318000000000003 37917.900000000001 + 0.97397999999999996 40767.5 + 0.99451999999999996 44062.800000000003 + 1.0149999999999999 47507.800000000003 + 1.0354000000000001 51102.300000000003 + 1.0487 53944.800000000003 + 1.0622 56489.599999999999 + 1.0751999999999999 59928.199999999997 + + + + = "Alnico 8" + = 6.6779999999999999 + = 6.6779999999999999 + = 109300 + = 0 + = 0 + = 0 + = 2.25 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.11536 8340 + 0.23438000000000001 18512 + 0.30429 24866 + 0.35666999999999999 29808 + 0.44341000000000003 39967 + 0.54315999999999998 54772 + 0.66569 77603 + 0.74668000000000001 95215 + 0.80359000000000003 109301 + + + + + = "Cast Alnico 2 (LNG12)" + = 1 + = 1 + = 45120 + = 0 + = 0 + = 0 + = 1.5 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 7 + 0 0 + 0.1474 3570 + 0.3175 9900 + 0.47920000000000001 19060 + 0.5847 28310 + 0.63719999999999999 34140 + 0.71999999999999997 45120 + + + + = "Cast Alnico 3 (LNG10)" + = 1 + = 1 + = 44200 + = 0 + = 0 + = 0 + = 1.7 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 6 + 0 0 + 0.097500000000000003 2700 + 0.20699999999999999 6900 + 0.35799999999999998 15500 + 0.48399999999999999 27100 + 0.60599999999999998 44200 + + + + = "Cast Alnico 5 (LNG37)" + = 1 + = 1 + = 48600 + = 0 + = 0 + = 0 + = 2.1000000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 11 + 0 0 + 0.27810000000000001 1600 + 0.63829999999999998 4100 + 0.82340000000000002 6300 + 0.9214 8600 + 1.0129999999999999 13400 + 1.0640000000000001 18200 + 1.1060000000000001 24300 + 1.149 33000 + 1.1839999999999999 42530 + 1.204 48600 + + + + = "Cast Alnico 5 (LNG40)" + = 1 + = 1 + = 51015 + = 0 + = 0 + = 0 + = 2.1000000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 11 + 0 0 + 0.1883 1109 + 0.37669999999999998 2287 + 0.57769999999999999 3619 + 0.79200000000000004 5578 + 0.97989999999999999 10201 + 1.0857000000000001 18139 + 1.1395999999999999 26809 + 1.1745000000000001 35119 + 1.2011000000000001 43100 + 1.2252000000000001 51015 + + + + = "Cast Alnico 5 (LNG44)" + = 1 + = 1 + = 54060 + = 0 + = 0 + = 0 + = 2.1000000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.3861 2030 + 0.69299999999999995 4360 + 0.91479999999999995 7490 + 1.0229999999999999 11010 + 1.097 16380 + 1.181 30960 + 1.2170000000000001 41370 + 1.252 54060 + + + + = "Cast Alnico 5-7 (LNG56)" + = 1 + = 1 + = 61400 + = 0 + = 0 + = 0 + = 2.1000000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.43070000000000003 3000 + 0.79069999999999996 5900 + 1.014 8800 + 1.1499999999999999 12800 + 1.2130000000000001 18000 + 1.2470000000000001 26000 + 1.276 37800 + 1.321 61400 + + + + = "Cast Alnico 6 (LNGT28)" + = 1 + = 1 + = 58450 + = 0 + = 0 + = 0 + = 2 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.1353 2400 + 0.32400000000000001 6100 + 0.49869999999999998 10490 + 0.71009999999999995 18700 + 0.83189999999999997 28130 + 0.90449999999999997 37770 + 0.96519999999999995 49201 + 1.0029999999999999 58450 + + + + = "Cast Alnico 8 (LNGT32)" + = 1 + = 1 + = 102600 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.13600000000000001 6490 + 0.249 13640 + 0.36799999999999999 23350 + 0.46999999999999997 34600 + 0.57499999999999996 49570 + 0.64200000000000002 61960 + 0.70999999999999996 76600 + 0.76500000000000001 90400 + 0.80900000000000005 102600 + + + + = "Cast Alnico 8 (LNGT38)" + = 1 + = 1 + = 115800 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 8 + 0 0 + 0.191 9600 + 0.35199999999999998 22050 + 0.46300000000000002 34540 + 0.57099999999999995 51350 + 0.67200000000000004 73450 + 0.751 95460 + 0.80900000000000005 115800 + + + + = "Cast Alnico 8 (LNGT44)" + = 1 + = 1 + = 116000 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.14399999999999999 6000 + 0.32500000000000001 16000 + 0.48399999999999999 28800 + 0.57899999999999996 40500 + 0.67500000000000004 56300 + 0.745 72700 + 0.80600000000000005 92200 + 0.85699999999999998 116000 + + + + = "Cast Alnico 9 (LNGT72)" + = 1 + = 1 + = 112100 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 13 + 0 0 + 0.1691 2900 + 0.37409999999999999 6700 + 0.57830000000000004 11300 + 0.7268 16690 + 0.80820000000000003 22540 + 0.88019999999999998 34470 + 0.91810000000000003 46050 + 0.95240000000000002 58990 + 0.98499999999999999 72980 + 1.016 88930 + 1.04 101630 + 1.0600000000000001 112100 + + + + = "Sintered Alnico 2 (FLNG12)" + = 1 + = 1 + = 50900 + = 0 + = 0 + = 0 + = 1.5 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.129 3800 + 0.247 8100 + 0.34799999999999998 13000 + 0.437 18800 + 0.51200000000000001 24900 + 0.58699999999999997 33000 + 0.65100000000000002 41630 + 0.71299999999999997 50900 + + + + = "Sintered Alnico 5 (FLNG34)" + = 1 + = 1 + = 51300 + = 0 + = 0 + = 0 + = 2 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.2833 2500 + 0.51629999999999998 4900 + 0.7218 7800 + 0.85370000000000001 11500 + 0.93179999999999996 16800 + 1.0149999999999999 26900 + 1.0600000000000001 36100 + 1.085 42830 + 1.113 51300 + + + + = "Sintered Alnico 8 (FLNGT38)" + = 1 + = 1 + = 121000 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.11700000000000001 7000 + 0.24099999999999999 16000 + 0.35399999999999998 26000 + 0.44500000000000001 37300 + 0.49299999999999999 44100 + 0.58099999999999996 59300 + 0.68300000000000005 81800 + 0.75600000000000001 102000 + 0.81299999999999994 121000 + + + + + = "Sintered NdFeB Magnets" + + = "Legacy NdFeB" + + = "NdFeB 52 MGOe" + = 1.05 + = 1.05 + = 891300 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 6 + 0 0 + 0.42799999999999999 95490 + 0.53300000000000003 175100 + 0.63800000000000001 254600 + 0.84799999999999998 413800 + 1.478 891300 + + + + = "NdFeB 37 MGOe" + = 1.048 + = 1.048 + = 950000 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "NdFeB 32 MGOe" + = 1.0449999999999999 + = 1.0449999999999999 + = 883310 + = 0 + = 0 + = 0 + = 0.69399999999999995 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N30EH" + + = "N30EH@20C" + = 1.02782 + = 1.02782 + = 862360 + = 0 + = 0 + = 0 + = 0.625 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N30EH@60C" + = 1.04816 + = 1.04816 + = 810310 + = 0 + = 0 + = 0 + = 0.625 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N30EH@100C" + = 1.07653 + = 1.07653 + = 761621 + = 0 + = 0 + = 0 + = 0.625 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N30EH@140C" + = 1.08829 + = 1.08829 + = 705155 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N30EH@180C" + = 1.1462600000000001 + = 1.1462600000000001 + = 638713 + = 0 + = 0 + = 0 + = 0.625 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + + = "N30" + = 1.05 + = 1.05 + = 836420 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N33" + = 1.05 + = 1.05 + = 878619 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N35" + = 1.05 + = 1.05 + = 905659 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N38" + = 1.05 + = 1.05 + = 944771 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N40" + = 1.05 + = 1.05 + = 969969 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N42" + = 1.05 + = 1.05 + = 994529 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N45" + = 1.05 + = 1.05 + = 1030272 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "N48" + = 1.05 + = 1.05 + = 1014538 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 6 + 0 0 + 0.070199999999999999 20713 + 0.14050000000000001 58818 + 0.2107 109648 + 0.28100000000000003 162700 + 1.405 1014538 + + + + = "N50" + = 1.05 + = 1.05 + = 987837 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 8 + 0 0 + 0.0717 11297 + 0.14349999999999999 30636 + 0.2152 67096 + 0.28689999999999999 118309 + 0.35859999999999997 172428 + 0.4304 226773 + 1.4346000000000001 987837 + + + + = "N52" + = 1.05 + = 1.05 + = 956180 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 8 + 0 0 + 0.073200000000000001 7484 + 0.1464 18446 + 0.2195 37084 + 0.29270000000000002 72766 + 0.3659 124571 + 0.43909999999999999 179757 + 1.4636 956180 + + + + = "N55" + = 1.05 + = 1.05 + = 922850 + = 0 + = 0 + = 0 + = 0.66700000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.075300000000000006 5371 + 0.15060000000000001 12456 + 0.22589999999999999 22657 + 0.30120000000000002 39606 + 0.3765 72533 + 0.45179999999999998 124321 + 0.52710000000000001 180991 + 0.60240000000000005 238036 + 1.506 922850 + + + + + = "Ceramic Magnets" + + = "Ceramic 1" + = 1.25 + = 1.25 + = 143280 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.029100000000000001 15920 + 0.056399999999999999 31840 + 0.081799999999999998 47760 + 0.1072 63680 + 0.13200000000000001 79600 + 0.1555 95520 + 0.17799999999999999 111440 + 0.20180000000000001 127360 + 0.22500000000000001 143280 + + + + = "Ceramic 5" + = 1.8859999999999999 + = 1.8859999999999999 + = 191262 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 11 + 0 0 + 0.11225 9979.6124409999993 + 0.119417 10822.945775 + 0.15196999999999999 21699.612441000001 + 0.177037 36726.279108000002 + 0.23735000000000001 78449.612441000005 + 0.259793 94301.612441000005 + 0.31205699999999997 131847.945775 + 0.33257700000000001 146865.612441 + 0.354493 162718.27910799999 + 0.39151000000000002 191082.325775 + + + + = "Ceramic 8" + = 1.4384600000000001 + = 1.4384600000000001 + = 233568 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.040029000000000002 1488.09925 + 0.069106000000000001 5665.9179999999997 + 0.087951000000000001 15231.1335 + 0.11024 30247.407749999998 + 0.15995000000000001 63009.464500000002 + 0.24912000000000001 128493.78925 + 0.32113999999999998 180339.326275 + 0.39145000000000002 233567.92025 + + + + = "Y25" + = 1 + = 1 + = 153035 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 8 + 0 0 + 0.055147000000000002 7066.4799999999996 + 0.12867999999999999 18836 + 0.19485 30605.5 + 0.23896999999999999 44738.5 + 0.27940999999999999 65922 + 0.33088000000000001 105948 + 0.37868000000000002 153035 + + + + = "Y30" + = 1 + = 1 + = 200106 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.066000000000000003 1160 + 0.13139000000000001 2323.6599999999999 + 0.14399999999999999 3490 + 0.15328 6000 + 0.16239999999999999 11630 + 0.17152999999999999 18613.200000000001 + 0.21168000000000001 51192.199999999997 + 0.27372000000000002 102376 + 0.38685999999999998 200106 + + + + + = "Sintered SmCo Magnets" + + = "Legacy SmCo" + + = "SmCo 27 MGOe" + = 1.103 + = 1.103 + = 772000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo 24 MGOe" + = 1.1100000000000001 + = 1.1100000000000001 + = 724000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo 20 MGOe" + = 1.0345 + = 1.0345 + = 693000 + = 0 + = 0 + = 0 + = 1.1759999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + = "SmCo18(1:5)" + = 1.03 + = 1.03 + = 646586 + = 0 + = 0 + = 0 + = 20 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo20(1:5)" + = 1.03 + = 1.03 + = 683563 + = 0 + = 0 + = 0 + = 20 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo22(1:5)" + = 1.03 + = 1.03 + = 718640 + = 0 + = 0 + = 0 + = 20 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo24(1:5)" + = 1.03 + = 1.03 + = 752082 + = 0 + = 0 + = 0 + = 20 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo24" + = 1.1000000000000001 + = 1.1000000000000001 + = 727759 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo26" + = 1.1000000000000001 + = 1.1000000000000001 + = 758741 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo28" + = 1.1000000000000001 + = 1.1000000000000001 + = 788507 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo30" + = 1.1000000000000001 + = 1.1000000000000001 + = 817190 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "SmCo32" + = 1.1000000000000001 + = 1.1000000000000001 + = 844899 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + = "Bonded NdFeB Magnets" + + = "BN10" + = 1.26 + = 1.26 + = 448368 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN9" + = 1.24 + = 1.24 + = 428776 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN7" + = 1.2 + = 1.2 + = 384396 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN8" + = 1.22 + = 1.22 + = 407554 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN6" + = 1.1799999999999999 + = 1.1799999999999999 + = 358885 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN5" + = 1.1599999999999999 + = 1.1599999999999999 + = 330427 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN4" + = 1.1399999999999999 + = 1.1399999999999999 + = 298125 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN3" + = 1.1200000000000001 + = 1.1200000000000001 + = 260478 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN2" + = 1.1000000000000001 + = 1.1000000000000001 + = 214604 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "BN1" + = 1.0800000000000001 + = 1.0800000000000001 + = 153147 + = 0 + = 0 + = 0 + = 0.01 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Legacy Bonded NdFeB" + + = "NdFeB 10 MGOe (Bonded)" + = 1.2230000000000001 + = 1.2230000000000001 + = 445634 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + + + = "Soft Magnetic Materials" + + = "US Steel Type 2-S 0.018 inch thickness" + = 9400 + = 9400 + = 0 + = 0 + = 0 + = 0 + = 6.25 + = 0.4572 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 57 + 0 0 + 0.0044450000000000002 9.5103069999999992 + 0.0058190000000000004 11.21247 + 0.0071929999999999997 13.219414 + 0.0085679999999999992 15.585253 + 0.012898 18.371262000000002 + 0.017228 21.656220999999999 + 0.027470000000000001 25.5213 + 0.046579000000000002 30.061992 + 0.092288999999999996 35.364241 + 0.22076000000000001 41.430433999999998 + 0.4113 48.386302999999998 + 0.60185 56.510370000000002 + 0.77170000000000005 66.066035999999997 + 0.91495000000000004 77.340575999999999 + 1.0464 90.591025999999999 + 1.1600999999999999 106.21208900000001 + 1.2619 124.594492 + 1.3431 146.31119100000001 + 1.3947000000000001 172.06246999999999 + 1.4286000000000001 202.52473699999999 + 1.4507000000000001 238.525598 + 1.4668000000000001 281.01202599999999 + 1.4830000000000001 331.05831499999999 + 1.4932000000000001 390.144609 + 1.5064 459.69534399999998 + 1.5166999999999999 541.73178900000005 + 1.5268999999999999 638.41049399999997 + 1.5371999999999999 752.33364300000005 + 1.5474000000000001 886.57292700000005 + 1.5576000000000001 1044.772997 + 1.5679000000000001 1231.22308 + 1.5840000000000001 1450.5386699999999 + 1.5972 1709.1655450000001 + 1.6104000000000001 2013.867792 + 1.6266 2372.5235849999999 + 1.6427 2795.1596880000002 + 1.6589 3292.9965269999998 + 1.6779999999999999 3878.9256599999999 + 1.6971000000000001 4569.1013169999997 + 1.7161999999999999 5382.0650580000001 + 1.7353000000000001 6339.7006929999998 + 1.7604 7465.5631620000004 + 1.7854000000000001 8791.7222000000002 + 1.8104 10352.236975 + 1.8384 12188.885675 + 1.8723000000000001 14347.823249999999 + 1.9060999999999999 16887.93705 + 1.9459 19872.0933 + 1.9886999999999999 23380.665274999999 + 2.0344000000000002 27504.371325 + 2.0741999999999998 32364.965025000001 + 2.1080999999999999 38095.340799999998 + 2.1389999999999998 44847.491674999997 + 2.1610999999999998 52819.565625000003 + 2.1772 62227.217675 + 2.1903999999999999 73321.116949999996 + + + + = "US Steel Type 2-S 0.024 inch thickness" + = 7400 + = 7400 + = 0 + = 0 + = 0 + = 0 + = 6.25 + = 0.60960000000000003 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 66 + 0 0 + 0.0046779999999999999 9.1307220000000004 + 0.0064009999999999996 10.474786 + 0.008123 12.016997999999999 + 0.0098449999999999996 13.786006 + 0.014524 15.816824 + 0.019202 18.147649000000001 + 0.023879999999999998 20.822248999999999 + 0.031514 23.893940000000001 + 0.048016000000000003 27.429568 + 0.067473000000000005 31.492000000000001 + 0.10170999999999999 36.179115000000003 + 0.15959000000000001 41.607095999999999 + 0.26477000000000001 47.948627000000002 + 0.39655000000000001 55.320686000000002 + 0.53718999999999995 63.850599000000003 + 0.67193000000000003 73.677623999999994 + 0.79779999999999995 84.980812 + 0.90297000000000005 97.936029000000005 + 1.0052000000000001 112.84885300000001 + 1.0955999999999999 129.96597299999999 + 1.1800999999999999 149.637531 + 1.2557 172.22162599999999 + 1.3165 198.08431300000001 + 1.3654999999999999 227.718974 + 1.3997999999999999 261.61103100000003 + 1.4252 300.436893 + 1.4446000000000001 344.928674 + 1.4611000000000001 395.961724 + 1.4717 454.42731400000002 + 1.4852000000000001 521.59868100000006 + 1.4987999999999999 598.69336299999998 + 1.5094000000000001 687.10396600000001 + 1.52 788.557321 + 1.5276000000000001 904.87575200000003 + 1.5382 1038.486375 + 1.5488 1191.832218 + 1.5593999999999999 1367.8576479999999 + 1.5729 1569.9844969999999 + 1.5834999999999999 1801.7937549999999 + 1.5941000000000001 2067.9009150000002 + 1.6047 2373.239783 + 1.6182000000000001 2724.0174019999999 + 1.6288 3126.281665 + 1.6424000000000001 3588.30863 + 1.6589 4119.2497100000001 + 1.6754 4728.7337829999997 + 1.7083999999999999 6231.5548699999999 + 1.7307999999999999 7155.3700669999998 + 1.7532000000000001 8216.3768749999999 + 1.7756000000000001 9433.9126250000008 + 1.8009999999999999 10834.476624999999 + 1.8292999999999999 12443.533675000001 + 1.8575999999999999 14292.119000000001 + 1.8889 16417.634024999999 + 1.9232 18861.459050000001 + 1.9574 21668.953249999999 + 1.9916 24894.229325 + 2.0287999999999999 28603.336599999999 + 2.0659999999999998 32864.711725000001 + 2.0973000000000002 37751.565999999999 + 2.1255999999999999 43359.392424999998 + 2.1480000000000001 49787.662875000002 + 2.1675 57161.314025 + 2.181 65610.852975000002 + 2.1945999999999999 75308.167125000007 + + + + = "Pure Iron" + = 14872 + = 14872 + = 0 + = 0 + = 0 + = 0 + = 10.44 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 21 + 0 0 + 0.22706499999999999 13.898400000000001 + 0.45412999999999998 27.796700000000001 + 0.68119499999999999 42.397399999999998 + 0.90825999999999996 61.415700000000001 + 1.13533 82.382400000000004 + 1.36239 144.66900000000001 + 1.58935 897.75999999999999 + 1.81236 4581.7399999999998 + 2.01004 17736.200000000001 + 2.1331600000000002 41339.300000000003 + 2.1999900000000001 68321.800000000003 + 2.2547899999999998 95685.5 + 2.2999299999999998 123355 + 2.3425099999999999 151083 + 2.3787600000000002 178954 + 2.4150100000000001 206825 + 2.45126 234696 + 2.4874999999999998 262568 + 2.5237500000000002 290439 + 2.5600000000000001 318310 + + + + = "Low Carbon Steel" + + = "1006 Steel" + = 1404 + = 1404 + = 0 + = 0 + = 0 + = 0 + = 5.7999999999999998 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 38 + 0 0 + 0.38833000000000001 79.577472 + 0.48252400000000001 100.182101 + 0.59529299999999996 126.121793 + 0.726634 158.77793 + 0.87345300000000003 199.88957099999999 + 1.0281009999999999 251.646061 + 1.178099 316.80362000000002 + 1.308718 398.83212800000001 + 1.408663 502.09990099999999 + 1.4756450000000001 632.10632499999997 + 1.5169570000000001 795.77471500000001 + 1.544297 1001.821011 + 1.567545 1261.2179289999999 + 1.592042 1587.779301 + 1.619381 1998.89571 + 1.649135 2516.4606050000002 + 1.6799839999999999 3168.036204 + 1.7105109999999999 3988.3212819999999 + 1.7400770000000001 5020.9990129999996 + 1.769441 6321.0632500000002 + 1.8005549999999999 7957.747155 + 1.8356250000000001 10018.210114 + 1.8761209999999999 12612.179292999999 + 1.9221870000000001 15877.793009999999 + 1.972386 19988.957103000001 + 2.0236740000000002 25164.606051999999 + 2.0719500000000002 31680.362036999999 + 2.1135380000000001 39883.212823000002 + 2.1470829999999999 50209.990126999997 + 2.1744270000000001 63210.632496999999 + 2.1996039999999999 79577.471546000001 + 2.2269369999999999 100182.101136 + 2.2598500000000001 126121.79292599999 + 2.3009309999999998 158777.930096 + 2.3525969999999998 199889.57102999999 + 2.4176359999999999 251646.06052200001 + 2.4995159999999998 316803.62037000002 + + + + = "1010 Steel" + = 902.60000000000002 + = 902.60000000000002 + = 0 + = 0 + = 0 + = 0 + = 5.7999999999999998 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 38 + 0 0 + 0.21186199999999999 79.577472 + 0.26566499999999998 100.182101 + 0.33237699999999998 126.121793 + 0.414377 158.77793 + 0.51381100000000002 199.88957099999999 + 0.63189899999999999 251.646061 + 0.76778400000000002 316.80362000000002 + 0.917018 398.83212800000001 + 1.0703530000000001 502.09990099999999 + 1.2142550000000001 632.10632499999997 + 1.3346370000000001 795.77471500000001 + 1.4229810000000001 1001.821011 + 1.480634 1261.2179289999999 + 1.5172140000000001 1587.779301 + 1.5445150000000001 1998.89571 + 1.571296 2516.4606050000002 + 1.6020490000000001 3168.036204 + 1.638404 3988.3212819999999 + 1.68049 5020.9990129999996 + 1.727311 6321.0632500000002 + 1.776659 7957.747155 + 1.8254010000000001 10018.210114 + 1.870557 12612.179292999999 + 1.910809 15877.793009999999 + 1.947222 19988.957103000001 + 1.9823280000000001 25164.606051999999 + 2.0182519999999999 31680.362036999999 + 2.0553979999999998 39883.212823000002 + 2.0925449999999999 50209.990126999997 + 2.1280950000000001 63210.632496999999 + 2.1616119999999999 79577.471546000001 + 2.1946439999999998 100182.101136 + 2.2303389999999998 126121.79292599999 + 2.272386 158777.930096 + 2.3242820000000002 199889.57102999999 + 2.3893559999999998 251646.06052200001 + 2.471238 316803.62037000002 + + + + = "1018 Steel" + = 529 + = 529 + = 0 + = 0 + = 0 + = 0 + = 5.7999999999999998 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 13 + 0 0 + 0.25030000000000002 238.73249999999999 + 0.92500000000000004 795.77499999999998 + 1.25 1591.55 + 1.3899999999999999 2387.3249999999998 + 1.5249999999999999 3978.875 + 1.71 7957.75 + 1.8700000000000001 15915.5 + 1.9550000000000001 23873.25 + 2.02 39788.75 + 2.1099999999999999 79577.5 + 2.2250000000000001 159155 + 2.4300000000000002 318310 + + + + = "1020 Steel" + = 760 + = 760 + = 0 + = 0 + = 0 + = 0 + = 5.7999999999999998 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 38 + 0 0 + 0.16625200000000001 79.577472 + 0.20872499999999999 100.182101 + 0.26163500000000001 126.121793 + 0.32714599999999999 158.77793 + 0.407495 199.88957099999999 + 0.50460400000000005 251.646061 + 0.61936599999999997 316.80362000000002 + 0.750502 398.83212800000001 + 0.89319499999999996 502.09990099999999 + 1.0382579999999999 632.10632499999997 + 1.173276 795.77471500000001 + 1.2867310000000001 1001.821011 + 1.3735329999999999 1261.2179289999999 + 1.4376580000000001 1587.779301 + 1.4891890000000001 1998.89571 + 1.5383439999999999 2516.4606050000002 + 1.591321 3168.036204 + 1.6497230000000001 3988.3212819999999 + 1.711927 5020.9990129999996 + 1.7747120000000001 6321.0632500000002 + 1.8349759999999999 7957.747155 + 1.8914420000000001 10018.210114 + 1.945262 12612.179292999999 + 1.998705 15877.793009999999 + 2.0528520000000001 19988.957103000001 + 2.1061839999999998 25164.606051999999 + 2.1551490000000002 31680.362036999999 + 2.1963750000000002 39883.212823000002 + 2.2290079999999999 50209.990126999997 + 2.2554500000000002 63210.632496999999 + 2.2800530000000001 79577.471546000001 + 2.3071359999999999 100182.101136 + 2.3399749999999999 126121.79292599999 + 2.3810440000000002 158777.930096 + 2.4327079999999999 199889.57102999999 + 2.4977480000000001 251646.06052200001 + 2.5796269999999999 316803.62037000002 + + + + = "1117 Steel" + = 1777 + = 1777 + = 0 + = 0 + = 0 + = 0 + = 5.7999999999999998 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 9 + 0 0 + 0.70040000000000002 238.73249999999999 + 1.351 795.77499999999998 + 1.6240000000000001 3183.0999999999999 + 1.77 7957.75 + 2 31831 + 2.1299999999999999 79577.5 + 2.25 159155 + 2.46 318310 + + + + + = "Magnetic Stainless Steel" + + = "416 Stainless Steel" + = 440 + = 440 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.20039999999999999 318.31 + 0.42559999999999998 477.46499999999997 + 0.76100000000000001 795.77499999999998 + 1.097 1591.55 + 1.2330000000000001 2387.3249999999998 + 1.335 3978.875 + 1.46 7957.75 + 1.5900000000000001 15915.5 + 1.6899999999999999 31831 + 1.724232 44456.279999999999 + 1.74 55704.25 + + + + = "430 Stainless Steel" + = 409 + = 409 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 10 + 0 0 + 0.20039999999999999 318.31 + 0.6008 636.62 + 1.1020000000000001 1591.55 + 1.3859999999999999 4774.6499999999996 + 1.4650000000000001 7957.75 + 1.667548 32902.232515999996 + 1.789509 92585.397305000006 + 1.878209 160685.354903 + 2.0800000000000001 318310 + + + + = "455 Stainless Steel" + = 470 + = 470 + = 0 + = 0 + = 0 + = 0 + = 1.6699999999999999 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 26 + 0 0 + 0.067337999999999995 342.70800000000003 + 0.10261000000000001 514.03099999999995 + 0.18909000000000001 713.09400000000005 + 0.29154000000000002 854.58199999999999 + 0.40999999999999998 995.75300000000004 + 0.55725000000000002 1107.72 + 0.73009999999999997 1247.9300000000001 + 0.86777000000000004 1417.4300000000001 + 0.97345000000000004 1616.1400000000001 + 1.0632999999999999 2273.6900000000001 + 1.1339999999999999 2931.6300000000001 + 1.224 4076.3600000000001 + 1.2724 4906.5900000000001 + 1.3500000000000001 6968.6800000000003 + 1.3761000000000001 8085.8699999999999 + 1.3991 9661.5 + 1.419 11438.5 + 1.4359999999999999 13874.299999999999 + 1.4462999999999999 15736.4 + 1.4533 17169.599999999999 + 1.464 19777.400000000001 + 1.478 22986.700000000001 + 1.4887999999999999 25795 + 1.4959 27715.200000000001 + 1.4995000000000001 28604.099999999999 + + + + + = "Silicon Iron" + + = "Carpenter Silicon Core Iron "A", 1066C Anneal" + = 7000 + = 7000 + = 0 + = 0 + = 0 + = 0 + = 4 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 35 + 0 0 + 0.076137999999999997 27.383403999999999 + 0.14288999999999999 31.395700000000001 + 0.21798000000000001 36.490250000000003 + 0.30552000000000001 42.403651000000004 + 0.39304 48.938552999999999 + 0.48466999999999999 55.704230000000003 + 0.58045000000000002 63.402555 + 0.68454999999999999 72.654231999999993 + 0.77612999999999999 81.009866000000002 + 0.85528000000000004 90.965007999999997 + 0.91776999999999997 100.076628 + 0.97614000000000001 110.875291 + 1.0510999999999999 124.506912 + 1.1262000000000001 144.71163200000001 + 1.1930000000000001 168.210859 + 1.2515000000000001 195.55367899999999 + 1.3058000000000001 225.79311799999999 + 1.3476999999999999 260.75150100000002 + 1.3937999999999999 309.50861800000001 + 1.4316 367.41714400000001 + 1.4694 436.172079 + 1.4990000000000001 525.02828399999999 + 1.5244 636.38899800000002 + 1.5414000000000001 745.35442899999998 + 1.5626 897.31556899999998 + 1.5839000000000001 1095.1451629999999 + 1.6094999999999999 1402.632513 + 1.6267 1771.9515590000001 + 1.6479999999999999 2223.0762450000002 + 1.6652 2713.5122019999999 + 1.6822999999999999 3335.0122550000001 + 1.7036 4042.6151319999999 + 1.7205999999999999 4767.5658979999998 + 1.7377 5779.3934479999998 + + + + = "M-15 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-19 Steel" + = 4416 + = 4416 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-22 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 15.120714 + 0.10000000000000001 22.718292000000002 + 0.14999999999999999 27.842732999999999 + 0.20000000000000001 31.871434000000001 + 0.25 35.365043999999997 + 0.29999999999999999 38.600588000000002 + 0.34999999999999998 41.736201999999999 + 0.40000000000000002 44.873978999999999 + 0.45000000000000001 48.087806999999998 + 0.5 51.437235999999999 + 0.55000000000000004 54.975220999999998 + 0.59999999999999998 58.752992999999996 + 0.65000000000000002 62.823644000000002 + 0.69999999999999996 67.245284999999996 + 0.75 72.084406000000001 + 0.80000000000000004 77.420100000000005 + 0.84999999999999998 83.350020999999998 + 0.90000000000000002 89.999611999999999 + 0.94999999999999996 97.537352999999996 + 1 106.20140600000001 + 1.05 116.34846400000001 + 1.1000000000000001 128.54732899999999 + 1.1499999999999999 143.76543100000001 + 1.2 163.75416899999999 + 1.25 191.86815799999999 + 1.3 234.833507 + 1.3500000000000001 306.50976900000001 + 1.3999999999999999 435.255202 + 1.45 674.911968 + 1.5 1108.3255690000001 + 1.55 1813.085468 + 1.6000000000000001 2801.2174209999998 + 1.6499999999999999 4053.6531169999998 + 1.7 5591.10689 + 1.75 7448.318413 + 1.8 9708.81567 + 1.8500000000000001 12486.931615 + 1.8999999999999999 16041.483644 + 1.95 21249.420623999998 + 2 31313.495878000002 + 2.0499999999999998 53589.446877000002 + 2.1000000000000001 88477.484601000004 + 2.1499999999999999 124329.41054 + 2.2000000000000002 159968.5693 + 2.25 197751.604272 + 2.2999999999999998 234024.75134700001 + + + + = "M-27 Steel" + = 12138 + = 12138 + = 0 + = 0 + = 0 + = 0 + = 2 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 17.059828 + 0.10000000000000001 25.634971 + 0.14999999999999999 31.338353999999999 + 0.20000000000000001 35.778996999999997 + 0.25 39.602124000000003 + 0.29999999999999999 43.123142999999999 + 0.34999999999999998 46.520439000000003 + 0.40000000000000002 49.908177000000002 + 0.45000000000000001 53.368284000000003 + 0.5 56.966318000000001 + 0.55000000000000004 60.760271000000003 + 0.59999999999999998 64.806105000000002 + 0.65000000000000002 69.161803000000006 + 0.69999999999999996 73.890922000000003 + 0.75 79.066315000000003 + 0.80000000000000004 84.774675999999999 + 0.84999999999999998 91.122721999999996 + 0.90000000000000002 98.246298999999993 + 0.94999999999999996 106.324591 + 1 115.60341699999999 + 1.05 126.435124 + 1.1000000000000001 139.34975900000001 + 1.1499999999999999 155.187082 + 1.2 175.350538 + 1.25 202.312017 + 1.3 240.640455 + 1.3500000000000001 299.11802699999998 + 1.3999999999999999 394.99338599999999 + 1.45 561.72617700000001 + 1.5 859.32876299999998 + 1.55 1375.4668879999999 + 1.6000000000000001 2191.2469139999998 + 1.6499999999999999 3328.145908 + 1.7 4760.5061720000003 + 1.75 6535.3394490000001 + 1.8 8788.9706569999998 + 1.8500000000000001 11670.804346999999 + 1.8999999999999999 15385.186211 + 1.95 20246.553030999999 + 2 26995.131141000002 + 2.0499999999999998 38724.496369 + 2.1000000000000001 64917.284463000004 + 2.1499999999999999 101489.30933800001 + 2.2000000000000002 137202.82896099999 + 2.25 176835.706764 + 2.2999999999999998 216374.28360900001 + + + + = "M-36 Steel" + = 1616 + = 1616 + = 0 + = 0 + = 0 + = 0 + = 2 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 19.398586000000002 + 0.10000000000000001 29.611086 + 0.14999999999999999 36.311286000000003 + 0.20000000000000001 41.398969999999998 + 0.25 45.654680999999997 + 0.29999999999999999 49.463585000000002 + 0.34999999999999998 53.042856999999998 + 0.40000000000000002 56.529325 + 0.45000000000000001 60.018492000000002 + 0.5 63.584023999999999 + 0.55000000000000004 67.288555000000002 + 0.59999999999999998 71.190393999999998 + 0.65000000000000002 75.348315999999997 + 0.69999999999999996 79.825601000000006 + 0.75 84.694101000000003 + 0.80000000000000004 90.039004000000006 + 0.84999999999999998 95.965085000000002 + 0.90000000000000002 102.60559499999999 + 0.94999999999999996 110.135639 + 1 118.793308 + 1.05 128.91455500000001 + 1.1000000000000001 140.99328499999999 + 1.1499999999999999 155.78958700000001 + 1.2 174.53384 + 1.25 199.32994600000001 + 1.3 233.989035 + 1.3500000000000001 285.82186100000001 + 1.3999999999999999 369.57162599999998 + 1.45 515.788276 + 1.5 785.78510400000005 + 1.55 1282.7937979999999 + 1.6000000000000001 2108.172454 + 1.6499999999999999 3257.880122 + 1.7 4726.4426309999999 + 1.75 6512.0094010000003 + 1.8 8720.2655529999993 + 1.8500000000000001 11459.429228999999 + 1.8999999999999999 14887.904936999999 + 1.95 19350.577347999999 + 2 26042.602019000002 + 2.0499999999999998 39200.400310999998 + 2.1000000000000001 65518.130312000001 + 2.1499999999999999 100476.654669 + 2.2000000000000002 136976.920182 + 2.25 176029.81784199999 + 2.2999999999999998 215228.81031199999 + + + + = "M-43 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.6000000000000001 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 22.815826000000001 + 0.10000000000000001 34.292324000000001 + 0.14999999999999999 41.691794999999999 + 0.20000000000000001 47.276539 + 0.25 51.943272999999998 + 0.29999999999999999 56.124130000000001 + 0.34999999999999998 60.058388999999998 + 0.40000000000000002 63.894412000000003 + 0.45000000000000001 67.734109000000004 + 0.5 71.654736999999997 + 0.55000000000000004 75.720754999999997 + 0.59999999999999998 79.991001999999995 + 0.65000000000000002 84.523664999999994 + 0.69999999999999996 89.380326999999994 + 0.75 94.629947999999999 + 0.80000000000000004 100.353469 + 0.84999999999999998 106.649919 + 0.90000000000000002 113.64520899999999 + 0.94999999999999996 121.50566499999999 + 1 130.459825 + 1.05 140.83502200000001 + 1.1000000000000001 153.12108799999999 + 1.1499999999999999 168.08528999999999 + 1.2 186.98695799999999 + 1.25 211.991513 + 1.3 246.99227999999999 + 1.3500000000000001 299.27421299999997 + 1.3999999999999999 382.88283799999999 + 1.45 525.15514299999995 + 1.5 777.59279800000002 + 1.55 1226.4570960000001 + 1.6000000000000001 1979.929758 + 1.6499999999999999 3105.52556 + 1.7 4589.1826570000003 + 1.75 6410.9674969999996 + 1.8 8681.3394960000005 + 1.8500000000000001 11524.478784000001 + 1.8999999999999999 15121.416504000001 + 1.95 19833.366747 + 2 26795.523691999999 + 2.0499999999999998 40064.363461000001 + 2.1000000000000001 66950.843427999993 + 2.1499999999999999 103339.791774 + 2.2000000000000002 141054.369267 + 2.25 181684.21904299999 + 2.2999999999999998 223103.57263000001 + + + + = "M-45 Steel" + = 4689 + = 4689 + = 0 + = 0 + = 0 + = 0 + = 2.8999999999999999 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 47 + 0 0 + 0.050000000000000003 19.965330000000002 + 0.10000000000000001 29.906288 + 0.14999999999999999 36.398771000000004 + 0.20000000000000001 41.371668999999997 + 0.25 45.590262000000003 + 0.29999999999999999 49.424858999999998 + 0.34999999999999998 53.082279999999997 + 0.40000000000000002 56.692664000000001 + 0.45000000000000001 60.347374000000002 + 0.5 64.117637000000002 + 0.55000000000000004 68.064755000000005 + 0.59999999999999998 72.246370999999996 + 0.65000000000000002 76.720885999999993 + 0.69999999999999996 81.551123000000004 + 0.75 86.807958999999997 + 0.80000000000000004 92.574503000000007 + 0.84999999999999998 98.951520000000002 + 0.90000000000000002 106.06504700000001 + 0.94999999999999996 114.077777 + 1 123.20691100000001 + 1.05 133.75338500000001 + 1.1000000000000001 146.15173799999999 + 1.1499999999999999 161.05866800000001 + 1.2 179.51663400000001 + 1.25 203.267945 + 1.3 235.37974800000001 + 1.3500000000000001 281.52494799999999 + 1.3999999999999999 352.64841200000001 + 1.45 470.42617899999999 + 1.5 677.45154100000002 + 1.55 1051.0680359999999 + 1.6000000000000001 1703.275165 + 1.6499999999999999 2726.5179589999998 + 1.7 4137.9810520000001 + 1.75 5832.6197039999997 + 1.8 7939.5529399999996 + 1.8500000000000001 10565.294335000001 + 1.8999999999999999 13843.912965 + 1.95 17970.359698 + 2 23423.776431999999 + 2.0499999999999998 32234.325959999998 + 2.1000000000000001 51366.778966999998 + 2.1499999999999999 84577.843500999996 + 2.2000000000000002 121162.49332199999 + 2.25 160127.812767 + 2.2999999999999998 202470.28224500001 + + + + = "M-47 Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 4.2999999999999998 + = 0.63500000000000001 + = 0 + = 0 + = 0 + = 0 + = 0.97999999999999998 + = 0 + = 0 + = 0 + + + + + = "Cobalt Iron" + + = "Hiperco-50" + = 3520 + = 3520 + = 0 + = 0 + = 0 + = 0 + = 2.5 + = 0 + = 20 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 22 + 0 0 + 0.29072999999999999 81.170000000000002 + 0.42870999999999998 106.8 + 0.58955999999999997 136.84 + 0.79627000000000003 179.91 + 1.0201 233.41 + 1.1980999999999999 283.70999999999998 + 1.3989 344.75 + 1.5596000000000001 402.92000000000002 + 1.7835000000000001 536.63999999999999 + 1.8985000000000001 670.10000000000002 + 1.9906999999999999 893.79999999999995 + 2.0543999999999998 1290.4000000000001 + 2.1183999999999998 2209.8000000000002 + 2.1476999999999999 3233.6999999999998 + 2.177 4549 + 2.2065000000000001 7297.8000000000002 + 2.2416999999999998 11554 + 2.2711999999999999 18294 + 2.2890000000000001 25071 + 2.3126000000000002 36690 + 2.3410000000000002 62037 + + + + = "Vanadium Permedur" + = 6856 + = 6856 + = 0 + = 0 + = 0 + = 0 + = 2.5 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.59999999999999998 71.400000000000006 + 1 119 + 1.6000000000000001 175 + 1.8 268 + 2 493 + 2.1000000000000001 804 + 2.2000000000000002 1910 + 2.2599999999999998 4775 + 2.2999999999999998 15120 + 2.3399999999999999 42971 + 2.3900000000000001 79577 + + + + + = "Nickel Alloys" + + = "Supermalloy" + = 529095 + = 529095 + = 0 + = 0 + = 0 + = 0 + = 1.7 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 12 + 0 0 + 0.45000099999999998 0.79577500000000001 + 0.57500200000000001 1.59155 + 0.62500299999999998 2.3873250000000001 + 0.65000400000000003 3.1831 + 0.680006 4.7746490000000001 + 0.70000799999999996 6.3662000000000001 + 0.72567300000000001 10.138479999999999 + 0.744506 15.68595 + 0.76002999999999998 23.873249999999999 + 0.78046000000000004 48 + 0.78510000000000002 79.577500000000001 + + + + = "Mu Metal" + = 82910 + = 82910 + = 0 + = 0 + = 0 + = 0 + = 1.8 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 31 + 0 0 + 0.080001000000000003 0.79577500000000001 + 0.099140000000000006 1.0342340000000001 + 0.12679699999999999 1.344149 + 0.16478400000000001 1.7469330000000001 + 0.21423800000000001 2.270413 + 0.27441399999999999 2.9507569999999999 + 0.34069300000000002 3.8349700000000002 + 0.39480599999999999 4.9841449999999998 + 0.43570300000000001 6.4776769999999999 + 0.46653800000000001 8.4187550000000009 + 0.49254100000000001 10.941490999999999 + 0.51263599999999998 14.220181 + 0.53089299999999995 18.481352000000001 + 0.54834099999999997 24.019411000000002 + 0.56394500000000003 31.216987 + 0.57866499999999998 40.571362999999998 + 0.59203600000000001 52.728839999999998 + 0.60396099999999997 68.529386000000002 + 0.61424699999999999 89.064670000000007 + 0.62285900000000005 115.75348700000001 + 0.63014599999999998 150.439784 + 0.63628200000000001 195.52006 + 0.64158999999999999 254.10893899999999 + 0.64653300000000002 330.25436300000001 + 0.65073700000000001 429.217266 + 0.65423600000000004 557.835058 + 0.65707000000000004 724.99402199999997 + 0.65927800000000003 942.24327400000004 + 0.66090599999999999 1224.592701 + 0.66200000000000003 1591.55 + + + + + + = "Solid Non-Magnetic Conductors" + + = "Titanium" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.798 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "316 Stainless Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.3340000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "304 Stainless Steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.45 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Copper" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Aluminum, 6061-T6" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 24.59 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + = "Aluminum, 1100" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 34.450000000000003 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + + + + + = "Copper AWG Magnet Wire" + + = "10 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.5887801724742099 + = 0 + + + + = "12 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.0530176819291301 + = 0 + + + + = "14 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.62813422596841 + = 0 + + + + = "16 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.2911827701741401 + = 0 + + + + = "18 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.0239652968433499 + = 0 + + + + = "20 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.812049969500513 + = 0 + + + + = "22 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.64399170069399603 + = 0 + + + + = "24 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.510714027632857 + = 0 + + + + = "26 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.40501891210693097 + = 0 + + + + = "28 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.32119799004660898 + = 0 + + + + = "30 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.25472427515370799 + = 0 + + + + = "32 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.20200766618485599 + = 0 + + + + = "34 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.16020105336575399 + = 0 + + + + = "36 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.12704655216407401 + = 0 + + + + + = "Copper SWG Magnet Wire" + + = "10 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 3.2511999999999999 + = 0 + + + + = "12 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.6415999999999999 + = 0 + + + + = "14 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.032 + = 0 + + + + = "16 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.6255999999999999 + = 0 + + + + = "18 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.2192000000000001 + = 0 + + + + = "20 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.91439999999999999 + = 0 + + + + = "22 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.71120000000000005 + = 0 + + + + = "24 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.55879999999999996 + = 0 + + + + = "26 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.4572 + = 0 + + + + = "28 AWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.37591999999999998 + = 0 + + + + = "30 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.31496000000000002 + = 0 + + + + = "32 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.27432000000000001 + = 0 + + + + = "34 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.23368 + = 0 + + + + = "36 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.19303999999999999 + = 0 + + + + = "38 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.15240000000000001 + = 0 + + + + = "40 SWG" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.12192 + = 0 + + + + + = "Copper Metric Magnet Wire" + + = "2.5mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2.5 + = 0 + + + + = "2mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 2 + = 0 + + + + = "1.6mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1.6000000000000001 + = 0 + + + + = "1.25mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 1 + = 1.25 + = 0 + + + + = "1mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 1 + = 0 + + + + = "0.8mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.80000000000000004 + = 0 + + + + = "0.63mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.63 + = 0 + + + + = "0.5mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.5 + = 0 + + + + = "0.4mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.40000000000000002 + = 0 + + + + = "0.315mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.315 + = 0 + + + + = "0.25mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.25 + = 0 + + + + = "0.2mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.20000000000000001 + = 0 + + + + = "0.16mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.16 + = 0 + + + + = "0.125mm" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 58 + = 0 + = 0 + = 0 + = 0 + = 3 + = 1 + = 1 + = 0.125 + = 0 + + + + + = "Metals Handbook DC Magnetization Curves" + + = "Supermendur" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.6099999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.061756563704186432 8.3768555555555544 + 0.078784651961084112 9.0070777777777771 + 0.081554695754912171 9.1008740740740723 + 0.094394327484926849 9.4856962962962932 + 0.11911813486733697 10.30502962962963 + 0.14675058899521243 11.079037037037034 + 0.57090648432208246 16.359851851851847 + 1.6154588505589607 20.305962962962958 + 1.9373720675610759 21.981777777777772 + 2.0562148603023509 35.403962962962957 + 2.0654038967077923 38.468666666666664 + 2.1117578041711655 60.73566666666666 + 2.143654205315491 87.344925925925921 + 2.1957385882474552 175.12592592592591 + 2.2312328182445689 294.32148148148144 + 2.236742633286096 319.81592592592585 + 2.2712155539171861 548.78851851851846 + 2.3060205575080532 991.91999999999985 + 2.3263004289513867 1441.5777777777776 + 2.3429107530489715 1989.1518518518515 + 2.3434331455082438 2009.9185185185181 + 2.3741851878535236 3866.8777777777768 + 2.3805044919465232 4518.8592592592586 + 2.4116361658645493 12124.555555555551 + 2.4427696993909738 34273.777777777766 + 2.4708885826369 56440.81481481481 + 2.4754890273493713 60072.259259259248 + 2.5566432709019331 124334.44444444444 + 2.80730899203899 323410 + + + + = "Vanadium Permendur" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.6099999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 28 + 0 0 + 0.10411120040352746 88.578888888888883 + 0.12359722078060682 93.281333333333322 + 0.15214268879362541 100.28522222222222 + 0.17615159534763009 105.60444444444443 + 0.18113408317445523 106.7 + 0.19833941239730252 110.05666666666664 + 0.21856931312456385 113.51444444444445 + 0.22596412370457608 114.69 + 0.54642739719099431 154.43111111111108 + 0.85717443712847452 187.4433333333333 + 1.1988015279764421 257.6322222222222 + 1.4826233278846064 381.08333333333331 + 1.5809767084466044 458.92999999999995 + 1.7583811971916443 701.23444444444442 + 1.8152740557050593 810.49666666666656 + 1.819229092203668 818.92555555555555 + 1.8274172655155092 836.03999999999996 + 2.0326977111485132 1492.4666666666665 + 2.1362003500193545 2122.344444444444 + 2.2573828824043209 3638.0999999999995 + 2.2986811232043647 4618.1555555555551 + 2.3184412710191524 5284.9555555555553 + 2.3767621955608833 10270.777777777776 + 2.4146221155551992 22856.333333333332 + 2.4520172281458574 45850.333333333328 + 2.5888726880360471 149902.22222222219 + 2.80730899203899 323410 + + + + = "Pure iron, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 10.295 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 36 + 0 0 + 0.058763804230316796 16.290222222222219 + 0.10495479865295962 17.877333333333329 + 0.11038914294005882 18.062888888888885 + 0.12125650530186718 18.439666666666664 + 0.18661400700465575 20.87255555555555 + 0.229021526963191 22.435777777777776 + 0.47273113639778119 31.851111111111113 + 0.95170264147811889 62.227222222222224 + 1.1915490626253744 92.094444444444434 + 1.311137186024772 118.01111111111112 + 1.3272990080104741 122.99777777777776 + 1.3627714178615502 136.40999999999997 + 1.443033163068657 176.70333333333332 + 1.4675463050528315 196.00333333333333 + 1.5193061782237554 243.64888888888885 + 1.526115850140338 251.34555555555553 + 1.5975920914017554 409.27777777777771 + 1.6067254973566771 444.70333333333326 + 1.6691004503948226 999.49777777777763 + 1.6918619992566377 1437.5222222222219 + 1.7424641053303827 2570.9666666666662 + 1.7815409730270535 3976.1111111111104 + 1.8199707103168845 5600.1666666666661 + 1.8701807934466155 7968.9888888888891 + 1.9361208266771577 11696.777777777776 + 2.0255629243443902 17893.111111111109 + 2.1086378947868365 27661.222222222219 + 2.1516697522798043 36227.888888888883 + 2.1722906956279413 41894.555555555547 + 2.2846887595088181 106704.44444444444 + 2.296415444853904 115956.66666666666 + 2.4117695948348024 203216.66666666666 + 2.4253929368441689 214057.77777777775 + 2.5009042187807395 271840 + 2.5627679303503155 320990 + + + + = "Ingot iron, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 10.15 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 32 + 0 0 + 0.072984889888521698 49.515666666666661 + 0.08385352174681851 50.548999999999992 + 0.14635190351601829 57.219000000000001 + 0.1626541663004869 59.019666666666666 + 0.1680882695334599 59.632333333333328 + 0.22061889806381388 65.437666666666672 + 0.3356136388354235 77.167999999999992 + 0.37454876340136006 81.245999999999995 + 0.39084422045132722 82.935999999999993 + 0.52122621400726477 97.785333333333327 + 0.78469730446956931 133.13666666666666 + 1.0128921911312923 179.4666666666667 + 1.3580770256878687 326.55333333333334 + 1.4520598527548207 445.51666666666671 + 1.4797806438388399 515.11333333333334 + 1.6360059260210866 2179.833333333333 + 1.6581064498582383 2710.7666666666664 + 1.7083724249351828 4063.0333333333333 + 1.8039492310588685 7492.9333333333325 + 1.8462955169896693 9413.1000000000004 + 1.9050790251776824 12848.333333333332 + 1.9644713963587555 17537.333333333332 + 1.9738438387370751 18470.333333333332 + 2.0274993188988266 24695 + 2.0497138199932405 28261 + 2.191352493389517 75773 + 2.2013004219832695 81487.666666666657 + 2.2952361494711493 147326.66666666666 + 2.4382775532796543 260916.66666666666 + 2.4819242162486139 295570 + 2.5141066913919881 321180 + + + + = "Hot rolled low-carbon steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 8.4100000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.055401337598916967 54.38133333333333 + 0.060842101822984253 55.519999999999996 + 0.082605463244301305 60.316999999999993 + 0.11524494238216776 67.594999999999999 + 0.13746228114260653 73.435000000000002 + 0.16012588444585232 78.954999999999984 + 0.17009568055768098 81.445333333333338 + 0.27701117196526293 104.38333333333333 + 0.40698290205106413 129.63333333333333 + 0.9833648518889706 266.4666666666667 + 1.2471911555840209 470.42666666666662 + 1.2917096428334274 538.18999999999994 + 1.3002976471973975 555.16999999999985 + 1.303038248081736 560.95333333333326 + 1.3139347389346607 584.68666666666661 + 1.3439234198120862 655.25666666666666 + 1.3630520135531405 704.53666666666663 + 1.3680705531385868 719.28999999999996 + 1.5479701608805008 1700.4333333333329 + 1.5714119148366126 1945.8666666666668 + 1.6270190539756397 2826.9000000000001 + 1.6312313135531282 2916.2333333333336 + 1.6340081778533859 2977.4000000000001 + 1.7342217645417177 6091.7333333333336 + 1.8663549543662834 12988.333333333332 + 1.9876052775720807 24965 + 2.0273771352258185 32025 + 2.1014325723687213 54377.333333333328 + 2.1251828014085139 64205.333333333328 + 2.4139738954543644 260993.33333333331 + 2.4614494666471085 298746.66666666663 + 2.4898323550981316 321280 + + + + = "M-50" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 5.5099999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.17091054334806732 138.36666666666667 + 0.17724901538331228 139.80333333333334 + 0.20486974193135704 145.68666666666667 + 0.21211497278665314 147.19666666666666 + 0.25377677260866005 156.58666666666664 + 0.27551295107421214 161.50333333333333 + 0.28275505384689487 163.17666666666665 + 0.32894146039445737 173.57999999999998 + 0.4059092888292386 190.41999999999999 + 0.42492426092321167 194.37666666666667 + 0.77168921241957378 269.93666666666661 + 0.85815490321356935 293.0333333333333 + 1.2092038476183415 480.52666666666664 + 1.3343818209365623 622.15333333333331 + 1.3588985394573863 661.98333333333335 + 1.5136837627030362 1207.2666666666667 + 1.6090881927062419 2006.5666666666668 + 1.6441685590258115 2494.9333333333329 + 1.6655211159195367 2855.0666666666666 + 1.691568870436805 3370.5333333333333 + 1.7385756065835569 4649.1333333333332 + 1.7957205762704673 6753.9333333333343 + 1.8243699271458804 8225.5999999999985 + 1.9398413963386592 17725.666666666664 + 1.9928982509957003 25224.666666666664 + 2.000053000114896 26568 + 2.018114303573709 30091.666666666664 + 2.0716131221779523 43725 + 2.0896200595568115 50043.666666666664 + 2.2033484254164013 104603.33333333333 + 2.3063251727798812 177690 + 2.4898323550981316 321280 + + + + = "Cold rolled low carbon strip steel" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 8.4100000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.25879392381720928 164.92999999999998 + 0.30180486493722419 173.63666666666668 + 0.33666735915473539 180.92666666666665 + 0.42495199342992973 200.53 + 0.7473178074029625 287.38666666666666 + 1.011384581253957 412.14333333333326 + 1.201776747252508 591.58999999999992 + 1.2680347934366085 690.83333333333326 + 1.3825549144095455 972.10333333333324 + 1.4844346021927772 1566.0333333333333 + 1.5543215879553376 2298.3999999999996 + 1.6275853376778917 3516.2666666666664 + 1.7326643792703789 6284.8000000000002 + 1.7421846824795273 6619.2666666666673 + 1.774621610366959 7895.3666666666659 + 1.7804018079804538 8144.8666666666659 + 1.9084190129899348 16487.666666666664 + 1.9600489652236601 21816.666666666664 + 2.0671950574242537 42384.333333333328 + 2.093638690713278 51093 + 2.1195996276460018 61592.666666666664 + 2.151693826634427 76601.666666666657 + 2.1766199432507078 89514 + 2.1913634881460617 97267.666666666657 + 2.2061088381613558 106800 + 2.2294237629023126 120976.66666666666 + 2.24540169688657 131463.33333333331 + 2.4243620951622349 269260 + 2.4898323550981316 321280 + + + + = "Cold drawn carbon steel, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 8.4100000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 36 + 0 0 + 0.090946180887965383 82.373999999999995 + 0.10728246566596635 89.49733333333333 + 0.10955030393725329 90.429666666666662 + 0.12135426454430355 96.233999999999995 + 0.12362219119906381 97.23666666666665 + 0.15900126276086618 112.41333333333333 + 0.18212188553282554 120.86666666666667 + 0.19888829857062906 125.96999999999998 + 0.32116791520471627 154.84333333333333 + 0.33520529909817764 158.06666666666666 + 0.3661469890679695 164.71666666666664 + 0.6385770848128145 233.75999999999999 + 0.80614564557310531 296.27666666666664 + 0.99686877275972408 399.56333333333333 + 1.0544509515756355 438.43333333333328 + 1.2389332822947856 610.05333333333328 + 1.2842834399278145 676.49333333333334 + 1.3106378481237844 719.78999999999996 + 1.4475898594633414 1159.0666666666666 + 1.5272264068962544 1718.6666666666665 + 1.5695701307382293 2204.3999999999996 + 1.5912705696451099 2496.5333333333333 + 1.6139233778662476 2856.8666666666668 + 1.6637330167015858 3819.4666666666672 + 1.6688513594615677 3940.1666666666665 + 1.6707362986902243 3981.2333333333336 + 1.7641458954366975 6827.1333333333332 + 1.7813517862208936 7494.9666666666672 + 1.9319430541358145 17912.666666666664 + 2.089377699618963 50567 + 2.1026973391465553 56100 + 2.1336190543455107 71237 + 2.1967288380407783 107930 + 2.243452492128168 142883.33333333331 + 2.4709203196924321 321350 + + + + = "M-43 and M-36" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 3.1899999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.062003332426385685 40.230111111111107 + 0.067437412837353883 40.647777777777776 + 0.078155034440016563 41.496111111111112 + 0.12782448788889547 46.012666666666661 + 0.14835359382772473 47.953777777777773 + 0.16269549134968753 49.463777777777764 + 0.17326234459244849 50.496444444444435 + 0.18292478075752774 51.550888888888892 + 0.20813821528624299 54.283999999999999 + 0.28316549341513542 62.728333333333332 + 0.29569047001086607 64.036000000000001 + 0.5449575641554919 90.902000000000001 + 0.85534408291427244 149.14111111111112 + 0.95411284228111326 185.28999999999996 + 1.0783242151543773 258.0022222222222 + 1.1735998839160162 344.74333333333334 + 1.297057135689808 584.82555555555541 + 1.4094468978188461 1089.5111111111109 + 1.4221166785377204 1171.5666666666666 + 1.4791182802584348 1632.6222222222223 + 1.5842443097787484 3271.411111111111 + 1.7757899007982414 10027.566666666666 + 1.8733590444723855 16325 + 1.9777506734496346 28582.111111111109 + 2.0289606074821238 38616.777777777774 + 2.0503959855000771 43737.888888888883 + 2.0542817946450875 44655 + 2.0616375486221221 46547.333333333328 + 2.0631589664660708 47033 + 2.1045055761627998 64895.444444444438 + 2.2929632827878246 197243.33333333331 + 2.4493208506573469 321430 + + + + = "Steel castings, as cast" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 6.2060000000000004 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 28 + 0 0 + 0.22194987077241227 225.36666666666662 + 0.24551488758529641 237.31666666666666 + 0.34430334498361326 291.79333333333329 + 0.37557345630905609 310.45000000000005 + 0.45441746007971556 358.73000000000002 + 0.62798140744099151 483.88999999999999 + 0.67013362301234491 520.13666666666666 + 0.86145272806437279 723.67333333333329 + 1.0751796105051517 1071.3333333333333 + 1.2410736322807892 1570.5666666666666 + 1.4233877961640156 2775.5 + 1.6562382506561981 6290.5333333333328 + 1.6866257903981818 7049.8666666666659 + 1.8135052258220372 12338.666666666666 + 1.9644220856887178 26304.666666666664 + 1.9790826105195667 28581 + 2.0124329223816582 36287 + 2.0213369102903727 39022.333333333328 + 2.0335027505427044 43292.333333333328 + 2.0509732689380429 50590 + 2.0520705255188347 51118.333333333328 + 2.1919831125116627 134313.33333333331 + 2.1973280088129705 138566.66666666666 + 2.2408245247605874 168803.33333333331 + 2.3097290616994943 223476.66666666666 + 2.3277953138527376 237853.33333333331 + 2.4357836825104187 321480 + + + + = "Carbon steel forgings, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 8.4100000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 29 + 0 0 + 0.22750086321702601 260.63999999999993 + 0.25470545979310849 280.21333333333331 + 0.28326856610354773 301.25333333333333 + 0.32904979636553344 334.06333333333333 + 0.65254151197752852 542.32999999999993 + 0.66749236607661877 553.62 + 0.98113689796108794 862.2733333333332 + 1.1422284706723329 1163.2666666666667 + 1.2786394193015127 1569.8666666666668 + 1.4093569171756908 2140.833333333333 + 1.6283110950732884 4703.8999999999996 + 1.7078750346842446 6691.1666666666661 + 1.7267353325576187 7269.6666666666661 + 1.8315256093435892 11957 + 1.8820380337618272 15335.666666666666 + 1.8901210956394068 15985.333333333332 + 1.8941754023883211 16320.333333333332 + 1.9547466996125868 22982 + 2.0110621023626405 35912.333333333328 + 2.0199377480484135 39023 + 2.024817901264111 40678.333333333328 + 2.0648044125044942 59739.666666666664 + 2.0852709953440494 71278.333333333328 + 2.086206771075799 72023 + 2.0904381513635188 74302.666666666657 + 2.0989149354262007 79907.666666666657 + 2.1458546190022632 114953.33333333333 + 2.4130442131136016 324950 + + + + = "3% Si strip, oriented" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0299999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.05246549309944102 4.9312592592592583 + 0.055391993406083542 5.0346592592592581 + 0.058318496435439696 5.1402259259259244 + 0.074660202414140814 5.7020259259259252 + 0.076324499345763436 5.7614777777777775 + 0.079904391813793815 5.8822185185185178 + 0.10853900605006972 6.8720555555555549 + 0.11392881647253879 7.0159259259259246 + 0.24101802116881355 8.446162962962962 + 0.48459275962277754 10.153785185185182 + 0.99236860298810226 16.277444444444441 + 1.1023984493889492 19.397259259259258 + 1.1430968459911965 21.068629629629626 + 1.1735429836842679 22.416074074074068 + 1.1932259601449735 23.605740740740742 + 1.4340113070526503 50.26025925925925 + 1.5469578997327189 84.390222222222221 + 1.5822267873504399 103.84148148148145 + 1.6675857599632533 221.50592592592585 + 1.7740108114029667 827.95666666666659 + 1.78140530841824 909.04962962962941 + 1.8129047879786413 1465.6777777777775 + 1.8555748924648665 2732.8111111111102 + 1.9142973597815689 6470.1999999999989 + 1.9245752602223902 7560.8037037037011 + 1.9362849851201365 9210.1962962962934 + 1.9583858490824357 13667.222222222221 + 1.9725143900109607 18664.999999999993 + 2.0006062016148736 33397.999999999993 + 2.0817033193784127 87776.592592592584 + 2.0900259335520763 94399.518518518496 + 2.3806075759315881 325080 + + + + = "M-27" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0299999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.038130201690622492 24.298999999999996 + 0.086404146886738822 38.579333333333331 + 0.097273491812906593 39.384333333333331 + 0.10859385810190443 40.206333333333333 + 0.11447771545289238 40.623333333333335 + 0.17787385370605846 45.507999999999996 + 0.18964838000684214 46.457333333333338 + 0.1950823194581181 46.939666666666668 + 0.25394873291480063 52.043333333333329 + 0.33998222992868687 60.13133333333333 + 0.65194475295724141 96.62266666666666 + 0.83626894647532968 134.44333333333333 + 1.0429529830435345 227.84333333333331 + 1.0796908664621463 257.99000000000001 + 1.295266662811603 742.71999999999991 + 1.4631832646660787 2161.8000000000002 + 1.5341330143926522 3342 + 1.6529901957958524 6225.7666666666664 + 1.6947934982891031 7740.3666666666659 + 1.7390524951276174 9723.7000000000007 + 1.7594211728903348 10786.333333333332 + 1.8478034790283238 16846.666666666664 + 1.9536259611096132 32727 + 1.9840482550598542 42426.666666666664 + 2.0131204838062411 55004.333333333328 + 2.0206009376408058 59153.333333333328 + 2.0654168165912949 87787.333333333328 + 2.1183636442000422 127613.33333333333 + 2.3628481072582348 321770 + + + + = "M-22" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0299999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 37 + 0 0 + 0.062675059890913154 27.104000000000003 + 0.065847414262564477 27.385999999999999 + 0.088958667088303592 29.443999999999996 + 0.10345689784923273 30.688666666666666 + 0.11886019395528903 31.985333333333333 + 0.13381189250971706 33.337000000000003 + 0.1827374279959727 37.741999999999997 + 0.1908917528159475 38.531000000000006 + 0.79423287231542106 140.21999999999997 + 0.93833452157187403 197.23666666666662 + 0.98184152670232427 218.72666666666669 + 1.0144621481165026 235.13666666666668 + 1.0525243045152348 258.07333333333332 + 1.1473712001398102 348.44333333333327 + 1.1946053827861141 428.69666666666672 + 1.2319025459637043 506.01666666666665 + 1.3777887839557001 1078.6333333333332 + 1.3796362335120236 1089.8666666666663 + 1.4035174688863727 1313.6666666666665 + 1.4104053915927715 1383.6333333333332 + 1.4270025673844073 1567.0666666666668 + 1.5118032580954526 2920.4333333333329 + 1.5314769966898023 3377 + 1.6172204229743854 5851.9333333333325 + 1.6733003407494156 7904.9666666666672 + 1.6896261282870839 8588.6333333333314 + 1.7699390724013586 12604.333333333332 + 1.8054637506247513 14878.666666666666 + 1.8658202043226608 20308.333333333332 + 1.8837508943760881 22295.666666666664 + 1.9297459556186265 28896.666666666664 + 1.9864586913965505 44689.666666666664 + 2.0114120646137197 57942 + 2.2345033384613493 228390 + 2.3083302348557941 287060 + 2.3520983727406923 321810 + + + + = "M-19" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0299999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.056240213271912282 22.716666666666669 + 0.065763087985674012 23.677999999999997 + 0.092969013625486957 26.536666666666665 + 0.098407378144601765 27.092000000000002 + 0.36065406660251248 48.329999999999998 + 0.44035017689669587 55.844999999999999 + 0.65681388869914303 82.671999999999983 + 0.92451110140083426 141.46333333333334 + 0.94716719703425167 148.96666666666664 + 1.1448273288217627 260.48000000000002 + 1.2406621335272494 394.28000000000003 + 1.2488497776552618 410.97333333333336 + 1.322607178813346 615.80666666666662 + 1.3563955151985336 765.67999999999995 + 1.4314419974780463 1518.8666666666663 + 1.4472868605756064 1793.2999999999997 + 1.5567967988753451 5010.8333333333321 + 1.5995275190710436 6494.1999999999989 + 1.7207170253103174 11605.333333333332 + 1.8444682987619752 19895.666666666664 + 1.859983655534319 21393.333333333332 + 1.8819875018925818 23730.666666666664 + 1.8862458027244693 24228 + 1.9773169038347667 44232 + 1.9921889030389557 51690 + 2.0112933854699198 64293.333333333328 + 2.0381582919895438 83364 + 2.0858876566852138 121186.66666666666 + 2.1645772075425009 183646.66666666666 + 2.3302548336176727 315250 + 2.3343933583400016 318543.33333333331 + 2.3427835051201891 325220 + + + + = "M-14" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.74 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 34 + 0 0 + 0.068203780765395211 14.68 + 0.075018096370031567 15.461666666666666 + 0.091366778358032724 17.330666666666662 + 0.094997568269498373 17.693999999999999 + 0.11314440933716036 19.42433333333333 + 0.1389767940154239 21.321999999999999 + 0.40116353032668717 34.640333333333331 + 0.53244906843212858 41.699999999999996 + 0.85211868548509462 70.573666666666668 + 1.0166007917290236 106.73333333333335 + 1.027005026595921 110.10333333333332 + 1.0764632916085533 129.9433333333333 + 1.1823010818623396 239.59333333333336 + 1.2023148179645375 277.05000000000001 + 1.3383811509208308 1046.0333333333333 + 1.3688427556013982 1413.3666666666668 + 1.4271095672819165 2527.5666666666666 + 1.4454166392095997 2984.1333333333332 + 1.4835332597467681 4031.8666666666659 + 1.5204669339556516 5225.7999999999993 + 1.551748178088983 6298.4333333333325 + 1.6016510722943771 8077.9666666666653 + 1.6590536390010702 10467.333333333332 + 1.7791582753310031 18322.666666666664 + 1.7906360805152517 19498.666666666664 + 1.8514598080908595 29226 + 1.8557505336223326 30465.333333333332 + 1.8632005510398157 33104.666666666664 + 1.9469769814722375 90700 + 1.98399278954702 120076.66666666666 + 2.0742554367752168 191666.66666666666 + 2.1765362540658613 272900 + 2.2428861599447636 325620 + + + + = "Malleable iron castings, as cast" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 28 + 0 0 + 0.26353350565096512 119.50333333333333 + 0.28347480606326797 125.84333333333332 + 0.29933482051697791 131.16 + 0.4207500729612299 169.82333333333332 + 0.45381704499546999 180.67666666666665 + 0.67398294368797651 270.25333333333333 + 0.81584827040356445 364.67999999999995 + 0.88341739759420257 430.30000000000001 + 0.96930327852010711 599.43999999999983 + 1.0593938564852876 870.46333333333325 + 1.1082695343941515 1116.3666666666666 + 1.1913079396270332 1836.5999999999999 + 1.209286913054672 2058.5999999999999 + 1.2875299671669662 3604.833333333333 + 1.3058304721307243 4082.6999999999998 + 1.3585099185476681 5870.1000000000004 + 1.6912560843583471 38772.333333333328 + 1.7851774626967321 59320.333333333328 + 1.8443829240342642 76089 + 1.8576389707997463 80139 + 1.8912461849042881 91710 + 2.0773791540119309 187706.66666666666 + 2.0798421626523451 189666.66666666666 + 2.1199642833769925 219366.66666666666 + 2.2019378457548324 284440 + 2.2171096438765687 296513.33333333331 + 2.2536233280916917 325570 + + + + = "416 stainless steel, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.74 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.20778995919879328 320.92999999999995 + 0.22364931371099023 331.02666666666664 + 0.25084135512504779 348.56666666666666 + 0.26171716173194137 355.83999999999997 + 0.28346935718756683 370.84999999999997 + 0.2889075243847965 374.6966666666666 + 0.41218760024480688 470.25 + 0.62566054494422463 660.92666666666662 + 0.68005862210630241 717.75333333333322 + 0.78252281053007089 837.79999999999984 + 0.80020925624997319 864.15000000000009 + 0.95816502937412396 1165.8333333333333 + 1.0767969774200417 1509.5666666666666 + 1.1100488305016618 1656.9333333333329 + 1.2055703265999278 2284.1333333333332 + 1.2385842209600626 2613.5 + 1.3726454443074343 4969.9666666666662 + 1.4275581497186043 6783.833333333333 + 1.5422692199452028 12124.333333333332 + 1.5580865944646081 13172.666666666666 + 1.5620671785059184 13449 + 1.6334236260295694 21451.666666666664 + 1.6754034599026606 30215.666666666664 + 1.6932013471857443 36049.666666666664 + 1.7139092459532073 44836 + 1.7383144421097252 58739.666666666664 + 1.76404286494438 76959 + 1.8507986277495354 143556.66666666666 + 1.8769989795155597 164326.66666666666 + 2.0216195572312698 279173.33333333331 + 2.0403266942858456 294060 + 2.0765429743964292 322880 + + + + = "Nodular cast iron" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.8999999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.20811990626542368 442.90666666666664 + 0.2339817229580381 476.18333333333339 + 0.2580267002999177 506.66999999999996 + 0.33558117574742435 597.76666666666665 + 0.35734951804561954 622.97333333333336 + 0.37367414813202371 642.57333333333327 + 0.62952161994988698 1022.5333333333333 + 0.87264196855053022 1696.5666666666666 + 0.9254635809159979 1920.6666666666665 + 1.0541258994226004 2646.6666666666665 + 1.1117915212006495 3123.2999999999997 + 1.3675522509279685 9272.5666666666657 + 1.3820293835968507 9970.5666666666657 + 1.4294741578988148 13056.666666666666 + 1.5049974550507339 20396.333333333332 + 1.5359095135457697 25101 + 1.5865666568750856 36473 + 1.5921431699844191 38019.333333333328 + 1.6496895337412476 56995.666666666664 + 1.6745253616249656 66600 + 1.7046130237917372 81126.333333333328 + 1.710171725582756 83693 + 1.7750575095432943 117900 + 1.8024488353076902 133543.33333333331 + 1.8526242892450928 164373.33333333331 + 1.9451044593202931 229186.66666666666 + 2.0044465191865868 276330 + 2.0452597902950234 306580 + 2.0700281067759252 326290 + + + + = "Gray iron, as cast" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.1000000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.2072800462748759 907.22000000000003 + 0.22092823830618194 945.57000000000005 + 0.24278094325321312 1027.3 + 0.26190362997185557 1093.0999999999999 + 0.29469938040025895 1225 + 0.34939479630267944 1476 + 0.40964167591244921 1815.7 + 0.46723779622430406 2210.5 + 0.56073947578101979 3047.4000000000001 + 0.69482990037208558 4806.3999999999996 + 0.7101108454775763 5061.8000000000002 + 0.79373280813519509 6694.6999999999998 + 0.86963906456124596 8673.2000000000007 + 0.95759568017910379 11591 + 1.0294826178995993 14708 + 1.0947013432220716 17906 + 1.1224441041190516 19452 + 1.3178994122609824 34377 + 1.3493191995132845 37735 + 1.3558119427918187 38525 + 1.4101461544904934 44998 + 1.4871175868899893 56514 + 1.5434202052718986 66702 + 1.6015122569094034 80383 + 1.6844610507161304 105250 + 1.8855792706643855 200280 + 1.9560736020145681 246510 + 2.0008727132547586 282160 + 2.0565035049996117 326350 + + + + = "Deltamax, oriented" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0880000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 35 + 0 0 + 0.11959702268528663 7.0522135514572613 + 0.13479435602367557 7.1545851801046556 + 0.22331089034898249 7.4592268488882079 + 0.25625232473327092 7.5341422259479387 + 0.43940221643173732 7.8365673813273684 + 1.1323781929057959 8.8039765178072393 + 1.1764352556501918 8.8912772968212792 + 1.2789189633243017 9.161676131687237 + 1.4161191839433638 10.469805497129496 + 1.424112947455225 10.688685818557463 + 1.4411188616107593 11.256383596673942 + 1.4441050763676266 11.373564294060859 + 1.4936604371202056 17.770826449220127 + 1.5084178899148384 28.956738877881069 + 1.5154149132478214 45.266431878609268 + 1.5255464509565075 117.74272570238273 + 1.5345585807432631 357.92860641162406 + 1.5412817494070279 940.77824992802562 + 1.5457546250990917 2029.7485139460441 + 1.5486412429254133 2524.7071533810886 + 1.5494336987841 2659.3257565750464 + 1.5507128482287165 3557.4545411437944 + 1.5507747108822383 3594.6177530525483 + 1.5520734359067678 4517.934391776319 + 1.5622860432334038 10161.423693881348 + 1.5628827141990107 10592.551196463948 + 1.569343527757411 15559.24359430303 + 1.5749906968995344 19966.454588562032 + 1.5937218838820988 34633.525817541333 + 1.6271373788221937 58837.124642246243 + 1.7420874208391619 149910.7886670391 + 1.7881678912943615 186470.28603363299 + 1.8277593090512831 217923.31538214014 + 1.9604084610740751 323330 + + + + = "4750 alloy" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0880000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.062267620425941785 2.6157851851851843 + 0.069980092994661514 2.7265851851851846 + 0.078144904714478769 2.8420148148148141 + 0.10877931438286799 3.2859111111111106 + 0.14025235738210864 3.644333333333333 + 0.58980515977882919 7.3480666666666652 + 0.77701571002182934 10.438518518518515 + 0.79608626377989444 10.879185185185182 + 0.89548789324334965 13.944259259259258 + 1.0156410564218947 20.882407407407406 + 1.113061235894111 33.993407407407403 + 1.1559892735560493 44.51581481481481 + 1.1926058372891561 57.6968148148148 + 1.2782142659115054 135.13962962962958 + 1.3714289091077587 406.15592592592594 + 1.4733389312506926 1702.1074074074072 + 1.5009561826635593 2744.4481481481475 + 1.5130476727071458 3595.344444444444 + 1.5374771630921702 6775.3851851851841 + 1.539637301213713 7362.5999999999985 + 1.5616654662184086 20173.407407407405 + 1.5754169603223946 30889.555555555551 + 1.5792231278130302 33918.407407407401 + 1.6028430733907113 52478.777777777766 + 1.6132108575023323 60696.777777777766 + 1.6270751198508848 71676.555555555533 + 1.701965485861944 130959.99999999997 + 1.7379936506252971 159547.77777777775 + 1.8143586195726003 220187.40740740736 + 1.9118105614895025 297628.14814814809 + 1.9277013566015917 310261.8518518518 + 1.9442838592977614 323390 + + + + = "Perminvar (45% Ni - 25% Co)" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 5 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.059487977354561211 105.59240020967941 + 0.063666234163931551 113.85544401797279 + 0.069154906561324947 123.71897439708243 + 0.11707455730941742 181.62079749450101 + 0.28790092738542783 244.98915255823164 + 0.60772482745503509 288.19289155257906 + 0.93066785133093488 413.02881886524807 + 0.95212011691157006 430.44908017881323 + 1.045033335553744 523.82915617904769 + 1.1538742398505948 707.14139957339069 + 1.384025586491457 1636.3640249481118 + 1.4337679537605279 2210.5934347039984 + 1.4766480026856466 3638.5168942899409 + 1.4899186887506606 4525.2038306201412 + 1.515966953147988 12142.277189023891 + 1.5173979887638001 13194.977390331609 + 1.5294414377083179 20414.692825678798 + 1.5405107526549182 29066.366118374579 + 1.5519461022782819 36153.723834066106 + 1.5842830298198454 61421.432494844834 + 1.585092130119339 62063.036252142432 + 1.5884179333642736 64697.169202979698 + 1.6750301239192267 131149.3675944063 + 1.6838579935167186 138143.03255764666 + 1.6893746968867345 142516.70204276522 + 1.7763070185278256 211528.30167533935 + 1.8180181609624082 244653.96116183657 + 1.8447006742641938 265862.60916767397 + 1.9130249215893231 320160 + + + + = "Powdered iron, sintered and annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 30 + 0 0 + 0.14489737221888069 123.46444444444444 + 0.18035833023209358 128.64777777777775 + 0.24283262175515918 138.2522222222222 + 0.27829214364244492 144.06111111111107 + 0.28719623546136192 145.54888888888888 + 0.40384795559679987 166.37 + 0.45742126477954398 176.96111111111111 + 0.48397934045250218 182.50333333333333 + 0.76894770752370123 261.6655555555555 + 0.80911679182839358 281.27333333333331 + 0.88730316007951449 360.61333333333329 + 0.95505044905214931 497.27444444444438 + 1.0051886127306782 671.76777777777772 + 1.0271205554333389 776.76444444444428 + 1.0431274425422967 870.66444444444437 + 1.069308052390642 1093.9666666666665 + 1.1160597915541866 1745.2333333333329 + 1.1385067763613901 2215.8777777777773 + 1.1535654614710764 2616.255555555555 + 1.2087708567531532 4441.9888888888881 + 1.2417107932828517 5817.7444444444427 + 1.3585735640225884 12799.777777777776 + 1.3665213279765531 13341.777777777776 + 1.4823755000676118 22403.666666666664 + 1.6572199836940955 60662.777777777766 + 1.7148378000293576 86345.111111111095 + 1.716725725203607 87246.222222222219 + 1.9032345902355345 200244.44444444441 + 2.06734067314654 326300 + + + + = "Monimax, oriented" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.45 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.10034521782368207 6.978358573388201 + 0.14639118367621862 7.4555030178326458 + 0.1726687859761088 7.5407312757201632 + 0.23288928934882028 7.6935098765432075 + 0.34013938512652697 7.9269174211248252 + 0.37984951182725052 8.0059106995884726 + 1.0431626412058028 9.1862737997256492 + 1.1805225923732723 9.6604650205761295 + 1.196780971671243 9.9644839506172804 + 1.2011550337153132 10.173230315500684 + 1.2200842354505606 13.325835390946498 + 1.2657607161778803 48.316399176954725 + 1.2902251901576292 109.77502057613165 + 1.2926116306305329 119.28840877914948 + 1.305198313233686 194.38117969821667 + 1.3060805557942006 202.62801097393685 + 1.3117444442344035 271.0435390946501 + 1.3151986554172004 347.80463648834007 + 1.3334555146827605 1635.7266117969814 + 1.3372274829737565 2328.8528120713295 + 1.3573169335584687 9084.5429355281158 + 1.3579844854666616 9569.0434842249633 + 1.3602367288165333 10953.282578875167 + 1.3687244735968811 15757.475994513024 + 1.3753151315127625 20861.338820301775 + 1.4364902949954648 64749.999999999985 + 1.4436210965864285 70363.272976680353 + 1.4980729114003877 113488.01097393688 + 1.5088720189758402 122049.5747599451 + 1.5432163327934059 147151.74211248281 + 1.5790463340081988 175584.77366255136 + 1.7702109385084199 327470 + + + + = "Monimax, nonoriented" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.45 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 35 + 0 0 + 0.056977218349100994 3.3568555555555553 + 0.060456528996684446 3.4272222222222219 + 0.081042313358082527 3.9629777777777777 + 0.091480633060513586 4.2173888888888893 + 0.71903672681826125 16.847555555555552 + 0.76587498739020854 19.884333333333331 + 0.89521052564163306 41.091222222222214 + 0.93154623496586031 52.708111111111101 + 0.96761301054901838 70.478666666666669 + 0.97155469964415908 72.706999999999979 + 0.97974158406048695 78.185444444444443 + 1.1131449015027493 292.14777777777772 + 1.1756331241798743 636.45333333333326 + 1.210860965124942 994.60222222222205 + 1.2144028533800286 1036.7777777777776 + 1.241524109578678 1460.422222222222 + 1.2854932837050883 2505.766666666666 + 1.3089440574557867 3386.1555555555556 + 1.346656284631955 6720.4555555555544 + 1.3494821349220179 7227.333333333333 + 1.362178409868281 10725.777777777777 + 1.3647799967897294 11655.444444444442 + 1.3670887223734525 12405.111111111109 + 1.3849063614709849 21968.444444444442 + 1.3882491556807444 24628.555555555551 + 1.4064912800175862 38906.444444444438 + 1.4191492730515356 48899.777777777766 + 1.4383785654348249 64069.333333333328 + 1.4645892121880559 84821 + 1.5083904690560177 119517.77777777777 + 1.6568027672055463 237302.22222222219 + 1.7453686200672334 307701.11111111107 + 1.7494066138246471 310914.44444444438 + 1.7702109385084199 327470 + + + + = "65 Permalloy, oriented" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.3199999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 32 + 0 0 + 0.24726764334342236 1.2507793933851539 + 0.34168281210524115 1.3691061118731893 + 0.4862630039087944 1.4698539484157216 + 0.72680259434977013 1.6431073362800377 + 0.86088809181380999 1.7642578892106546 + 1.1521148143121054 2.2097483649172709 + 1.2175388267072618 2.6074123033412913 + 1.2508763064389954 3.4866292739927838 + 1.2645325899567788 5.5645116411793554 + 1.2689368122302571 7.4434211536181794 + 1.2761681920236325 11.162203644430889 + 1.2806381033865866 15.564928042811895 + 1.2828995330922288 18.189650273501659 + 1.2923232147175603 35.738448220969005 + 1.2995217368453504 63.949282799031273 + 1.3087347865513519 186.48411641179351 + 1.3263772401840255 2211.5251096546922 + 1.335994806905622 5293.802086402814 + 1.3423801595220255 8021.9080272316178 + 1.3431454911045453 8627.1984690680547 + 1.3486564292343524 10730.789229284146 + 1.3554102030766064 15926.7712069637 + 1.3794336758392822 34722.562498941537 + 1.3919220468719029 44558.425324730284 + 1.422832802759713 68941.394723026606 + 1.4510116474769781 91271.242408846811 + 1.4836739160184191 117124.27949668915 + 1.5015228792570605 131307.64856305771 + 1.5235231773448787 148748.72478788794 + 1.555152308491794 173839.19558332898 + 1.7470514698350668 324160 + + + + = "Sinimax" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.1599999999999999 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 31 + 0 0 + 0.049470588695617601 2.0600185185185178 + 0.075689332979866714 3.1533444444444436 + 0.080989389778738083 3.2869629629629622 + 0.18334532315428545 4.530762962962962 + 0.52946490394825907 11.860185185185184 + 0.6097107636468766 16.523185185185184 + 0.66556127472900206 24.003444444444444 + 0.73085136580915511 43.822925925925915 + 0.76382978865680251 61.725407407407403 + 0.81118930590470928 100.5405185185185 + 0.85263604885314204 150.70555555555555 + 0.91234960630389017 266.71333333333325 + 0.95234426279575202 399.80592592592586 + 1.005629264270619 768.95814814814798 + 1.035741084226431 1305.9333333333329 + 1.0464669930748007 1624.2296296296292 + 1.0762523469826892 2935.9185185185179 + 1.0826494937782061 3325.6407407407405 + 1.0941984235799245 5091.7037037037026 + 1.116730273175484 13950.148148148146 + 1.1178582212934063 14847.740740740739 + 1.1268006442480378 19656.148148148142 + 1.1298546826698987 22036.370370370365 + 1.2103171487613098 83331.259259259241 + 1.2268157969919147 96380.888888888876 + 1.2346063882674567 102580.44444444444 + 1.3440236179431095 189383.70370370365 + 1.3871408086500354 223642.22222222219 + 1.4380755208195561 264098.14814814809 + 1.5190675755698559 328470 + + + + = "78 Permalloy" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.3199999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 34 + 0 0 + 0.10591921206800799 2.0633002692678941 + 0.13778956866609487 2.5338565039204708 + 0.13946561771868463 2.5602772968212824 + 0.16025871538631711 2.8696195871225574 + 0.17607096899997499 3.0855623109620809 + 0.23384830392847505 3.6792053836644127 + 0.27063606232746218 3.9963846144727242 + 0.33230850685462332 4.5238134108960315 + 0.44884016156493978 5.5610871276397535 + 0.48866857268618724 6.040289059933273 + 0.56618388521890006 7.7441213636132673 + 0.64328902808242039 12.222245203136371 + 0.67752500258815562 15.515751613067106 + 0.69264258494487729 17.57321895375026 + 0.76613032682626492 31.095154261714832 + 0.84664023271147948 59.786150214228833 + 0.92639676309552821 121.08316957103416 + 0.93253627130392025 128.86437704279487 + 0.95346116920678359 163.61486748293783 + 1.0308372620291448 507.40405967924926 + 1.0396850601434653 599.12832969228896 + 1.0449378402908196 685.74748124438986 + 1.0599152831326242 936.44060407458164 + 1.07109277258876 1347.0656251587654 + 1.0906270507544935 6468.5022591407105 + 1.0986493889067872 12578.78697353045 + 1.1262658449442227 34111.643160764754 + 1.1535317682695525 55592.85860895185 + 1.1662546877881663 65649.111686904056 + 1.1992893188469278 89661.924418703027 + 1.2240107343187734 109234.65455807882 + 1.2313842386813008 115059.63894392786 + 1.4916606736288494 321780 + + + + = "Moly-Permalloy" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.74 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 31 + 0 0 + 0.17342202193002826 2.1002197530864191 + 0.17704587655192039 2.1220728395061723 + 0.20241336086323294 2.2815148148148143 + 0.21328789570021867 2.3534469135802465 + 0.248628218162597 2.6100543209876541 + 0.25587705220552792 2.6646530864197526 + 0.27753640248956957 2.8353320987654316 + 0.4013252804277172 4.2020308641975292 + 0.49518749912301835 6.3605876543209874 + 0.55565902461704286 9.8341444444444424 + 0.63928682301935891 22.327518518518517 + 0.73358328357855096 83.467629629629613 + 0.73751798255679335 89.76129629629628 + 0.74857222987028715 120.05999999999997 + 0.7584803641647393 163.96395061728393 + 0.76889873611519133 243.32654320987652 + 0.77249351794877574 281.41888888888877 + 0.78946478669847386 541.49740740740731 + 0.79722402458784869 724.31209876543198 + 0.81312408883832643 2112.0567901234563 + 0.81966552836360429 4799.8753086419747 + 0.82168535656701114 6288.8197530864172 + 0.85770506135513991 34214.382716049375 + 0.85816038110286375 34571.802469135786 + 0.88578623434625947 56342.765432098749 + 0.96817135160806567 121566.66666666664 + 1.0725357555310444 204391.35802469129 + 1.1007201134617026 226774.07407407399 + 1.1854052138978768 294050.86419753078 + 1.2301501418198926 329610 + + + + = "Supermalloy" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.74 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 34 + 0 0 + 0.45479029884017119 0.89276806584362112 + 0.47419418182153228 0.96993683127571995 + 0.47666234266704122 0.98004106995884754 + 0.52354739998319166 1.205765432098765 + 0.60583926518525566 2.0678353909465015 + 0.6870463510249275 5.8399353909465006 + 0.73210866957846443 13.972584362139912 + 0.7401172916907971 17.198823045267485 + 0.74138163830270609 17.74318106995884 + 0.74192355836466972 17.928452674897109 + 0.75088906285440749 23.487711934156373 + 0.75398238410900709 26.883884773662544 + 0.75853071440168751 31.417053497942383 + 0.77070125414344937 70.652864197530818 + 0.77686964210308851 201.80267489711929 + 0.78047547529222039 508.83897119341543 + 0.78369309757075634 820.67201646090507 + 0.78382107107870935 829.24399176954705 + 0.78476070449328772 1337.4621399176951 + 0.78683375143078493 2683.2724279835384 + 0.78708489830045059 2855.9152263374476 + 0.79016400327690006 5057.8288065843608 + 0.80717096918921771 20147.658436213984 + 0.81184199920930722 23792.111111111102 + 0.81847609246773756 28985.489711934151 + 0.82294934414167908 32495.77366255143 + 0.85324852794507511 56366.69547325102 + 0.86356780432482472 64519.666666666657 + 0.91216302371712621 102985.7407407407 + 0.92639071434526665 114262.7160493827 + 0.95603081708491011 137768.31275720158 + 0.96720493282201248 146633.37448559664 + 1.1934583722583829 326330 + + + + = "Mumetal" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 1.74 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 27 + 0 0 + 0.079966858795000512 0.860246172839506 + 0.081044746616295307 0.86922098765432065 + 0.093001903409685144 0.97434444444444424 + 0.09407978038038875 0.98450901234567878 + 0.10179298471178473 1.0586913580246911 + 0.11568200065910944 1.1990987654320986 + 0.2226534509330822 2.3531901234567894 + 0.23852219194772517 2.5302469135802466 + 0.39193101337971092 5.227392592592591 + 0.47972626545915664 10.585790123456787 + 0.55605040558227847 32.15374074074073 + 0.56130482779669588 35.672827160493817 + 0.56267995010401561 36.801716049382705 + 0.59075471532157364 65.154703703703674 + 0.59626410190450307 73.8032345679012 + 0.60773381317835806 94.695888888888874 + 0.62329794744825984 149.56382716049382 + 0.63033195674187881 206.39543209876538 + 0.63313084141938702 233.80209876543205 + 0.64463535651486892 449.89641975308632 + 0.66396464451248827 4072.1679012345671 + 0.68133287065863002 17264.209876543202 + 0.68156519359361811 17444.469135802465 + 0.74685455816660673 66655.654320987625 + 0.91052413286942624 196427.40740740736 + 1.0703815584096044 323420 + + + + = "Pure nickel, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 13.34 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 34 + 0 0 + 0.056855498921438249 63.557962962962947 + 0.070678815645204229 69.056222222222203 + 0.088178266679553932 75.81081481481479 + 0.090245555812212996 76.600888888888875 + 0.092262596017961954 77.399185185185175 + 0.22449927969650391 141.19259259259255 + 0.25744314554104863 166.66851851851848 + 0.26653021876855176 175.53925925925921 + 0.2883140227837529 205.0922222222222 + 0.33367873773909384 301.09518518518513 + 0.35266418775503294 366.73629629629625 + 0.40464612091220142 850.45518518518497 + 0.41024715205926787 943.52666666666664 + 0.43386747638494338 1687.9814814814813 + 0.47001454453115399 3180.5259259259255 + 0.49039910037484669 4166.1962962962953 + 0.49489231771762254 4434.0148148148128 + 0.50855763419556077 5127.6222222222214 + 0.54638044433672417 7767.1148148148131 + 0.5866852204722478 13328.370370370369 + 0.59050850127230825 14185.407407407405 + 0.60358296962162661 17460.481481481478 + 0.61321263700227191 19984.296296296292 + 0.62526813614782761 26455.962962962956 + 0.63207036589456078 29658.81481481481 + 0.64302656710489081 36131.62962962962 + 0.68293292539634209 63324.185185185182 + 0.69451779102009592 72483.592592592569 + 0.73737836973209903 104274.07407407406 + 0.76776436519503055 128363.70370370368 + 0.88366391945605305 220358.14814814812 + 0.98122238054043609 297860.37037037034 + 1.0094608507779244 320300 + + + + = "Soft magnetic ferrite (Fe-Ni-Zn-V)" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 27 + 0 0 + 0.068850756910128444 44.63519753086419 + 0.079231351768504585 47.996938271604932 + 0.096629805222867599 54.360481481481472 + 0.10428518223687107 57.254135802469136 + 0.11791981395323581 63.513925925925903 + 0.12337443073651684 66.205407407407364 + 0.15091206297703 83.18401234567898 + 0.19174942986281673 128.63864197530862 + 0.20263507284968685 150.32185185185182 + 0.2390242052470492 280.2956790123456 + 0.24393625127711305 307.76197530864192 + 0.24555614462251754 317.50148148148139 + 0.26724361274612662 486.03790123456781 + 0.29056515192641547 775.60827160493818 + 0.29618977849347761 869.47777777777765 + 0.31289613290425267 1359.0728395061724 + 0.31335557743458525 1373.2691358024688 + 0.33594174880643024 2431.4518518518512 + 0.36483908041448099 5699.1765432098764 + 0.36848205798752964 6389.1543209876527 + 0.37676605298145499 8458.0074074074037 + 0.47711675995875713 61532.617283950603 + 0.49488110240278821 73419.641975308608 + 0.6669901800055722 197003.70370370365 + 0.82853938560684104 321027.90123456786 + 0.83272023087673985 324350 + + + + = "30% Ni-Fe temperature compensation alloy" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0299999999999998 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 32 + 0 0 + 0.060113308674792906 142.95456790123455 + 0.062857638858785259 149.01370370370367 + 0.069720083054575957 165.32197530864192 + 0.071092776918512457 168.79197530864195 + 0.072465561539570067 172.33419753086415 + 0.073160377025011297 174.13259259259257 + 0.075211620686610747 179.64148148148143 + 0.07865298344971032 189.21419753086414 + 0.090573511527902453 230.48419753086415 + 0.09173014719001045 235.32259259259254 + 0.096081218950381131 253.06358024691352 + 0.11106929969834518 349.19061728395047 + 0.12633098005016211 512.82654320987638 + 0.13565984935109959 664.89234567901224 + 0.14608535460629327 889.33938271604916 + 0.16792449506871465 2084.6753086419749 + 0.18605976885809922 4138.3358024691352 + 0.19379963309702175 5593.4148148148133 + 0.21167448348931983 10875.91358024691 + 0.22129772754588689 14101.382716049382 + 0.22688329029513268 16309.024691358021 + 0.23985503757386678 21589.938271604929 + 0.32351551293721692 65616.012345678988 + 0.3375286151160129 73558.74074074073 + 0.3723983380111674 94385.123456790112 + 0.38977543731306441 104715.80246913579 + 0.47891664646063203 158645.9259259259 + 0.52519022474047605 187319.25925925924 + 0.58521776351433052 225820.12345679011 + 0.66940592764230478 280840 + 0.73279031933069971 324740 + + + + = "Monel, annealed" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 2.0880000000000001 + = 0 + = 0 + = 0 + = 0 + = 0 + = 1 + = 0 + = 0 + = 33 + 0 0 + 0.06385547268601896 168.80530864197527 + 0.065672720473441859 170.56456790123454 + 0.069307372126070438 174.13851851851848 + 0.10086606319840659 209.87938271604935 + 0.11042509267557883 225.69061728395059 + 0.11257005387905053 230.42456790123452 + 0.1136509763173387 232.82876543209869 + 0.120958904419634 252.99012345679012 + 0.12429732314896022 263.71753086419744 + 0.13537724713853658 308.16148148148142 + 0.14155244655573135 363.87703703703693 + 0.14505446855037543 407.92740740740737 + 0.15088961590713745 534.4353086419751 + 0.15699115352979087 861.9265432098764 + 0.17434963029540401 1542.1333333333332 + 0.18662093286025705 2385.7086419753077 + 0.19283770520395996 2936.6456790123448 + 0.20908477804280093 5093.0271604938262 + 0.21445381732176208 6812.8061728395041 + 0.21524141771760777 7403.4049382716039 + 0.23144819934385918 19869.061728395056 + 0.24039356143004514 26857.185185185175 + 0.24830440071119164 33061.555555555547 + 0.26672886502187387 47564.123456790112 + 0.29136783486743895 67021.469135802443 + 0.29776257091693137 72078.407407407387 + 0.32725369177333019 95424.28395061726 + 0.39310792044175674 147639.99999999994 + 0.49190301531745756 226071.97530864191 + 0.51657447176451354 245669.1358024691 + 0.58017915554525556 296202.59259259253 + 0.61666837237896033 325200 + + + + + = "15% Copper Clad Aluminum Magnet Wire" + + = "10AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.5881964804969222 + = 0 + + + + = "11AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.3048562119681435 + = 0 + + + + = "12AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.052534341144066 + = 0 + + + + = "13AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.8278351593908164 + = 0 + + + + = "14AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.6277346999432007 + = 0 + + + + = "15AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.4495400418286173 + = 0 + + + + = "16AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.2908530689539455 + = 0 + + + + = "17AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.1495381966308109 + = 0 + + + + = "18AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.0236936312078153 + = 0 + + + + = "19AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.91162577602630535 + = 0 + + + + = "20AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.81182643925900699 + = 0 + + + + = "21AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.72295253689814543 + = 0 + + + + = "22AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.64380801773901508 + = 0 + + + + = "23AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.57332776710822442 + = 0 + + + + = "24AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.51056327271548829 + = 0 + + + + = "25AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 0 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.45466985972222002 + = 0 + + + + = "26AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.40489532323845878 + = 0 + + + + = "27AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.36056980526603466 + = 0 + + + + = "28AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.32109677985343826 + = 0 + + + + = "29AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.28594502514201398 + = 0 + + + + = "30AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.25464147426451217 + = 0 + + + + = "31AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.22676484888450307 + = 0 + + + + = "32AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.20193998969781299 + = 0 + + + + = "33AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.17983280759674947 + = 0 + + + + = "34AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.16014578755066544 + = 0 + + + + = "35AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.14261398469478395 + = 0 + + + + = "36AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.12700145874326854 + = 0 + + + + = "37AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.11309809874142071 + = 0 + + + + = "38AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.10071679542501406 + = 0 + + + + = "39AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.089690923132813724 + = 0 + + + + = "40AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.079872097384249927 + = 0 + + + + = "41AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.071128177944074666 + = 0 + + + + = "42AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.063341490499554454 + = 0 + + + + = "43AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.056407243017805704 + = 0 + + + + = "44AWG 15% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 38.526499999999999 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.050232115470856625 + = 0 + + + + + = "10% Copper Clad Aluminum Magnet Wire" + + = "10AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.5881964804969222 + = 0 + + + + = "11AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.3048562119681435 + = 0 + + + + = "12AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 2.052534341144066 + = 0 + + + + = "13AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.8278351593908164 + = 0 + + + + = "14AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.6277346999432007 + = 0 + + + + = "15AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.4495400418286173 + = 0 + + + + = "16AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.2908530689539455 + = 0 + + + + = "17AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.1495381966308109 + = 0 + + + + = "18AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 1.0236936312078153 + = 0 + + + + = "19AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.91162577602630535 + = 0 + + + + = "20AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.81182643925900699 + = 0 + + + + = "21AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.72295253689814543 + = 0 + + + + = "22AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.64380801773901508 + = 0 + + + + = "23AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.57332776710822442 + = 0 + + + + = "24AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.51056327271548829 + = 0 + + + + = "25AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.45466985972221974 + = 0 + + + + = "26AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.40489532323845878 + = 0 + + + + = "27AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.36056980526603466 + = 0 + + + + = "28AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.32109677985343826 + = 0 + + + + = "29AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.28594502514201398 + = 0 + + + + = "30AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.25464147426451217 + = 0 + + + + = "31AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.22676484888450307 + = 0 + + + + = "32AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.20193998969781299 + = 0 + + + + = "33AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.17983280759674947 + = 0 + + + + = "34AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.16014578755066544 + = 0 + + + + = "35AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.14261398469478395 + = 0 + + + + = "36AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.12700145874326854 + = 0 + + + + = "37AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.11309809874142071 + = 0 + + + + = "38AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.10071679542501406 + = 0 + + + + = "39AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.089690923132813724 + = 0 + + + + = "40AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.079872097384249927 + = 0 + + + + = "41AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.071128177944074666 + = 0 + + + + = "42AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.063341490499554454 + = 0 + + + + = "43AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.056407243017805704 + = 0 + + + + = "44AWG 10% CCA" + = 1 + = 1 + = 0 + = 0 + = 1 + = 0 + = 37.381 + = 0 + = 0 + = 0 + = 0 + = 8 + = 1 + = 1 + = 0.050232115470856625 + = 0 + + + diff --git a/release/statlib.dat b/release/statlib.dat new file mode 100644 index 0000000..f629cdf --- /dev/null +++ b/release/statlib.dat @@ -0,0 +1,182 @@ + + = "Air" + = 1 + = 1 + = 0 + + + + = "Delrin" + = 3.7 + = 3.7 + = 0 + + + + = "Ethanol" + = 25 + = 25 + = 0 + + + + = "Germanium" + = 16 + = 16 + = 0 + + + + = "Kapton 100" + = 3.9 + = 3.9 + = 0 + + + + = "Kapton 150" + = 2.9 + = 2.9 + = 0 + + + + = "Lexan" + = 2.96 + = 2.96 + = 0 + + + + = "Marble" + = 8 + = 8 + = 0 + + + + = "Mica" + = 6 + = 6 + = 0 + + + + = "Mylar" + = 3.2 + = 3.2 + = 0 + + + + = "Nylon" + = 3.8 + = 3.8 + = 0 + + + + = "Paper" + = 3 + = 3 + = 0 + + + + = "Polyamide" + = 2.5 + = 2.5 + = 0 + + + + = "Polyethylene LDPE/HDPE" + = 2.3 + = 2.3 + = 0 + + + + = "Polypropylene" + = 2.2 + = 2.2 + = 0 + + + + = "Polystyrene" + = 2.5 + = 2.5 + = 0 + + + + = "Porcelain" + = 5.9 + = 5.9 + = 0 + + + + = "PVC" + = 3 + = 3 + = 0 + + + + = "Pyrex" + = 4.7 + = 4.7 + = 0 + + + + = "Rubber" + = 3 + = 3 + = 0 + + + + = "Silicon" + = 12 + = 12 + = 0 + + + + = "Teflon" + = 2.1 + = 2.1 + = 0 + + + + = "Transformer Oil" + = 4.5 + = 4.5 + = 0 + + + + = "Vinyl" + = 3 + = 3 + = 0 + + + + = "Water@20C" + = 80.4 + = 80.4 + = 0 + + + + = "Water@50C" + = 78.5 + = 78.5 + = 0 + + diff --git a/triangle/icon1.ico b/triangle/icon1.ico new file mode 100644 index 0000000..cd6ede9 Binary files /dev/null and b/triangle/icon1.ico differ diff --git a/triangle/triangle.c b/triangle/triangle.c new file mode 100644 index 0000000..9431394 --- /dev/null +++ b/triangle/triangle.c @@ -0,0 +1,14240 @@ +/*****************************************************************************/ +/* */ +/* 888888888 ,o, / 888 */ +/* 888 88o88o " o8888o 88o8888o o88888o 888 o88888o */ +/* 888 888 888 88b 888 888 888 888 888 d888 88b */ +/* 888 888 888 o88^o888 888 888 "88888" 888 8888oo888 */ +/* 888 888 888 C888 888 888 888 / 888 q888 */ +/* 888 888 888 "88o^888 888 888 Cb 888 "88oooo" */ +/* "8oo8D */ +/* */ +/* A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator. */ +/* (triangle.c) */ +/* */ +/* Version 1.6 */ +/* July 28, 2005 */ +/* */ +/* Copyright 1993, 1995, 1997, 1998, 2002, 2005 */ +/* Jonathan Richard Shewchuk */ +/* 2360 Woolsey #H */ +/* Berkeley, California 94705-1927 */ +/* jrs@cs.berkeley.edu */ +/* */ +/* This program may be freely redistributed under the condition that the */ +/* copyright notices (including this entire header and the copyright */ +/* notice printed when the `-h' switch is selected) are not removed, and */ +/* no compensation is received. Private, research, and institutional */ +/* use is free. You may distribute modified versions of this code UNDER */ +/* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */ +/* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */ +/* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */ +/* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */ +/* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */ +/* WITH THE AUTHOR. (If you are not directly supplying this code to a */ +/* customer, and you are instead telling them how they can obtain it for */ +/* free, then you are not required to make any arrangement with me.) */ +/* */ +/* Hypertext instructions for Triangle are available on the Web at */ +/* */ +/* http://www.cs.cmu.edu/~quake/triangle.html */ +/* */ +/* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */ +/* whatsoever. This code is provided "as-is". Use at your own risk. */ +/* */ +/* Some of the references listed below are marked with an asterisk. [*] */ +/* These references are available for downloading from the Web page */ +/* */ +/* http://www.cs.cmu.edu/~quake/triangle.research.html */ +/* */ +/* Three papers discussing aspects of Triangle are available. A short */ +/* overview appears in "Triangle: Engineering a 2D Quality Mesh */ +/* Generator and Delaunay Triangulator," in Applied Computational */ +/* Geometry: Towards Geometric Engineering, Ming C. Lin and Dinesh */ +/* Manocha, editors, Lecture Notes in Computer Science volume 1148, */ +/* pages 203-222, Springer-Verlag, Berlin, May 1996 (from the First ACM */ +/* Workshop on Applied Computational Geometry). [*] */ +/* */ +/* The algorithms are discussed in the greatest detail in "Delaunay */ +/* Refinement Algorithms for Triangular Mesh Generation," Computational */ +/* Geometry: Theory and Applications 22(1-3):21-74, May 2002. [*] */ +/* */ +/* More detail about the data structures may be found in my dissertation: */ +/* "Delaunay Refinement Mesh Generation," Ph.D. thesis, Technical Report */ +/* CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */ +/* Pittsburgh, Pennsylvania, 18 May 1997. [*] */ +/* */ +/* Triangle was created as part of the Quake Project in the School of */ +/* Computer Science at Carnegie Mellon University. For further */ +/* information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F. */ +/* Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu, */ +/* "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous */ +/* Media on Parallel Computers," Computer Methods in Applied Mechanics */ +/* and Engineering 152(1-2):85-102, 22 January 1998. */ +/* */ +/* Triangle's Delaunay refinement algorithm for quality mesh generation is */ +/* a hybrid of one due to Jim Ruppert, "A Delaunay Refinement Algorithm */ +/* for Quality 2-Dimensional Mesh Generation," Journal of Algorithms */ +/* 18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */ +/* Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */ +/* Annual Symposium on Computational Geometry (San Diego, California), */ +/* pages 274-280, Association for Computing Machinery, May 1993, */ +/* http://portal.acm.org/citation.cfm?id=161150 . */ +/* */ +/* The Delaunay refinement algorithm has been modified so that it meshes */ +/* domains with small input angles well, as described in Gary L. Miller, */ +/* Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's */ +/* Algorithm Works," Twelfth International Meshing Roundtable, pages */ +/* 91-102, Sandia National Laboratories, September 2003. [*] */ +/* */ +/* My implementation of the divide-and-conquer and incremental Delaunay */ +/* triangulation algorithms follows closely the presentation of Guibas */ +/* and Stolfi, even though I use a triangle-based data structure instead */ +/* of their quad-edge data structure. (In fact, I originally implemented */ +/* Triangle using the quad-edge data structure, but the switch to a */ +/* triangle-based data structure sped Triangle by a factor of two.) The */ +/* mesh manipulation primitives and the two aforementioned Delaunay */ +/* triangulation algorithms are described by Leonidas J. Guibas and Jorge */ +/* Stolfi, "Primitives for the Manipulation of General Subdivisions and */ +/* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */ +/* 4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/ +/* */ +/* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */ +/* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */ +/* Delaunay Triangulation," International Journal of Computer and */ +/* Information Science 9(3):219-242, 1980. Triangle's improvement of the */ +/* divide-and-conquer algorithm by alternating between vertical and */ +/* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */ +/* Conquer Algorithm for Constructing Delaunay Triangulations," */ +/* Algorithmica 2(2):137-151, 1987. */ +/* */ +/* The incremental insertion algorithm was first proposed by C. L. Lawson, */ +/* "Software for C1 Surface Interpolation," in Mathematical Software III, */ +/* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */ +/* For point location, I use the algorithm of Ernst P. Mucke, Isaac */ +/* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */ +/* Preprocessing in Two- and Three-Dimensional Delaunay Triangulations," */ +/* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */ +/* ACM, May 1996. [*] If I were to randomize the order of vertex */ +/* insertion (I currently don't bother), their result combined with the */ +/* result of Kenneth L. Clarkson and Peter W. Shor, "Applications of */ +/* Random Sampling in Computational Geometry II," Discrete & */ +/* Computational Geometry 4(1):387-421, 1989, would yield an expected */ +/* O(n^{4/3}) bound on running time. */ +/* */ +/* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */ +/* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */ +/* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */ +/* boundary of the triangulation are maintained in a splay tree for the */ +/* purpose of point location. Splay trees are described by Daniel */ +/* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */ +/* Trees," Journal of the ACM 32(3):652-686, July 1985, */ +/* http://portal.acm.org/citation.cfm?id=3835 . */ +/* */ +/* The algorithms for exact computation of the signs of determinants are */ +/* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */ +/* Point Arithmetic and Fast Robust Geometric Predicates," Discrete & */ +/* Computational Geometry 18(3):305-363, October 1997. (Also available */ +/* as Technical Report CMU-CS-96-140, School of Computer Science, */ +/* Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996.) [*] */ +/* An abbreviated version appears as Jonathan Richard Shewchuk, "Robust */ +/* Adaptive Floating-Point Geometric Predicates," Proceedings of the */ +/* Twelfth Annual Symposium on Computational Geometry, ACM, May 1996. [*] */ +/* Many of the ideas for my exact arithmetic routines originate with */ +/* Douglas M. Priest, "Algorithms for Arbitrary Precision Floating Point */ +/* Arithmetic," Tenth Symposium on Computer Arithmetic, pp. 132-143, IEEE */ +/* Computer Society Press, 1991. [*] Many of the ideas for the correct */ +/* evaluation of the signs of determinants are taken from Steven Fortune */ +/* and Christopher J. Van Wyk, "Efficient Exact Arithmetic for Computa- */ +/* tional Geometry," Proceedings of the Ninth Annual Symposium on */ +/* Computational Geometry, ACM, pp. 163-172, May 1993, and from Steven */ +/* Fortune, "Numerical Stability of Algorithms for 2D Delaunay Triangu- */ +/* lations," International Journal of Computational Geometry & Applica- */ +/* tions 5(1-2):193-213, March-June 1995. */ +/* */ +/* The method of inserting new vertices off-center (not precisely at the */ +/* circumcenter of every poor-quality triangle) is from Alper Ungor, */ +/* "Off-centers: A New Type of Steiner Points for Computing Size-Optimal */ +/* Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN */ +/* 2004 (Buenos Aires, Argentina), April 2004. */ +/* */ +/* For definitions of and results involving Delaunay triangulations, */ +/* constrained and conforming versions thereof, and other aspects of */ +/* triangular mesh generation, see the excellent survey by Marshall Bern */ +/* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */ +/* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */ +/* editors, World Scientific, Singapore, pp. 23-90, 1992. [*] */ +/* */ +/* The time for incrementally adding PSLG (planar straight line graph) */ +/* segments to create a constrained Delaunay triangulation is probably */ +/* O(t^2) per segment in the worst case and O(t) per segment in the */ +/* common case, where t is the number of triangles that intersect the */ +/* segment before it is inserted. This doesn't count point location, */ +/* which can be much more expensive. I could improve this to O(d log d) */ +/* time, but d is usually quite small, so it's not worth the bother. */ +/* (This note does not apply when the -s switch is used, invoking a */ +/* different method is used to insert segments.) */ +/* */ +/* The time for deleting a vertex from a Delaunay triangulation is O(d^2) */ +/* in the worst case and O(d) in the common case, where d is the degree */ +/* of the vertex being deleted. I could improve this to O(d log d) time, */ +/* but d is usually quite small, so it's not worth the bother. */ +/* */ +/* Ruppert's Delaunay refinement algorithm typically generates triangles */ +/* at a linear rate (constant time per triangle) after the initial */ +/* triangulation is formed. There may be pathological cases where */ +/* quadratic time is required, but these never arise in practice. */ +/* */ +/* The geometric predicates (circumcenter calculations, segment */ +/* intersection formulae, etc.) appear in my "Lecture Notes on Geometric */ +/* Robustness" at http://www.cs.berkeley.edu/~jrs/mesh . */ +/* */ +/* If you make any improvements to this code, please please please let me */ +/* know, so that I may obtain the improvements. Even if you don't change */ +/* the code, I'd still love to hear what it's being used for. */ +/* */ +/*****************************************************************************/ + +/* For single precision (which will save some memory and reduce paging), */ +/* define the symbol SINGLE by using the -DSINGLE compiler switch or by */ +/* writing "#define SINGLE" below. */ +/* */ +/* For double precision (which will allow you to refine meshes to a smaller */ +/* edge length), leave SINGLE undefined. */ +/* */ +/* Double precision uses more memory, but improves the resolution of the */ +/* meshes you can generate with Triangle. It also reduces the likelihood */ +/* of a floating exception due to overflow. Finally, it is much faster */ +/* than single precision on 64-bit architectures like the DEC Alpha. I */ +/* recommend double precision unless you want to generate a mesh for which */ +/* you do not have enough memory. */ +#if defined(_WIN32) +#include +#endif +#define ANSI_DECLARATORS + +/* #define SINGLE */ + +#ifdef SINGLE +#define REAL float +#else /* not SINGLE */ +#define REAL double +#endif /* not SINGLE */ + +/* If yours is not a Unix system, define the NO_TIMER compiler switch to */ +/* remove the Unix-specific timing code. */ + +#define NO_TIMER + +/* To insert lots of self-checks for internal errors, define the SELF_CHECK */ +/* symbol. This will slow down the program significantly. It is best to */ +/* define the symbol using the -DSELF_CHECK compiler switch, but you could */ +/* write "#define SELF_CHECK" below. If you are modifying this code, I */ +/* recommend you turn self-checks on until your work is debugged. */ + +/* #define SELF_CHECK */ + +/* To compile Triangle as a callable object library (triangle.o), define the */ +/* TRILIBRARY symbol. Read the file triangle.h for details on how to call */ +/* the procedure triangulate() that results. */ + +/* #define TRILIBRARY */ + +/* It is possible to generate a smaller version of Triangle using one or */ +/* both of the following symbols. Define the REDUCED symbol to eliminate */ +/* all features that are primarily of research interest; specifically, the */ +/* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */ +/* all meshing algorithms above and beyond constrained Delaunay */ +/* triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s */ +/* switches. These reductions are most likely to be useful when */ +/* generating an object library (triangle.o) by defining the TRILIBRARY */ +/* symbol. */ + +#define REDUCED +/* #define CDT_ONLY */ + +/* On some machines, my exact arithmetic routines might be defeated by the */ +/* use of internal extended precision floating-point registers. The best */ +/* way to solve this problem is to set the floating-point registers to use */ +/* single or double precision internally. On 80x86 processors, this may */ +/* be accomplished by setting the CPU86 symbol for the Microsoft C */ +/* compiler, or the LINUX symbol for the gcc compiler running on Linux. */ +/* */ +/* An inferior solution is to declare certain values as `volatile', thus */ +/* forcing them to be stored to memory and rounded off. Unfortunately, */ +/* this solution might slow Triangle down quite a bit. To use volatile */ +/* values, write "#define INEXACT volatile" below. Normally, however, */ +/* INEXACT should be defined to be nothing. ("#define INEXACT".) */ +/* */ +/* For more discussion, see http://www.cs.cmu.edu/~quake/robust.pc.html . */ +/* For yet more discussion, see Section 5 of my paper, "Adaptive Precision */ +/* Floating-Point Arithmetic and Fast Robust Geometric Predicates" (also */ +/* available as Section 6.6 of my dissertation). */ + +/* #define CPU86 */ +/* #define LINUX */ + +#define INEXACT /* Nothing */ +/* #define INEXACT volatile */ + +/* Maximum number of characters in a file name (including the null). */ + +#define FILENAMESIZE 2048 + +/* Maximum number of characters in a line read from a file (including the */ +/* null). */ + +#define INPUTLINESIZE 1024 + +/* For efficiency, a variety of data structures are allocated in bulk. The */ +/* following constants determine how many of each structure is allocated */ +/* at once. */ + +#define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */ +#define SUBSEGPERBLOCK 508 /* Number of subsegments allocated at once. */ +#define VERTEXPERBLOCK 4092 /* Number of vertices allocated at once. */ +#define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */ +/* Number of encroached subsegments allocated at once. */ +#define BADSUBSEGPERBLOCK 252 +/* Number of skinny triangles allocated at once. */ +#define BADTRIPERBLOCK 4092 +/* Number of flipped triangles allocated at once. */ +#define FLIPSTACKERPERBLOCK 252 +/* Number of splay tree nodes allocated at once. */ +#define SPLAYNODEPERBLOCK 508 + +/* The vertex types. A DEADVERTEX has been deleted entirely. An */ +/* UNDEADVERTEX is not part of the mesh, but is written to the output */ +/* .node file and affects the node indexing in the other output files. */ + +#define INPUTVERTEX 0 +#define SEGMENTVERTEX 1 +#define FREEVERTEX 2 +#define DEADVERTEX -32768 +#define UNDEADVERTEX -32767 + +/* The next line is used to outsmart some very stupid compilers. If your */ +/* compiler is smarter, feel free to replace the "int" with "void". */ +/* Not that it matters. */ + +#define VOID int + +/* Two constants for algorithms based on random sampling. Both constants */ +/* have been chosen empirically to optimize their respective algorithms. */ + +/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */ +/* how large a random sample of triangles to inspect. */ + +#define SAMPLEFACTOR 11 + +/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */ +/* of boundary edges should be maintained in the splay tree for point */ +/* location on the front. */ + +#define SAMPLERATE 10 + +/* A number that speaks for itself, every kissable digit. */ + +#define PI 3.141592653589793238462643383279502884197169399375105820974944592308 + +/* Another fave. */ + +#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732 + +/* And here's one for those of you who are intimidated by math. */ + +#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333 + +#include +#include +#include +#include +#ifndef NO_TIMER +#include +#endif /* not NO_TIMER */ +#ifdef CPU86 +#include +#endif /* CPU86 */ +#ifdef LINUX +#include +#endif /* LINUX */ +#ifdef TRILIBRARY +#include "triangle.h" +#endif /* TRILIBRARY */ + +/* A few forward declarations. */ + +#ifndef TRILIBRARY +char *readline(); +char *findfield(); +#endif /* not TRILIBRARY */ + +/* Labels that signify the result of point location. The result of a */ +/* search indicates that the point falls in the interior of a triangle, on */ +/* an edge, on a vertex, or outside the mesh. */ + +enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE}; + +/* Labels that signify the result of vertex insertion. The result indicates */ +/* that the vertex was inserted with complete success, was inserted but */ +/* encroaches upon a subsegment, was not inserted because it lies on a */ +/* segment, or was not inserted because another vertex occupies the same */ +/* location. */ + +enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX, + DUPLICATEVERTEX}; + +/* Labels that signify the result of direction finding. The result */ +/* indicates that a segment connecting the two query points falls within */ +/* the direction triangle, along the left edge of the direction triangle, */ +/* or along the right edge of the direction triangle. */ + +enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR}; + +/*****************************************************************************/ +/* */ +/* The basic mesh data structures */ +/* */ +/* There are three: vertices, triangles, and subsegments (abbreviated */ +/* `subseg'). These three data structures, linked by pointers, comprise */ +/* the mesh. A vertex simply represents a mesh vertex and its properties. */ +/* A triangle is a triangle. A subsegment is a special data structure used */ +/* to represent an impenetrable edge of the mesh (perhaps on the outer */ +/* boundary, on the boundary of a hole, or part of an internal boundary */ +/* separating two triangulated regions). Subsegments represent boundaries, */ +/* defined by the user, that triangles may not lie across. */ +/* */ +/* A triangle consists of a list of three vertices, a list of three */ +/* adjoining triangles, a list of three adjoining subsegments (when */ +/* segments exist), an arbitrary number of optional user-defined */ +/* floating-point attributes, and an optional area constraint. The latter */ +/* is an upper bound on the permissible area of each triangle in a region, */ +/* used for mesh refinement. */ +/* */ +/* For a triangle on a boundary of the mesh, some or all of the neighboring */ +/* triangles may not be present. For a triangle in the interior of the */ +/* mesh, often no neighboring subsegments are present. Such absent */ +/* triangles and subsegments are never represented by NULL pointers; they */ +/* are represented by two special records: `dummytri', the triangle that */ +/* fills "outer space", and `dummysub', the omnipresent subsegment. */ +/* `dummytri' and `dummysub' are used for several reasons; for instance, */ +/* they can be dereferenced and their contents examined without violating */ +/* protected memory. */ +/* */ +/* However, it is important to understand that a triangle includes other */ +/* information as well. The pointers to adjoining vertices, triangles, and */ +/* subsegments are ordered in a way that indicates their geometric relation */ +/* to each other. Furthermore, each of these pointers contains orientation */ +/* information. Each pointer to an adjoining triangle indicates which face */ +/* of that triangle is contacted. Similarly, each pointer to an adjoining */ +/* subsegment indicates which side of that subsegment is contacted, and how */ +/* the subsegment is oriented relative to the triangle. */ +/* */ +/* The data structure representing a subsegment may be thought to be */ +/* abutting the edge of one or two triangle data structures: either */ +/* sandwiched between two triangles, or resting against one triangle on an */ +/* exterior boundary or hole boundary. */ +/* */ +/* A subsegment consists of a list of four vertices--the vertices of the */ +/* subsegment, and the vertices of the segment it is a part of--a list of */ +/* two adjoining subsegments, and a list of two adjoining triangles. One */ +/* of the two adjoining triangles may not be present (though there should */ +/* always be one), and neighboring subsegments might not be present. */ +/* Subsegments also store a user-defined integer "boundary marker". */ +/* Typically, this integer is used to indicate what boundary conditions are */ +/* to be applied at that location in a finite element simulation. */ +/* */ +/* Like triangles, subsegments maintain information about the relative */ +/* orientation of neighboring objects. */ +/* */ +/* Vertices are relatively simple. A vertex is a list of floating-point */ +/* numbers, starting with the x, and y coordinates, followed by an */ +/* arbitrary number of optional user-defined floating-point attributes, */ +/* followed by an integer boundary marker. During the segment insertion */ +/* phase, there is also a pointer from each vertex to a triangle that may */ +/* contain it. Each pointer is not always correct, but when one is, it */ +/* speeds up segment insertion. These pointers are assigned values once */ +/* at the beginning of the segment insertion phase, and are not used or */ +/* updated except during this phase. Edge flipping during segment */ +/* insertion will render some of them incorrect. Hence, don't rely upon */ +/* them for anything. */ +/* */ +/* Other than the exception mentioned above, vertices have no information */ +/* about what triangles, subfacets, or subsegments they are linked to. */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* Handles */ +/* */ +/* The oriented triangle (`otri') and oriented subsegment (`osub') data */ +/* structures defined below do not themselves store any part of the mesh. */ +/* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */ +/* */ +/* Oriented triangles and oriented subsegments will usually be referred to */ +/* as "handles." A handle is essentially a pointer into the mesh; it */ +/* allows you to "hold" one particular part of the mesh. Handles are used */ +/* to specify the regions in which one is traversing and modifying the mesh.*/ +/* A single `triangle' may be held by many handles, or none at all. (The */ +/* latter case is not a memory leak, because the triangle is still */ +/* connected to other triangles in the mesh.) */ +/* */ +/* An `otri' is a handle that holds a triangle. It holds a specific edge */ +/* of the triangle. An `osub' is a handle that holds a subsegment. It */ +/* holds either the left or right side of the subsegment. */ +/* */ +/* Navigation about the mesh is accomplished through a set of mesh */ +/* manipulation primitives, further below. Many of these primitives take */ +/* a handle and produce a new handle that holds the mesh near the first */ +/* handle. Other primitives take two handles and glue the corresponding */ +/* parts of the mesh together. The orientation of the handles is */ +/* important. For instance, when two triangles are glued together by the */ +/* bond() primitive, they are glued at the edges on which the handles lie. */ +/* */ +/* Because vertices have no information about which triangles they are */ +/* attached to, I commonly represent a vertex by use of a handle whose */ +/* origin is the vertex. A single handle can simultaneously represent a */ +/* triangle, an edge, and a vertex. */ +/* */ +/*****************************************************************************/ + +/* The triangle data structure. Each triangle contains three pointers to */ +/* adjoining triangles, plus three pointers to vertices, plus three */ +/* pointers to subsegments (declared below; these pointers are usually */ +/* `dummysub'). It may or may not also contain user-defined attributes */ +/* and/or a floating-point "area constraint." It may also contain extra */ +/* pointers for nodes, when the user asks for high-order elements. */ +/* Because the size and structure of a `triangle' is not decided until */ +/* runtime, I haven't simply declared the type `triangle' as a struct. */ + +typedef REAL **triangle; /* Really: typedef triangle *triangle */ + +/* An oriented triangle: includes a pointer to a triangle and orientation. */ +/* The orientation denotes an edge of the triangle. Hence, there are */ +/* three possible orientations. By convention, each edge always points */ +/* counterclockwise about the corresponding triangle. */ + +struct otri { + triangle *tri; + int orient; /* Ranges from 0 to 2. */ +}; + +/* The subsegment data structure. Each subsegment contains two pointers to */ +/* adjoining subsegments, plus four pointers to vertices, plus two */ +/* pointers to adjoining triangles, plus one boundary marker, plus one */ +/* segment number. */ + +typedef REAL **subseg; /* Really: typedef subseg *subseg */ + +/* An oriented subsegment: includes a pointer to a subsegment and an */ +/* orientation. The orientation denotes a side of the edge. Hence, there */ +/* are two possible orientations. By convention, the edge is always */ +/* directed so that the "side" denoted is the right side of the edge. */ + +struct osub { + subseg *ss; + int ssorient; /* Ranges from 0 to 1. */ +}; + +/* The vertex data structure. Each vertex is actually an array of REALs. */ +/* The number of REALs is unknown until runtime. An integer boundary */ +/* marker, and sometimes a pointer to a triangle, is appended after the */ +/* REALs. */ + +typedef REAL *vertex; + +/* A queue used to store encroached subsegments. Each subsegment's vertices */ +/* are stored so that we can check whether a subsegment is still the same. */ + +struct badsubseg { + subseg encsubseg; /* An encroached subsegment. */ + vertex subsegorg, subsegdest; /* Its two vertices. */ +}; + +/* A queue used to store bad triangles. The key is the square of the cosine */ +/* of the smallest angle of the triangle. Each triangle's vertices are */ +/* stored so that one can check whether a triangle is still the same. */ + +struct badtriang { + triangle poortri; /* A skinny or too-large triangle. */ + REAL key; /* cos^2 of smallest (apical) angle. */ + vertex triangorg, triangdest, triangapex; /* Its three vertices. */ + struct badtriang *nexttriang; /* Pointer to next bad triangle. */ +}; + +/* A stack of triangles flipped during the most recent vertex insertion. */ +/* The stack is used to undo the vertex insertion if the vertex encroaches */ +/* upon a subsegment. */ + +struct flipstacker { + triangle flippedtri; /* A recently flipped triangle. */ + struct flipstacker *prevflip; /* Previous flip in the stack. */ +}; + +/* A node in a heap used to store events for the sweepline Delaunay */ +/* algorithm. Nodes do not point directly to their parents or children in */ +/* the heap. Instead, each node knows its position in the heap, and can */ +/* look up its parent and children in a separate array. The `eventptr' */ +/* points either to a `vertex' or to a triangle (in encoded format, so */ +/* that an orientation is included). In the latter case, the origin of */ +/* the oriented triangle is the apex of a "circle event" of the sweepline */ +/* algorithm. To distinguish site events from circle events, all circle */ +/* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */ + +struct event { + REAL xkey, ykey; /* Coordinates of the event. */ + VOID *eventptr; /* Can be a vertex or the location of a circle event. */ + int heapposition; /* Marks this event's position in the heap. */ +}; + +/* A node in the splay tree. Each node holds an oriented ghost triangle */ +/* that represents a boundary edge of the growing triangulation. When a */ +/* circle event covers two boundary edges with a triangle, so that they */ +/* are no longer boundary edges, those edges are not immediately deleted */ +/* from the tree; rather, they are lazily deleted when they are next */ +/* encountered. (Since only a random sample of boundary edges are kept */ +/* in the tree, lazy deletion is faster.) `keydest' is used to verify */ +/* that a triangle is still the same as when it entered the splay tree; if */ +/* it has been rotated (due to a circle event), it no longer represents a */ +/* boundary edge and should be deleted. */ + +struct splaynode { + struct otri keyedge; /* Lprev of an edge on the front. */ + vertex keydest; /* Used to verify that splay node is still live. */ + struct splaynode *lchild, *rchild; /* Children in splay tree. */ +}; + +/* A type used to allocate memory. firstblock is the first block of items. */ +/* nowblock is the block from which items are currently being allocated. */ +/* nextitem points to the next slab of free memory for an item. */ +/* deaditemstack is the head of a linked list (stack) of deallocated items */ +/* that can be recycled. unallocateditems is the number of items that */ +/* remain to be allocated from nowblock. */ +/* */ +/* Traversal is the process of walking through the entire list of items, and */ +/* is separate from allocation. Note that a traversal will visit items on */ +/* the "deaditemstack" stack as well as live items. pathblock points to */ +/* the block currently being traversed. pathitem points to the next item */ +/* to be traversed. pathitemsleft is the number of items that remain to */ +/* be traversed in pathblock. */ +/* */ +/* alignbytes determines how new records should be aligned in memory. */ +/* itembytes is the length of a record in bytes (after rounding up). */ +/* itemsperblock is the number of items allocated at once in a single */ +/* block. itemsfirstblock is the number of items in the first block, */ +/* which can vary from the others. items is the number of currently */ +/* allocated items. maxitems is the maximum number of items that have */ +/* been allocated at once; it is the current number of items plus the */ +/* number of records kept on deaditemstack. */ + +struct memorypool { + VOID **firstblock, **nowblock; + VOID *nextitem; + VOID *deaditemstack; + VOID **pathblock; + VOID *pathitem; + int alignbytes; + int itembytes; + int itemsperblock; + int itemsfirstblock; + long items, maxitems; + int unallocateditems; + int pathitemsleft; +}; + + +/* Global constants. */ + +REAL splitter; /* Used to split REAL factors for exact multiplication. */ +REAL epsilon; /* Floating-point machine epsilon. */ +REAL resulterrbound; +REAL ccwerrboundA, ccwerrboundB, ccwerrboundC; +REAL iccerrboundA, iccerrboundB, iccerrboundC; +REAL o3derrboundA, o3derrboundB, o3derrboundC; + +/* Random number seed is not constant, but I've made it global anyway. */ + +unsigned long randomseed; /* Current random number seed. */ + + +/* Mesh data structure. Triangle operates on only one mesh, but the mesh */ +/* structure is used (instead of global variables) to allow reentrancy. */ + +struct mesh { + +/* Variables used to allocate memory for triangles, subsegments, vertices, */ +/* viri (triangles being eaten), encroached segments, bad (skinny or too */ +/* large) triangles, and splay tree nodes. */ + + struct memorypool triangles; + struct memorypool subsegs; + struct memorypool vertices; + struct memorypool viri; + struct memorypool badsubsegs; + struct memorypool badtriangles; + struct memorypool flipstackers; + struct memorypool splaynodes; + +/* Variables that maintain the bad triangle queues. The queues are */ +/* ordered from 4095 (highest priority) to 0 (lowest priority). */ + + struct badtriang *queuefront[4096]; + struct badtriang *queuetail[4096]; + int nextnonemptyq[4096]; + int firstnonemptyq; + +/* Variable that maintains the stack of recently flipped triangles. */ + + struct flipstacker *lastflip; + +/* Other variables. */ + + REAL xmin, xmax, ymin, ymax; /* x and y bounds. */ + REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */ + int invertices; /* Number of input vertices. */ + int inelements; /* Number of input triangles. */ + int insegments; /* Number of input segments. */ + int holes; /* Number of input holes. */ + int regions; /* Number of input regions. */ + int undeads; /* Number of input vertices that don't appear in the mesh. */ + long edges; /* Number of output edges. */ + int mesh_dim; /* Dimension (ought to be 2). */ + int nextras; /* Number of attributes per vertex. */ + int eextras; /* Number of attributes per triangle. */ + long hullsize; /* Number of edges in convex hull. */ + int steinerleft; /* Number of Steiner points not yet used. */ + int vertexmarkindex; /* Index to find boundary marker of a vertex. */ + int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */ + int highorderindex; /* Index to find extra nodes for high-order elements. */ + int elemattribindex; /* Index to find attributes of a triangle. */ + int areaboundindex; /* Index to find area bound of a triangle. */ + int checksegments; /* Are there segments in the triangulation yet? */ + int checkquality; /* Has quality triangulation begun yet? */ + int readnodefile; /* Has a .node file been read? */ + long samples; /* Number of random samples for point location. */ + + long incirclecount; /* Number of incircle tests performed. */ + long counterclockcount; /* Number of counterclockwise tests performed. */ + long orient3dcount; /* Number of 3D orientation tests performed. */ + long hyperbolacount; /* Number of right-of-hyperbola tests performed. */ + long circumcentercount; /* Number of circumcenter calculations performed. */ + long circletopcount; /* Number of circle top calculations performed. */ + +/* Triangular bounding box vertices. */ + + vertex infvertex1, infvertex2, infvertex3; + +/* Pointer to the `triangle' that occupies all of "outer space." */ + + triangle *dummytri; + triangle *dummytribase; /* Keep base address so we can free() it later. */ + +/* Pointer to the omnipresent subsegment. Referenced by any triangle or */ +/* subsegment that isn't really connected to a subsegment at that */ +/* location. */ + + subseg *dummysub; + subseg *dummysubbase; /* Keep base address so we can free() it later. */ + +/* Pointer to a recently visited triangle. Improves point location if */ +/* proximate vertices are inserted sequentially. */ + + struct otri recenttri; + +}; /* End of `struct mesh'. */ + + +/* Data structure for command line switches and file names. This structure */ +/* is used (instead of global variables) to allow reentrancy. */ + +struct behavior { + +/* Switches for the triangulator. */ +/* poly: -p switch. refine: -r switch. */ +/* quality: -q switch. */ +/* minangle: minimum angle bound, specified after -q switch. */ +/* goodangle: cosine squared of minangle. */ +/* offconstant: constant used to place off-center Steiner points. */ +/* vararea: -a switch without number. */ +/* fixedarea: -a switch with number. */ +/* maxarea: maximum area bound, specified after -a switch. */ +/* usertest: -u switch. */ +/* regionattrib: -A switch. convex: -c switch. */ +/* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */ +/* firstnumber: inverse of -z switch. All items are numbered starting */ +/* from `firstnumber'. */ +/* edgesout: -e switch. voronoi: -v switch. */ +/* neighbors: -n switch. geomview: -g switch. */ +/* nobound: -B switch. nopolywritten: -P switch. */ +/* nonodewritten: -N switch. noelewritten: -E switch. */ +/* noiterationnum: -I switch. noholes: -O switch. */ +/* noexact: -X switch. */ +/* order: element order, specified after -o switch. */ +/* nobisect: count of how often -Y switch is selected. */ +/* steiner: maximum number of Steiner points, specified after -S switch. */ +/* incremental: -i switch. sweepline: -F switch. */ +/* dwyer: inverse of -l switch. */ +/* splitseg: -s switch. */ +/* conformdel: -D switch. docheck: -C switch. */ +/* quiet: -Q switch. verbose: count of how often -V switch is selected. */ +/* usesegments: -p, -r, -q, or -c switch; determines whether segments are */ +/* used at all. */ +/* */ +/* Read the instructions to find out the meaning of these switches. */ + + int poly, refine, quality, vararea, fixedarea, usertest; + int regionattrib, convex, weighted, jettison; + int firstnumber; + int edgesout, voronoi, neighbors, geomview; + int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum; + int noholes, noexact, conformdel; + int incremental, sweepline, dwyer; + int splitseg; + int docheck; + int quiet, verbose; + int usesegments; + int order; + int nobisect; + int steiner; + REAL minangle, goodangle, offconstant; + REAL maxarea; + +/* Variables for file names. */ + +#ifndef TRILIBRARY + char innodefilename[FILENAMESIZE]; + char inelefilename[FILENAMESIZE]; + char inpolyfilename[FILENAMESIZE]; + char areafilename[FILENAMESIZE]; + char outnodefilename[FILENAMESIZE]; + char outelefilename[FILENAMESIZE]; + char outpolyfilename[FILENAMESIZE]; + char edgefilename[FILENAMESIZE]; + char vnodefilename[FILENAMESIZE]; + char vedgefilename[FILENAMESIZE]; + char neighborfilename[FILENAMESIZE]; + char offfilename[FILENAMESIZE]; +#endif /* not TRILIBRARY */ + +}; /* End of `struct behavior'. */ + + +/*****************************************************************************/ +/* */ +/* Mesh manipulation primitives. Each triangle contains three pointers to */ +/* other triangles, with orientations. Each pointer points not to the */ +/* first byte of a triangle, but to one of the first three bytes of a */ +/* triangle. It is necessary to extract both the triangle itself and the */ +/* orientation. To save memory, I keep both pieces of information in one */ +/* pointer. To make this possible, I assume that all triangles are aligned */ +/* to four-byte boundaries. The decode() routine below decodes a pointer, */ +/* extracting an orientation (in the range 0 to 2) and a pointer to the */ +/* beginning of a triangle. The encode() routine compresses a pointer to a */ +/* triangle and an orientation into a single pointer. My assumptions that */ +/* triangles are four-byte-aligned and that the `unsigned long' type is */ +/* long enough to hold a pointer are two of the few kludges in this program.*/ +/* */ +/* Subsegments are manipulated similarly. A pointer to a subsegment */ +/* carries both an address and an orientation in the range 0 to 1. */ +/* */ +/* The other primitives take an oriented triangle or oriented subsegment, */ +/* and return an oriented triangle or oriented subsegment or vertex; or */ +/* they change the connections in the data structure. */ +/* */ +/* Below, triangles and subsegments are denoted by their vertices. The */ +/* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */ +/* c. These vertices occur in counterclockwise order about the triangle. */ +/* The handle abc may simultaneously denote vertex a, edge ab, and triangle */ +/* abc. */ +/* */ +/* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */ +/* b. If ab is thought to be directed upward (with b directly above a), */ +/* then the handle ab is thought to grasp the right side of ab, and may */ +/* simultaneously denote vertex a and edge ab. */ +/* */ +/* An asterisk (*) denotes a vertex whose identity is unknown. */ +/* */ +/* Given this notation, a partial list of mesh manipulation primitives */ +/* follows. */ +/* */ +/* */ +/* For triangles: */ +/* */ +/* sym: Find the abutting triangle; same edge. */ +/* sym(abc) -> ba* */ +/* */ +/* lnext: Find the next edge (counterclockwise) of a triangle. */ +/* lnext(abc) -> bca */ +/* */ +/* lprev: Find the previous edge (clockwise) of a triangle. */ +/* lprev(abc) -> cab */ +/* */ +/* onext: Find the next edge counterclockwise with the same origin. */ +/* onext(abc) -> ac* */ +/* */ +/* oprev: Find the next edge clockwise with the same origin. */ +/* oprev(abc) -> a*b */ +/* */ +/* dnext: Find the next edge counterclockwise with the same destination. */ +/* dnext(abc) -> *ba */ +/* */ +/* dprev: Find the next edge clockwise with the same destination. */ +/* dprev(abc) -> cb* */ +/* */ +/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */ +/* rnext(abc) -> *a* */ +/* */ +/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */ +/* rprev(abc) -> b** */ +/* */ +/* org: Origin dest: Destination apex: Apex */ +/* org(abc) -> a dest(abc) -> b apex(abc) -> c */ +/* */ +/* bond: Bond two triangles together at the resepective handles. */ +/* bond(abc, bad) */ +/* */ +/* */ +/* For subsegments: */ +/* */ +/* ssym: Reverse the orientation of a subsegment. */ +/* ssym(ab) -> ba */ +/* */ +/* spivot: Find adjoining subsegment with the same origin. */ +/* spivot(ab) -> a* */ +/* */ +/* snext: Find next subsegment in sequence. */ +/* snext(ab) -> b* */ +/* */ +/* sorg: Origin sdest: Destination */ +/* sorg(ab) -> a sdest(ab) -> b */ +/* */ +/* sbond: Bond two subsegments together at the respective origins. */ +/* sbond(ab, ac) */ +/* */ +/* */ +/* For interacting tetrahedra and subfacets: */ +/* */ +/* tspivot: Find a subsegment abutting a triangle. */ +/* tspivot(abc) -> ba */ +/* */ +/* stpivot: Find a triangle abutting a subsegment. */ +/* stpivot(ab) -> ba* */ +/* */ +/* tsbond: Bond a triangle to a subsegment. */ +/* tsbond(abc, ba) */ +/* */ +/*****************************************************************************/ + +/********* Mesh manipulation primitives begin here *********/ +/** **/ +/** **/ + +/* Fast lookup arrays to speed some of the mesh manipulation primitives. */ + +int plus1mod3[3] = {1, 2, 0}; +int minus1mod3[3] = {2, 0, 1}; + +/********* Primitives for triangles *********/ +/* */ +/* */ + +/* decode() converts a pointer to an oriented triangle. The orientation is */ +/* extracted from the two least significant bits of the pointer. */ + +#define decode(ptr, otri) \ + (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \ + (otri).tri = (triangle *) \ + ((unsigned long) (ptr) ^ (unsigned long) (otri).orient) + +/* encode() compresses an oriented triangle into a single pointer. It */ +/* relies on the assumption that all triangles are aligned to four-byte */ +/* boundaries, so the two least significant bits of (otri).tri are zero. */ + +#define encode(otri) \ + (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient) + +/* The following handle manipulation primitives are all described by Guibas */ +/* and Stolfi. However, Guibas and Stolfi use an edge-based data */ +/* structure, whereas I use a triangle-based data structure. */ + +/* sym() finds the abutting triangle, on the same edge. Note that the edge */ +/* direction is necessarily reversed, because the handle specified by an */ +/* oriented triangle is directed counterclockwise around the triangle. */ + +#define sym(otri1, otri2) \ + ptr = (otri1).tri[(otri1).orient]; \ + decode(ptr, otri2); + +#define symself(otri) \ + ptr = (otri).tri[(otri).orient]; \ + decode(ptr, otri); + +/* lnext() finds the next edge (counterclockwise) of a triangle. */ + +#define lnext(otri1, otri2) \ + (otri2).tri = (otri1).tri; \ + (otri2).orient = plus1mod3[(otri1).orient] + +#define lnextself(otri) \ + (otri).orient = plus1mod3[(otri).orient] + +/* lprev() finds the previous edge (clockwise) of a triangle. */ + +#define lprev(otri1, otri2) \ + (otri2).tri = (otri1).tri; \ + (otri2).orient = minus1mod3[(otri1).orient] + +#define lprevself(otri) \ + (otri).orient = minus1mod3[(otri).orient] + +/* onext() spins counterclockwise around a vertex; that is, it finds the */ +/* next edge with the same origin in the counterclockwise direction. This */ +/* edge is part of a different triangle. */ + +#define onext(otri1, otri2) \ + lprev(otri1, otri2); \ + symself(otri2); + +#define onextself(otri) \ + lprevself(otri); \ + symself(otri); + +/* oprev() spins clockwise around a vertex; that is, it finds the next edge */ +/* with the same origin in the clockwise direction. This edge is part of */ +/* a different triangle. */ + +#define oprev(otri1, otri2) \ + sym(otri1, otri2); \ + lnextself(otri2); + +#define oprevself(otri) \ + symself(otri); \ + lnextself(otri); + +/* dnext() spins counterclockwise around a vertex; that is, it finds the */ +/* next edge with the same destination in the counterclockwise direction. */ +/* This edge is part of a different triangle. */ + +#define dnext(otri1, otri2) \ + sym(otri1, otri2); \ + lprevself(otri2); + +#define dnextself(otri) \ + symself(otri); \ + lprevself(otri); + +/* dprev() spins clockwise around a vertex; that is, it finds the next edge */ +/* with the same destination in the clockwise direction. This edge is */ +/* part of a different triangle. */ + +#define dprev(otri1, otri2) \ + lnext(otri1, otri2); \ + symself(otri2); + +#define dprevself(otri) \ + lnextself(otri); \ + symself(otri); + +/* rnext() moves one edge counterclockwise about the adjacent triangle. */ +/* (It's best understood by reading Guibas and Stolfi. It involves */ +/* changing triangles twice.) */ + +#define rnext(otri1, otri2) \ + sym(otri1, otri2); \ + lnextself(otri2); \ + symself(otri2); + +#define rnextself(otri) \ + symself(otri); \ + lnextself(otri); \ + symself(otri); + +/* rprev() moves one edge clockwise about the adjacent triangle. */ +/* (It's best understood by reading Guibas and Stolfi. It involves */ +/* changing triangles twice.) */ + +#define rprev(otri1, otri2) \ + sym(otri1, otri2); \ + lprevself(otri2); \ + symself(otri2); + +#define rprevself(otri) \ + symself(otri); \ + lprevself(otri); \ + symself(otri); + +/* These primitives determine or set the origin, destination, or apex of a */ +/* triangle. */ + +#define org(otri, vertexptr) \ + vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3] + +#define dest(otri, vertexptr) \ + vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3] + +#define apex(otri, vertexptr) \ + vertexptr = (vertex) (otri).tri[(otri).orient + 3] + +#define setorg(otri, vertexptr) \ + (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr + +#define setdest(otri, vertexptr) \ + (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr + +#define setapex(otri, vertexptr) \ + (otri).tri[(otri).orient + 3] = (triangle) vertexptr + +/* Bond two triangles together. */ + +#define bond(otri1, otri2) \ + (otri1).tri[(otri1).orient] = encode(otri2); \ + (otri2).tri[(otri2).orient] = encode(otri1) + +/* Dissolve a bond (from one side). Note that the other triangle will still */ +/* think it's connected to this triangle. Usually, however, the other */ +/* triangle is being deleted entirely, or bonded to another triangle, so */ +/* it doesn't matter. */ + +#define dissolve(otri) \ + (otri).tri[(otri).orient] = (triangle) m->dummytri + +/* Copy an oriented triangle. */ + +#define otricopy(otri1, otri2) \ + (otri2).tri = (otri1).tri; \ + (otri2).orient = (otri1).orient + +/* Test for equality of oriented triangles. */ + +#define otriequal(otri1, otri2) \ + (((otri1).tri == (otri2).tri) && \ + ((otri1).orient == (otri2).orient)) + +/* Primitives to infect or cure a triangle with the virus. These rely on */ +/* the assumption that all subsegments are aligned to four-byte boundaries.*/ + +#define infect(otri) \ + (otri).tri[6] = (triangle) \ + ((unsigned long) (otri).tri[6] | (unsigned long) 2l) + +#define uninfect(otri) \ + (otri).tri[6] = (triangle) \ + ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l) + +/* Test a triangle for viral infection. */ + +#define infected(otri) \ + (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l) + +/* Check or set a triangle's attributes. */ + +#define elemattribute(otri, attnum) \ + ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] + +#define setelemattribute(otri, attnum, value) \ + ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value + +/* Check or set a triangle's maximum area bound. */ + +#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex] + +#define setareabound(otri, value) \ + ((REAL *) (otri).tri)[m->areaboundindex] = value + +/* Check or set a triangle's deallocation. Its second pointer is set to */ +/* NULL to indicate that it is not allocated. (Its first pointer is used */ +/* for the stack of dead items.) Its fourth pointer (its first vertex) */ +/* is set to NULL in case a `badtriang' structure points to it. */ + +#define deadtri(tria) ((tria)[1] == (triangle) NULL) + +#define killtri(tria) \ + (tria)[1] = (triangle) NULL; \ + (tria)[3] = (triangle) NULL + +/********* Primitives for subsegments *********/ +/* */ +/* */ + +/* sdecode() converts a pointer to an oriented subsegment. The orientation */ +/* is extracted from the least significant bit of the pointer. The two */ +/* least significant bits (one for orientation, one for viral infection) */ +/* are masked out to produce the real pointer. */ + +#define sdecode(sptr, osub) \ + (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \ + (osub).ss = (subseg *) \ + ((unsigned long) (sptr) & ~ (unsigned long) 3l) + +/* sencode() compresses an oriented subsegment into a single pointer. It */ +/* relies on the assumption that all subsegments are aligned to two-byte */ +/* boundaries, so the least significant bit of (osub).ss is zero. */ + +#define sencode(osub) \ + (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient) + +/* ssym() toggles the orientation of a subsegment. */ + +#define ssym(osub1, osub2) \ + (osub2).ss = (osub1).ss; \ + (osub2).ssorient = 1 - (osub1).ssorient + +#define ssymself(osub) \ + (osub).ssorient = 1 - (osub).ssorient + +/* spivot() finds the other subsegment (from the same segment) that shares */ +/* the same origin. */ + +#define spivot(osub1, osub2) \ + sptr = (osub1).ss[(osub1).ssorient]; \ + sdecode(sptr, osub2) + +#define spivotself(osub) \ + sptr = (osub).ss[(osub).ssorient]; \ + sdecode(sptr, osub) + +/* snext() finds the next subsegment (from the same segment) in sequence; */ +/* one whose origin is the input subsegment's destination. */ + +#define snext(osub1, osub2) \ + sptr = (osub1).ss[1 - (osub1).ssorient]; \ + sdecode(sptr, osub2) + +#define snextself(osub) \ + sptr = (osub).ss[1 - (osub).ssorient]; \ + sdecode(sptr, osub) + +/* These primitives determine or set the origin or destination of a */ +/* subsegment or the segment that includes it. */ + +#define sorg(osub, vertexptr) \ + vertexptr = (vertex) (osub).ss[2 + (osub).ssorient] + +#define sdest(osub, vertexptr) \ + vertexptr = (vertex) (osub).ss[3 - (osub).ssorient] + +#define setsorg(osub, vertexptr) \ + (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr + +#define setsdest(osub, vertexptr) \ + (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr + +#define segorg(osub, vertexptr) \ + vertexptr = (vertex) (osub).ss[4 + (osub).ssorient] + +#define segdest(osub, vertexptr) \ + vertexptr = (vertex) (osub).ss[5 - (osub).ssorient] + +#define setsegorg(osub, vertexptr) \ + (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr + +#define setsegdest(osub, vertexptr) \ + (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr + +/* These primitives read or set a boundary marker. Boundary markers are */ +/* used to hold user-defined tags for setting boundary conditions in */ +/* finite element solvers. */ + +#define mark(osub) (* (int *) ((osub).ss + 8)) + +#define setmark(osub, value) \ + * (int *) ((osub).ss + 8) = value + +/* Bond two subsegments together. */ + +#define sbond(osub1, osub2) \ + (osub1).ss[(osub1).ssorient] = sencode(osub2); \ + (osub2).ss[(osub2).ssorient] = sencode(osub1) + +/* Dissolve a subsegment bond (from one side). Note that the other */ +/* subsegment will still think it's connected to this subsegment. */ + +#define sdissolve(osub) \ + (osub).ss[(osub).ssorient] = (subseg) m->dummysub + +/* Copy a subsegment. */ + +#define subsegcopy(osub1, osub2) \ + (osub2).ss = (osub1).ss; \ + (osub2).ssorient = (osub1).ssorient + +/* Test for equality of subsegments. */ + +#define subsegequal(osub1, osub2) \ + (((osub1).ss == (osub2).ss) && \ + ((osub1).ssorient == (osub2).ssorient)) + +/* Check or set a subsegment's deallocation. Its second pointer is set to */ +/* NULL to indicate that it is not allocated. (Its first pointer is used */ +/* for the stack of dead items.) Its third pointer (its first vertex) */ +/* is set to NULL in case a `badsubseg' structure points to it. */ + +#define deadsubseg(sub) ((sub)[1] == (subseg) NULL) + +#define killsubseg(sub) \ + (sub)[1] = (subseg) NULL; \ + (sub)[2] = (subseg) NULL + +/********* Primitives for interacting triangles and subsegments *********/ +/* */ +/* */ + +/* tspivot() finds a subsegment abutting a triangle. */ + +#define tspivot(otri, osub) \ + sptr = (subseg) (otri).tri[6 + (otri).orient]; \ + sdecode(sptr, osub) + +/* stpivot() finds a triangle abutting a subsegment. It requires that the */ +/* variable `ptr' of type `triangle' be defined. */ + +#define stpivot(osub, otri) \ + ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \ + decode(ptr, otri) + +/* Bond a triangle to a subsegment. */ + +#define tsbond(otri, osub) \ + (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \ + (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri) + +/* Dissolve a bond (from the triangle side). */ + +#define tsdissolve(otri) \ + (otri).tri[6 + (otri).orient] = (triangle) m->dummysub + +/* Dissolve a bond (from the subsegment side). */ + +#define stdissolve(osub) \ + (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri + +/********* Primitives for vertices *********/ +/* */ +/* */ + +#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex] + +#define setvertexmark(vx, value) \ + ((int *) (vx))[m->vertexmarkindex] = value + +#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1] + +#define setvertextype(vx, value) \ + ((int *) (vx))[m->vertexmarkindex + 1] = value + +#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex] + +#define setvertex2tri(vx, value) \ + ((triangle *) (vx))[m->vertex2triindex] = value + +/** **/ +/** **/ +/********* Mesh manipulation primitives end here *********/ + +/********* User-defined triangle evaluation routine begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* triunsuitable() Determine if a triangle is unsuitable, and thus must */ +/* be further refined. */ +/* */ +/* You may write your own procedure that decides whether or not a selected */ +/* triangle is too big (and needs to be refined). There are two ways to do */ +/* this. */ +/* */ +/* (1) Modify the procedure `triunsuitable' below, then recompile */ +/* Triangle. */ +/* */ +/* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */ +/* to this file, or by using the appropriate compiler switch). This way, */ +/* you can compile triangle.c separately from your test. Write your own */ +/* `triunsuitable' procedure in a separate C file (using the same prototype */ +/* as below). Compile it and link the object code with triangle.o. */ +/* */ +/* This procedure returns 1 if the triangle is too large and should be */ +/* refined; 0 otherwise. */ +/* */ +/*****************************************************************************/ + +#ifdef EXTERNAL_TEST + +int triunsuitable(); + +#else /* not EXTERNAL_TEST */ + +#ifdef ANSI_DECLARATORS +int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area) +#else /* not ANSI_DECLARATORS */ +int triunsuitable(triorg, tridest, triapex, area) +vertex triorg; /* The triangle's origin vertex. */ +vertex tridest; /* The triangle's destination vertex. */ +vertex triapex; /* The triangle's apex vertex. */ +REAL area; /* The area of the triangle. */ +#endif /* not ANSI_DECLARATORS */ + +{ + REAL dxoa, dxda, dxod; + REAL dyoa, dyda, dyod; + REAL oalen, dalen, odlen; + REAL maxlen; + + dxoa = triorg[0] - triapex[0]; + dyoa = triorg[1] - triapex[1]; + dxda = tridest[0] - triapex[0]; + dyda = tridest[1] - triapex[1]; + dxod = triorg[0] - tridest[0]; + dyod = triorg[1] - tridest[1]; + /* Find the squares of the lengths of the triangle's three edges. */ + oalen = dxoa * dxoa + dyoa * dyoa; + dalen = dxda * dxda + dyda * dyda; + odlen = dxod * dxod + dyod * dyod; + /* Find the square of the length of the longest edge. */ + maxlen = (dalen > oalen) ? dalen : oalen; + maxlen = (odlen > maxlen) ? odlen : maxlen; + + if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) { + return 1; + } else { + return 0; + } +} + +#endif /* not EXTERNAL_TEST */ + +/** **/ +/** **/ +/********* User-defined triangle evaluation routine ends here *********/ + +/********* Memory allocation and program exit wrappers begin here *********/ +/** **/ +/** **/ + +#ifdef ANSI_DECLARATORS +void triexit(int status) +#else /* not ANSI_DECLARATORS */ +void triexit(status) +int status; +#endif /* not ANSI_DECLARATORS */ + +{ + exit(status); +} + +#ifdef ANSI_DECLARATORS +VOID *trimalloc(int size) +#else /* not ANSI_DECLARATORS */ +VOID *trimalloc(size) +int size; +#endif /* not ANSI_DECLARATORS */ + +{ + VOID *memptr; + + memptr = (VOID *) malloc((unsigned int) size); + if (memptr == (VOID *) NULL) { + printf("Error: Out of memory.\n"); + triexit(1); + } + return(memptr); +} + +#ifdef ANSI_DECLARATORS +void trifree(VOID *memptr) +#else /* not ANSI_DECLARATORS */ +void trifree(memptr) +VOID *memptr; +#endif /* not ANSI_DECLARATORS */ + +{ + free(memptr); +} + +/** **/ +/** **/ +/********* Memory allocation and program exit wrappers end here *********/ + +/********* User interaction routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* syntax() Print list of command line switches. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +void syntax() +{ + ShellExecute(NULL, "open", "https://www.cs.cmu.edu/~quake/triangle.switch.html", NULL, NULL, SW_SHOWNORMAL); + triexit(0); +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* info() Print out complete instructions. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +void info() +{ + ShellExecute(NULL, "open", "https://www.cs.cmu.edu/~quake/triangle.help.html", NULL, NULL, SW_SHOWNORMAL); + triexit(0); +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* internalerror() Ask the user to send me the defective product. Exit. */ +/* */ +/*****************************************************************************/ + +void internalerror() +{ + printf(" Please report this bug to jrs@cs.berkeley.edu\n"); + printf(" Include the message above, your input data set, and the exact\n"); + printf(" command line you used to run Triangle.\n"); + triexit(1); +} + +/*****************************************************************************/ +/* */ +/* parsecommandline() Read the command line, identify switches, and set */ +/* up options and file names. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void parsecommandline(int argc, char **argv, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void parsecommandline(argc, argv, b) +int argc; +char **argv; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ +#ifdef TRILIBRARY +#define STARTINDEX 0 +#else /* not TRILIBRARY */ +#define STARTINDEX 1 + int increment; + int meshnumber; +#endif /* not TRILIBRARY */ + int i, j, k; + char workstring[FILENAMESIZE]; + + b->poly = b->refine = b->quality = 0; + b->vararea = b->fixedarea = b->usertest = 0; + b->regionattrib = b->convex = b->weighted = b->jettison = 0; + b->firstnumber = 1; + b->edgesout = b->voronoi = b->neighbors = b->geomview = 0; + b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0; + b->noiterationnum = 0; + b->noholes = b->noexact = 0; + b->incremental = b->sweepline = 0; + b->dwyer = 1; + b->splitseg = 0; + b->docheck = 0; + b->nobisect = 0; + b->conformdel = 0; + b->steiner = -1; + b->order = 1; + b->minangle = 0.0; + b->maxarea = -1.0; + b->quiet = b->verbose = 0; +#ifndef TRILIBRARY + b->innodefilename[0] = '\0'; +#endif /* not TRILIBRARY */ + + for (i = STARTINDEX; i < argc; i++) { +#ifndef TRILIBRARY + if (argv[i][0] == '-') { +#endif /* not TRILIBRARY */ + for (j = STARTINDEX; argv[i][j] != '\0'; j++) { + if (argv[i][j] == 'p') { + b->poly = 1; + } +#ifndef CDT_ONLY + if (argv[i][j] == 'r') { + b->refine = 1; + } + if (argv[i][j] == 'q') { + b->quality = 1; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + b->minangle = (REAL) strtod(workstring, (char **) NULL); + } else { + b->minangle = 20.0; + } + } + if (argv[i][j] == 'a') { + b->quality = 1; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + b->fixedarea = 1; + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + b->maxarea = (REAL) strtod(workstring, (char **) NULL); + if (b->maxarea <= 0.0) { + printf("Error: Maximum area must be greater than zero.\n"); + triexit(1); + } + } else { + b->vararea = 1; + } + } + if (argv[i][j] == 'u') { + b->quality = 1; + b->usertest = 1; + } +#endif /* not CDT_ONLY */ + if (argv[i][j] == 'A') { + b->regionattrib = 1; + } + if (argv[i][j] == 'c') { + b->convex = 1; + } + if (argv[i][j] == 'w') { + b->weighted = 1; + } + if (argv[i][j] == 'W') { + b->weighted = 2; + } + if (argv[i][j] == 'j') { + b->jettison = 1; + } + if (argv[i][j] == 'z') { + b->firstnumber = 0; + } + if (argv[i][j] == 'e') { + b->edgesout = 1; + } + if (argv[i][j] == 'v') { + b->voronoi = 1; + } + if (argv[i][j] == 'n') { + b->neighbors = 1; + } + if (argv[i][j] == 'g') { + b->geomview = 1; + } + if (argv[i][j] == 'B') { + b->nobound = 1; + } + if (argv[i][j] == 'P') { + b->nopolywritten = 1; + } + if (argv[i][j] == 'N') { + b->nonodewritten = 1; + } + if (argv[i][j] == 'E') { + b->noelewritten = 1; + } +#ifndef TRILIBRARY + if (argv[i][j] == 'I') { + b->noiterationnum = 1; + } +#endif /* not TRILIBRARY */ + if (argv[i][j] == 'O') { + b->noholes = 1; + } + if (argv[i][j] == 'X') { + b->noexact = 1; + } + if (argv[i][j] == 'o') { + if (argv[i][j + 1] == '2') { + j++; + b->order = 2; + } + } +#ifndef CDT_ONLY + if (argv[i][j] == 'Y') { + b->nobisect++; + } + if (argv[i][j] == 'S') { + b->steiner = 0; + while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + j++; + b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0'); + } + } +#endif /* not CDT_ONLY */ +#ifndef REDUCED + if (argv[i][j] == 'i') { + b->incremental = 1; + } + if (argv[i][j] == 'F') { + b->sweepline = 1; + } +#endif /* not REDUCED */ + if (argv[i][j] == 'l') { + b->dwyer = 0; + } +#ifndef REDUCED +#ifndef CDT_ONLY + if (argv[i][j] == 's') { + b->splitseg = 1; + } + if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) { + b->quality = 1; + b->conformdel = 1; + } +#endif /* not CDT_ONLY */ + if (argv[i][j] == 'C') { + b->docheck = 1; + } +#endif /* not REDUCED */ + if (argv[i][j] == 'Q') { + b->quiet = 1; + } + if (argv[i][j] == 'V') { + b->verbose++; + } +#ifndef TRILIBRARY + if ((argv[i][j] == 'h') || (argv[i][j] == 'H') || + (argv[i][j] == '?')) { + info(); + } +#endif /* not TRILIBRARY */ + } +#ifndef TRILIBRARY + } else { + strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1); + b->innodefilename[FILENAMESIZE - 1] = '\0'; + } +#endif /* not TRILIBRARY */ + } +#ifndef TRILIBRARY + if (b->innodefilename[0] == '\0') { + syntax(); + } + if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) { + b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; + } + if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) { + b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; + b->poly = 1; + } +#ifndef CDT_ONLY + if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) { + b->innodefilename[strlen(b->innodefilename) - 4] = '\0'; + b->refine = 1; + } + if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) { + b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; + b->refine = 1; + b->quality = 1; + b->vararea = 1; + } +#endif /* not CDT_ONLY */ +#endif /* not TRILIBRARY */ + b->usesegments = b->poly || b->refine || b->quality || b->convex; + b->goodangle = cos(b->minangle * PI / 180.0); + if (b->goodangle == 1.0) { + b->offconstant = 0.0; + } else { + b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle)); + } + b->goodangle *= b->goodangle; + if (b->refine && b->noiterationnum) { + printf( + "Error: You cannot use the -I switch when refining a triangulation.\n"); + triexit(1); + } + /* Be careful not to allocate space for element area constraints that */ + /* will never be assigned any value (other than the default -1.0). */ + if (!b->refine && !b->poly) { + b->vararea = 0; + } + /* Be careful not to add an extra attribute to each element unless the */ + /* input supports it (PSLG in, but not refining a preexisting mesh). */ + if (b->refine || !b->poly) { + b->regionattrib = 0; + } + /* Regular/weighted triangulations are incompatible with PSLGs */ + /* and meshing. */ + if (b->weighted && (b->poly || b->quality)) { + b->weighted = 0; + if (!b->quiet) { + printf("Warning: weighted triangulations (-w, -W) are incompatible\n"); + printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n" + ); + } + } + if (b->jettison && b->nonodewritten && !b->quiet) { + printf("Warning: -j and -N switches are somewhat incompatible.\n"); + printf(" If any vertices are jettisoned, you will need the output\n"); + printf(" .node file to reconstruct the new node indices."); + } + +#ifndef TRILIBRARY + strcpy(b->inpolyfilename, b->innodefilename); + strcpy(b->inelefilename, b->innodefilename); + strcpy(b->areafilename, b->innodefilename); + increment = 0; + strcpy(workstring, b->innodefilename); + j = 1; + while (workstring[j] != '\0') { + if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) { + increment = j + 1; + } + j++; + } + meshnumber = 0; + if (increment > 0) { + j = increment; + do { + if ((workstring[j] >= '0') && (workstring[j] <= '9')) { + meshnumber = meshnumber * 10 + (int) (workstring[j] - '0'); + } else { + increment = 0; + } + j++; + } while (workstring[j] != '\0'); + } + if (b->noiterationnum) { + strcpy(b->outnodefilename, b->innodefilename); + strcpy(b->outelefilename, b->innodefilename); + strcpy(b->edgefilename, b->innodefilename); + strcpy(b->vnodefilename, b->innodefilename); + strcpy(b->vedgefilename, b->innodefilename); + strcpy(b->neighborfilename, b->innodefilename); + strcpy(b->offfilename, b->innodefilename); + strcat(b->outnodefilename, ".node"); + strcat(b->outelefilename, ".ele"); + strcat(b->edgefilename, ".edge"); + strcat(b->vnodefilename, ".v.node"); + strcat(b->vedgefilename, ".v.edge"); + strcat(b->neighborfilename, ".neigh"); + strcat(b->offfilename, ".off"); + } else if (increment == 0) { + strcpy(b->outnodefilename, b->innodefilename); + strcpy(b->outpolyfilename, b->innodefilename); + strcpy(b->outelefilename, b->innodefilename); + strcpy(b->edgefilename, b->innodefilename); + strcpy(b->vnodefilename, b->innodefilename); + strcpy(b->vedgefilename, b->innodefilename); + strcpy(b->neighborfilename, b->innodefilename); + strcpy(b->offfilename, b->innodefilename); + strcat(b->outnodefilename, ".1.node"); + strcat(b->outpolyfilename, ".1.poly"); + strcat(b->outelefilename, ".1.ele"); + strcat(b->edgefilename, ".1.edge"); + strcat(b->vnodefilename, ".1.v.node"); + strcat(b->vedgefilename, ".1.v.edge"); + strcat(b->neighborfilename, ".1.neigh"); + strcat(b->offfilename, ".1.off"); + } else { + workstring[increment] = '%'; + workstring[increment + 1] = 'd'; + workstring[increment + 2] = '\0'; + sprintf(b->outnodefilename, workstring, meshnumber + 1); + strcpy(b->outpolyfilename, b->outnodefilename); + strcpy(b->outelefilename, b->outnodefilename); + strcpy(b->edgefilename, b->outnodefilename); + strcpy(b->vnodefilename, b->outnodefilename); + strcpy(b->vedgefilename, b->outnodefilename); + strcpy(b->neighborfilename, b->outnodefilename); + strcpy(b->offfilename, b->outnodefilename); + strcat(b->outnodefilename, ".node"); + strcat(b->outpolyfilename, ".poly"); + strcat(b->outelefilename, ".ele"); + strcat(b->edgefilename, ".edge"); + strcat(b->vnodefilename, ".v.node"); + strcat(b->vedgefilename, ".v.edge"); + strcat(b->neighborfilename, ".neigh"); + strcat(b->offfilename, ".off"); + } + strcat(b->innodefilename, ".node"); + strcat(b->inpolyfilename, ".poly"); + strcat(b->inelefilename, ".ele"); + strcat(b->areafilename, ".area"); +#endif /* not TRILIBRARY */ +} + +/** **/ +/** **/ +/********* User interaction routines begin here *********/ + +/********* Debugging routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* printtriangle() Print out the details of an oriented triangle. */ +/* */ +/* I originally wrote this procedure to simplify debugging; it can be */ +/* called directly from the debugger, and presents information about an */ +/* oriented triangle in digestible form. It's also used when the */ +/* highest level of verbosity (`-VVV') is specified. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void printtriangle(struct mesh *m, struct behavior *b, struct otri *t) +#else /* not ANSI_DECLARATORS */ +void printtriangle(m, b, t) +struct mesh *m; +struct behavior *b; +struct otri *t; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri printtri; + struct osub printsh; + vertex printvertex; + + printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri, + t->orient); + decode(t->tri[0], printtri); + if (printtri.tri == m->dummytri) { + printf(" [0] = Outer space\n"); + } else { + printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri, + printtri.orient); + } + decode(t->tri[1], printtri); + if (printtri.tri == m->dummytri) { + printf(" [1] = Outer space\n"); + } else { + printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri, + printtri.orient); + } + decode(t->tri[2], printtri); + if (printtri.tri == m->dummytri) { + printf(" [2] = Outer space\n"); + } else { + printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri, + printtri.orient); + } + + org(*t, printvertex); + if (printvertex == (vertex) NULL) + printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3); + else + printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", + (t->orient + 1) % 3 + 3, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + dest(*t, printvertex); + if (printvertex == (vertex) NULL) + printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3); + else + printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", + (t->orient + 2) % 3 + 3, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + apex(*t, printvertex); + if (printvertex == (vertex) NULL) + printf(" Apex [%d] = NULL\n", t->orient + 3); + else + printf(" Apex [%d] = x%lx (%.12g, %.12g)\n", + t->orient + 3, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + + if (b->usesegments) { + sdecode(t->tri[6], printsh); + if (printsh.ss != m->dummysub) { + printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss, + printsh.ssorient); + } + sdecode(t->tri[7], printsh); + if (printsh.ss != m->dummysub) { + printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss, + printsh.ssorient); + } + sdecode(t->tri[8], printsh); + if (printsh.ss != m->dummysub) { + printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss, + printsh.ssorient); + } + } + + if (b->vararea) { + printf(" Area constraint: %.4g\n", areabound(*t)); + } +} + +/*****************************************************************************/ +/* */ +/* printsubseg() Print out the details of an oriented subsegment. */ +/* */ +/* I originally wrote this procedure to simplify debugging; it can be */ +/* called directly from the debugger, and presents information about an */ +/* oriented subsegment in digestible form. It's also used when the highest */ +/* level of verbosity (`-VVV') is specified. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void printsubseg(struct mesh *m, struct behavior *b, struct osub *s) +#else /* not ANSI_DECLARATORS */ +void printsubseg(m, b, s) +struct mesh *m; +struct behavior *b; +struct osub *s; +#endif /* not ANSI_DECLARATORS */ + +{ + struct osub printsh; + struct otri printtri; + vertex printvertex; + + printf("subsegment x%lx with orientation %d and mark %d:\n", + (unsigned long) s->ss, s->ssorient, mark(*s)); + sdecode(s->ss[0], printsh); + if (printsh.ss == m->dummysub) { + printf(" [0] = No subsegment\n"); + } else { + printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss, + printsh.ssorient); + } + sdecode(s->ss[1], printsh); + if (printsh.ss == m->dummysub) { + printf(" [1] = No subsegment\n"); + } else { + printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss, + printsh.ssorient); + } + + sorg(*s, printvertex); + if (printvertex == (vertex) NULL) + printf(" Origin[%d] = NULL\n", 2 + s->ssorient); + else + printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", + 2 + s->ssorient, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + sdest(*s, printvertex); + if (printvertex == (vertex) NULL) + printf(" Dest [%d] = NULL\n", 3 - s->ssorient); + else + printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", + 3 - s->ssorient, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + + decode(s->ss[6], printtri); + if (printtri.tri == m->dummytri) { + printf(" [6] = Outer space\n"); + } else { + printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri, + printtri.orient); + } + decode(s->ss[7], printtri); + if (printtri.tri == m->dummytri) { + printf(" [7] = Outer space\n"); + } else { + printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri, + printtri.orient); + } + + segorg(*s, printvertex); + if (printvertex == (vertex) NULL) + printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient); + else + printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n", + 4 + s->ssorient, (unsigned long) printvertex, + printvertex[0], printvertex[1]); + segdest(*s, printvertex); + if (printvertex == (vertex) NULL) + printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient); + else + printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n", + 5 - s->ssorient, (unsigned long) printvertex, + printvertex[0], printvertex[1]); +} + +/** **/ +/** **/ +/********* Debugging routines end here *********/ + +/********* Memory management routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* poolzero() Set all of a pool's fields to zero. */ +/* */ +/* This procedure should never be called on a pool that has any memory */ +/* allocated to it, as that memory would leak. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void poolzero(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +void poolzero(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + pool->firstblock = (VOID **) NULL; + pool->nowblock = (VOID **) NULL; + pool->nextitem = (VOID *) NULL; + pool->deaditemstack = (VOID *) NULL; + pool->pathblock = (VOID **) NULL; + pool->pathitem = (VOID *) NULL; + pool->alignbytes = 0; + pool->itembytes = 0; + pool->itemsperblock = 0; + pool->itemsfirstblock = 0; + pool->items = 0; + pool->maxitems = 0; + pool->unallocateditems = 0; + pool->pathitemsleft = 0; +} + +/*****************************************************************************/ +/* */ +/* poolrestart() Deallocate all items in a pool. */ +/* */ +/* The pool is returned to its starting state, except that no memory is */ +/* freed to the operating system. Rather, the previously allocated blocks */ +/* are ready to be reused. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void poolrestart(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +void poolrestart(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + unsigned long alignptr; + + pool->items = 0; + pool->maxitems = 0; + + /* Set the currently active block. */ + pool->nowblock = pool->firstblock; + /* Find the first item in the pool. Increment by the size of (VOID *). */ + alignptr = (unsigned long) (pool->nowblock + 1); + /* Align the item on an `alignbytes'-byte boundary. */ + pool->nextitem = (VOID *) + (alignptr + (unsigned long) pool->alignbytes - + (alignptr % (unsigned long) pool->alignbytes)); + /* There are lots of unallocated items left in this block. */ + pool->unallocateditems = pool->itemsfirstblock; + /* The stack of deallocated items is empty. */ + pool->deaditemstack = (VOID *) NULL; +} + +/*****************************************************************************/ +/* */ +/* poolinit() Initialize a pool of memory for allocation of items. */ +/* */ +/* This routine initializes the machinery for allocating items. A `pool' */ +/* is created whose records have size at least `bytecount'. Items will be */ +/* allocated in `itemcount'-item blocks. Each item is assumed to be a */ +/* collection of words, and either pointers or floating-point values are */ +/* assumed to be the "primary" word type. (The "primary" word type is used */ +/* to determine alignment of items.) If `alignment' isn't zero, all items */ +/* will be `alignment'-byte aligned in memory. `alignment' must be either */ +/* a multiple or a factor of the primary word size; powers of two are safe. */ +/* `alignment' is normally used to create a few unused bits at the bottom */ +/* of each item's pointer, in which information may be stored. */ +/* */ +/* Don't change this routine unless you understand it. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void poolinit(struct memorypool *pool, int bytecount, int itemcount, + int firstitemcount, int alignment) +#else /* not ANSI_DECLARATORS */ +void poolinit(pool, bytecount, itemcount, firstitemcount, alignment) +struct memorypool *pool; +int bytecount; +int itemcount; +int firstitemcount; +int alignment; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Find the proper alignment, which must be at least as large as: */ + /* - The parameter `alignment'. */ + /* - sizeof(VOID *), so the stack of dead items can be maintained */ + /* without unaligned accesses. */ + if (alignment > sizeof(VOID *)) { + pool->alignbytes = alignment; + } else { + pool->alignbytes = sizeof(VOID *); + } + pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) * + pool->alignbytes; + pool->itemsperblock = itemcount; + if (firstitemcount == 0) { + pool->itemsfirstblock = itemcount; + } else { + pool->itemsfirstblock = firstitemcount; + } + + /* Allocate a block of items. Space for `itemsfirstblock' items and one */ + /* pointer (to point to the next block) are allocated, as well as space */ + /* to ensure alignment of the items. */ + pool->firstblock = (VOID **) + trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) + + pool->alignbytes); + /* Set the next block pointer to NULL. */ + *(pool->firstblock) = (VOID *) NULL; + poolrestart(pool); +} + +/*****************************************************************************/ +/* */ +/* pooldeinit() Free to the operating system all memory taken by a pool. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void pooldeinit(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +void pooldeinit(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + while (pool->firstblock != (VOID **) NULL) { + pool->nowblock = (VOID **) *(pool->firstblock); + trifree((VOID *) pool->firstblock); + pool->firstblock = pool->nowblock; + } +} + +/*****************************************************************************/ +/* */ +/* poolalloc() Allocate space for an item. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +VOID *poolalloc(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +VOID *poolalloc(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + VOID *newitem; + VOID **newblock; + unsigned long alignptr; + + /* First check the linked list of dead items. If the list is not */ + /* empty, allocate an item from the list rather than a fresh one. */ + if (pool->deaditemstack != (VOID *) NULL) { + newitem = pool->deaditemstack; /* Take first item in list. */ + pool->deaditemstack = * (VOID **) pool->deaditemstack; + } else { + /* Check if there are any free items left in the current block. */ + if (pool->unallocateditems == 0) { + /* Check if another block must be allocated. */ + if (*(pool->nowblock) == (VOID *) NULL) { + /* Allocate a new block of items, pointed to by the previous block. */ + newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes + + (int) sizeof(VOID *) + + pool->alignbytes); + *(pool->nowblock) = (VOID *) newblock; + /* The next block pointer is NULL. */ + *newblock = (VOID *) NULL; + } + + /* Move to the new block. */ + pool->nowblock = (VOID **) *(pool->nowblock); + /* Find the first item in the block. */ + /* Increment by the size of (VOID *). */ + alignptr = (unsigned long) (pool->nowblock + 1); + /* Align the item on an `alignbytes'-byte boundary. */ + pool->nextitem = (VOID *) + (alignptr + (unsigned long) pool->alignbytes - + (alignptr % (unsigned long) pool->alignbytes)); + /* There are lots of unallocated items left in this block. */ + pool->unallocateditems = pool->itemsperblock; + } + + /* Allocate a new item. */ + newitem = pool->nextitem; + /* Advance `nextitem' pointer to next free item in block. */ + pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes); + pool->unallocateditems--; + pool->maxitems++; + } + pool->items++; + return newitem; +} + +/*****************************************************************************/ +/* */ +/* pooldealloc() Deallocate space for an item. */ +/* */ +/* The deallocated space is stored in a queue for later reuse. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void pooldealloc(struct memorypool *pool, VOID *dyingitem) +#else /* not ANSI_DECLARATORS */ +void pooldealloc(pool, dyingitem) +struct memorypool *pool; +VOID *dyingitem; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Push freshly killed item onto stack. */ + *((VOID **) dyingitem) = pool->deaditemstack; + pool->deaditemstack = dyingitem; + pool->items--; +} + +/*****************************************************************************/ +/* */ +/* traversalinit() Prepare to traverse the entire list of items. */ +/* */ +/* This routine is used in conjunction with traverse(). */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void traversalinit(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +void traversalinit(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + unsigned long alignptr; + + /* Begin the traversal in the first block. */ + pool->pathblock = pool->firstblock; + /* Find the first item in the block. Increment by the size of (VOID *). */ + alignptr = (unsigned long) (pool->pathblock + 1); + /* Align with item on an `alignbytes'-byte boundary. */ + pool->pathitem = (VOID *) + (alignptr + (unsigned long) pool->alignbytes - + (alignptr % (unsigned long) pool->alignbytes)); + /* Set the number of items left in the current block. */ + pool->pathitemsleft = pool->itemsfirstblock; +} + +/*****************************************************************************/ +/* */ +/* traverse() Find the next item in the list. */ +/* */ +/* This routine is used in conjunction with traversalinit(). Be forewarned */ +/* that this routine successively returns all items in the list, including */ +/* deallocated ones on the deaditemqueue. It's up to you to figure out */ +/* which ones are actually dead. Why? I don't want to allocate extra */ +/* space just to demarcate dead items. It can usually be done more */ +/* space-efficiently by a routine that knows something about the structure */ +/* of the item. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +VOID *traverse(struct memorypool *pool) +#else /* not ANSI_DECLARATORS */ +VOID *traverse(pool) +struct memorypool *pool; +#endif /* not ANSI_DECLARATORS */ + +{ + VOID *newitem; + unsigned long alignptr; + + /* Stop upon exhausting the list of items. */ + if (pool->pathitem == pool->nextitem) { + return (VOID *) NULL; + } + + /* Check whether any untraversed items remain in the current block. */ + if (pool->pathitemsleft == 0) { + /* Find the next block. */ + pool->pathblock = (VOID **) *(pool->pathblock); + /* Find the first item in the block. Increment by the size of (VOID *). */ + alignptr = (unsigned long) (pool->pathblock + 1); + /* Align with item on an `alignbytes'-byte boundary. */ + pool->pathitem = (VOID *) + (alignptr + (unsigned long) pool->alignbytes - + (alignptr % (unsigned long) pool->alignbytes)); + /* Set the number of items left in the current block. */ + pool->pathitemsleft = pool->itemsperblock; + } + + newitem = pool->pathitem; + /* Find the next item in the block. */ + pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes); + pool->pathitemsleft--; + return newitem; +} + +/*****************************************************************************/ +/* */ +/* dummyinit() Initialize the triangle that fills "outer space" and the */ +/* omnipresent subsegment. */ +/* */ +/* The triangle that fills "outer space," called `dummytri', is pointed to */ +/* by every triangle and subsegment on a boundary (be it outer or inner) of */ +/* the triangulation. Also, `dummytri' points to one of the triangles on */ +/* the convex hull (until the holes and concavities are carved), making it */ +/* possible to find a starting triangle for point location. */ +/* */ +/* The omnipresent subsegment, `dummysub', is pointed to by every triangle */ +/* or subsegment that doesn't have a full complement of real subsegments */ +/* to point to. */ +/* */ +/* `dummytri' and `dummysub' are generally required to fulfill only a few */ +/* invariants: their vertices must remain NULL and `dummytri' must always */ +/* be bonded (at offset zero) to some triangle on the convex hull of the */ +/* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */ +/* `dummysub' may change willy-nilly. This makes it possible to avoid */ +/* writing a good deal of special-case code (in the edge flip, for example) */ +/* for dealing with the boundary of the mesh, places where no subsegment is */ +/* present, and so forth. Other entities are frequently bonded to */ +/* `dummytri' and `dummysub' as if they were real mesh entities, with no */ +/* harm done. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, + int subsegbytes) +#else /* not ANSI_DECLARATORS */ +void dummyinit(m, b, trianglebytes, subsegbytes) +struct mesh *m; +struct behavior *b; +int trianglebytes; +int subsegbytes; +#endif /* not ANSI_DECLARATORS */ + +{ + unsigned long alignptr; + + /* Set up `dummytri', the `triangle' that occupies "outer space." */ + m->dummytribase = (triangle *) trimalloc(trianglebytes + + m->triangles.alignbytes); + /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */ + alignptr = (unsigned long) m->dummytribase; + m->dummytri = (triangle *) + (alignptr + (unsigned long) m->triangles.alignbytes - + (alignptr % (unsigned long) m->triangles.alignbytes)); + /* Initialize the three adjoining triangles to be "outer space." These */ + /* will eventually be changed by various bonding operations, but their */ + /* values don't really matter, as long as they can legally be */ + /* dereferenced. */ + m->dummytri[0] = (triangle) m->dummytri; + m->dummytri[1] = (triangle) m->dummytri; + m->dummytri[2] = (triangle) m->dummytri; + /* Three NULL vertices. */ + m->dummytri[3] = (triangle) NULL; + m->dummytri[4] = (triangle) NULL; + m->dummytri[5] = (triangle) NULL; + + if (b->usesegments) { + /* Set up `dummysub', the omnipresent subsegment pointed to by any */ + /* triangle side or subsegment end that isn't attached to a real */ + /* subsegment. */ + m->dummysubbase = (subseg *) trimalloc(subsegbytes + + m->subsegs.alignbytes); + /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */ + alignptr = (unsigned long) m->dummysubbase; + m->dummysub = (subseg *) + (alignptr + (unsigned long) m->subsegs.alignbytes - + (alignptr % (unsigned long) m->subsegs.alignbytes)); + /* Initialize the two adjoining subsegments to be the omnipresent */ + /* subsegment. These will eventually be changed by various bonding */ + /* operations, but their values don't really matter, as long as they */ + /* can legally be dereferenced. */ + m->dummysub[0] = (subseg) m->dummysub; + m->dummysub[1] = (subseg) m->dummysub; + /* Four NULL vertices. */ + m->dummysub[2] = (subseg) NULL; + m->dummysub[3] = (subseg) NULL; + m->dummysub[4] = (subseg) NULL; + m->dummysub[5] = (subseg) NULL; + /* Initialize the two adjoining triangles to be "outer space." */ + m->dummysub[6] = (subseg) m->dummytri; + m->dummysub[7] = (subseg) m->dummytri; + /* Set the boundary marker to zero. */ + * (int *) (m->dummysub + 8) = 0; + + /* Initialize the three adjoining subsegments of `dummytri' to be */ + /* the omnipresent subsegment. */ + m->dummytri[6] = (triangle) m->dummysub; + m->dummytri[7] = (triangle) m->dummysub; + m->dummytri[8] = (triangle) m->dummysub; + } +} + +/*****************************************************************************/ +/* */ +/* initializevertexpool() Calculate the size of the vertex data structure */ +/* and initialize its memory pool. */ +/* */ +/* This routine also computes the `vertexmarkindex' and `vertex2triindex' */ +/* indices used to find values within each vertex. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void initializevertexpool(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void initializevertexpool(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + int vertexsize; + + /* The index within each vertex at which the boundary marker is found, */ + /* followed by the vertex type. Ensure the vertex marker is aligned to */ + /* a sizeof(int)-byte address. */ + m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) + + sizeof(int) - 1) / + sizeof(int); + vertexsize = (m->vertexmarkindex + 2) * sizeof(int); + if (b->poly) { + /* The index within each vertex at which a triangle pointer is found. */ + /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */ + m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) / + sizeof(triangle); + vertexsize = (m->vertex2triindex + 1) * sizeof(triangle); + } + + /* Initialize the pool of vertices. */ + poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK, + m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK, + sizeof(REAL)); +} + +/*****************************************************************************/ +/* */ +/* initializetrisubpools() Calculate the sizes of the triangle and */ +/* subsegment data structures and initialize */ +/* their memory pools. */ +/* */ +/* This routine also computes the `highorderindex', `elemattribindex', and */ +/* `areaboundindex' indices used to find values within each triangle. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void initializetrisubpools(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void initializetrisubpools(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + int trisize; + + /* The index within each triangle at which the extra nodes (above three) */ + /* associated with high order elements are found. There are three */ + /* pointers to other triangles, three pointers to corners, and possibly */ + /* three pointers to subsegments before the extra nodes. */ + m->highorderindex = 6 + (b->usesegments * 3); + /* The number of bytes occupied by a triangle. */ + trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) * + sizeof(triangle); + /* The index within each triangle at which its attributes are found, */ + /* where the index is measured in REALs. */ + m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL); + /* The index within each triangle at which the maximum area constraint */ + /* is found, where the index is measured in REALs. Note that if the */ + /* `regionattrib' flag is set, an additional attribute will be added. */ + m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib; + /* If triangle attributes or an area bound are needed, increase the number */ + /* of bytes occupied by a triangle. */ + if (b->vararea) { + trisize = (m->areaboundindex + 1) * sizeof(REAL); + } else if (m->eextras + b->regionattrib > 0) { + trisize = m->areaboundindex * sizeof(REAL); + } + /* If a Voronoi diagram or triangle neighbor graph is requested, make */ + /* sure there's room to store an integer index in each triangle. This */ + /* integer index can occupy the same space as the subsegment pointers */ + /* or attributes or area constraint or extra nodes. */ + if ((b->voronoi || b->neighbors) && + (trisize < 6 * sizeof(triangle) + sizeof(int))) { + trisize = 6 * sizeof(triangle) + sizeof(int); + } + + /* Having determined the memory size of a triangle, initialize the pool. */ + poolinit(&m->triangles, trisize, TRIPERBLOCK, + (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) : + TRIPERBLOCK, 4); + + if (b->usesegments) { + /* Initialize the pool of subsegments. Take into account all eight */ + /* pointers and one boundary marker. */ + poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int), + SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4); + + /* Initialize the "outer space" triangle and omnipresent subsegment. */ + dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes); + } else { + /* Initialize the "outer space" triangle. */ + dummyinit(m, b, m->triangles.itembytes, 0); + } +} + +/*****************************************************************************/ +/* */ +/* triangledealloc() Deallocate space for a triangle, marking it dead. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void triangledealloc(struct mesh *m, triangle *dyingtriangle) +#else /* not ANSI_DECLARATORS */ +void triangledealloc(m, dyingtriangle) +struct mesh *m; +triangle *dyingtriangle; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Mark the triangle as dead. This makes it possible to detect dead */ + /* triangles when traversing the list of all triangles. */ + killtri(dyingtriangle); + pooldealloc(&m->triangles, (VOID *) dyingtriangle); +} + +/*****************************************************************************/ +/* */ +/* triangletraverse() Traverse the triangles, skipping dead ones. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +triangle *triangletraverse(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +triangle *triangletraverse(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + triangle *newtriangle; + + do { + newtriangle = (triangle *) traverse(&m->triangles); + if (newtriangle == (triangle *) NULL) { + return (triangle *) NULL; + } + } while (deadtri(newtriangle)); /* Skip dead ones. */ + return newtriangle; +} + +/*****************************************************************************/ +/* */ +/* subsegdealloc() Deallocate space for a subsegment, marking it dead. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void subsegdealloc(struct mesh *m, subseg *dyingsubseg) +#else /* not ANSI_DECLARATORS */ +void subsegdealloc(m, dyingsubseg) +struct mesh *m; +subseg *dyingsubseg; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Mark the subsegment as dead. This makes it possible to detect dead */ + /* subsegments when traversing the list of all subsegments. */ + killsubseg(dyingsubseg); + pooldealloc(&m->subsegs, (VOID *) dyingsubseg); +} + +/*****************************************************************************/ +/* */ +/* subsegtraverse() Traverse the subsegments, skipping dead ones. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +subseg *subsegtraverse(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +subseg *subsegtraverse(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + subseg *newsubseg; + + do { + newsubseg = (subseg *) traverse(&m->subsegs); + if (newsubseg == (subseg *) NULL) { + return (subseg *) NULL; + } + } while (deadsubseg(newsubseg)); /* Skip dead ones. */ + return newsubseg; +} + +/*****************************************************************************/ +/* */ +/* vertexdealloc() Deallocate space for a vertex, marking it dead. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void vertexdealloc(struct mesh *m, vertex dyingvertex) +#else /* not ANSI_DECLARATORS */ +void vertexdealloc(m, dyingvertex) +struct mesh *m; +vertex dyingvertex; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Mark the vertex as dead. This makes it possible to detect dead */ + /* vertices when traversing the list of all vertices. */ + setvertextype(dyingvertex, DEADVERTEX); + pooldealloc(&m->vertices, (VOID *) dyingvertex); +} + +/*****************************************************************************/ +/* */ +/* vertextraverse() Traverse the vertices, skipping dead ones. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +vertex vertextraverse(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +vertex vertextraverse(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex newvertex; + + do { + newvertex = (vertex) traverse(&m->vertices); + if (newvertex == (vertex) NULL) { + return (vertex) NULL; + } + } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */ + return newvertex; +} + +/*****************************************************************************/ +/* */ +/* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */ +/* dead. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg) +#else /* not ANSI_DECLARATORS */ +void badsubsegdealloc(m, dyingseg) +struct mesh *m; +struct badsubseg *dyingseg; +#endif /* not ANSI_DECLARATORS */ + +{ + /* Set subsegment's origin to NULL. This makes it possible to detect dead */ + /* badsubsegs when traversing the list of all badsubsegs . */ + dyingseg->subsegorg = (vertex) NULL; + pooldealloc(&m->badsubsegs, (VOID *) dyingseg); +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +struct badsubseg *badsubsegtraverse(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +struct badsubseg *badsubsegtraverse(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + struct badsubseg *newseg; + + do { + newseg = (struct badsubseg *) traverse(&m->badsubsegs); + if (newseg == (struct badsubseg *) NULL) { + return (struct badsubseg *) NULL; + } + } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */ + return newseg; +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* getvertex() Get a specific vertex, by number, from the list. */ +/* */ +/* The first vertex is number 'firstnumber'. */ +/* */ +/* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */ +/* is large). I don't care to take the trouble to make it work in constant */ +/* time. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +vertex getvertex(struct mesh *m, struct behavior *b, int number) +#else /* not ANSI_DECLARATORS */ +vertex getvertex(m, b, number) +struct mesh *m; +struct behavior *b; +int number; +#endif /* not ANSI_DECLARATORS */ + +{ + VOID **getblock; + char *foundvertex; + unsigned long alignptr; + int current; + + getblock = m->vertices.firstblock; + current = b->firstnumber; + + /* Find the right block. */ + if (current + m->vertices.itemsfirstblock <= number) { + getblock = (VOID **) *getblock; + current += m->vertices.itemsfirstblock; + while (current + m->vertices.itemsperblock <= number) { + getblock = (VOID **) *getblock; + current += m->vertices.itemsperblock; + } + } + + /* Now find the right vertex. */ + alignptr = (unsigned long) (getblock + 1); + foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes - + (alignptr % (unsigned long) m->vertices.alignbytes)); + return (vertex) (foundvertex + m->vertices.itembytes * (number - current)); +} + +/*****************************************************************************/ +/* */ +/* triangledeinit() Free all remaining allocated memory. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void triangledeinit(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void triangledeinit(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + pooldeinit(&m->triangles); + trifree((VOID *) m->dummytribase); + if (b->usesegments) { + pooldeinit(&m->subsegs); + trifree((VOID *) m->dummysubbase); + } + pooldeinit(&m->vertices); +#ifndef CDT_ONLY + if (b->quality) { + pooldeinit(&m->badsubsegs); + if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) { + pooldeinit(&m->badtriangles); + pooldeinit(&m->flipstackers); + } + } +#endif /* not CDT_ONLY */ +} + +/** **/ +/** **/ +/********* Memory management routines end here *********/ + +/********* Constructors begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* maketriangle() Create a new triangle with orientation zero. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri) +#else /* not ANSI_DECLARATORS */ +void maketriangle(m, b, newotri) +struct mesh *m; +struct behavior *b; +struct otri *newotri; +#endif /* not ANSI_DECLARATORS */ + +{ + int i; + + newotri->tri = (triangle *) poolalloc(&m->triangles); + /* Initialize the three adjoining triangles to be "outer space". */ + newotri->tri[0] = (triangle) m->dummytri; + newotri->tri[1] = (triangle) m->dummytri; + newotri->tri[2] = (triangle) m->dummytri; + /* Three NULL vertices. */ + newotri->tri[3] = (triangle) NULL; + newotri->tri[4] = (triangle) NULL; + newotri->tri[5] = (triangle) NULL; + if (b->usesegments) { + /* Initialize the three adjoining subsegments to be the omnipresent */ + /* subsegment. */ + newotri->tri[6] = (triangle) m->dummysub; + newotri->tri[7] = (triangle) m->dummysub; + newotri->tri[8] = (triangle) m->dummysub; + } + for (i = 0; i < m->eextras; i++) { + setelemattribute(*newotri, i, 0.0); + } + if (b->vararea) { + setareabound(*newotri, -1.0); + } + + newotri->orient = 0; +} + +/*****************************************************************************/ +/* */ +/* makesubseg() Create a new subsegment with orientation zero. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void makesubseg(struct mesh *m, struct osub *newsubseg) +#else /* not ANSI_DECLARATORS */ +void makesubseg(m, newsubseg) +struct mesh *m; +struct osub *newsubseg; +#endif /* not ANSI_DECLARATORS */ + +{ + newsubseg->ss = (subseg *) poolalloc(&m->subsegs); + /* Initialize the two adjoining subsegments to be the omnipresent */ + /* subsegment. */ + newsubseg->ss[0] = (subseg) m->dummysub; + newsubseg->ss[1] = (subseg) m->dummysub; + /* Four NULL vertices. */ + newsubseg->ss[2] = (subseg) NULL; + newsubseg->ss[3] = (subseg) NULL; + newsubseg->ss[4] = (subseg) NULL; + newsubseg->ss[5] = (subseg) NULL; + /* Initialize the two adjoining triangles to be "outer space." */ + newsubseg->ss[6] = (subseg) m->dummytri; + newsubseg->ss[7] = (subseg) m->dummytri; + /* Set the boundary marker to zero. */ + setmark(*newsubseg, 0); + + newsubseg->ssorient = 0; +} + +/** **/ +/** **/ +/********* Constructors end here *********/ + +/********* Geometric primitives begin here *********/ +/** **/ +/** **/ + +/* The adaptive exact arithmetic geometric predicates implemented herein are */ +/* described in detail in my paper, "Adaptive Precision Floating-Point */ +/* Arithmetic and Fast Robust Geometric Predicates." See the header for a */ +/* full citation. */ + +/* Which of the following two methods of finding the absolute values is */ +/* fastest is compiler-dependent. A few compilers can inline and optimize */ +/* the fabs() call; but most will incur the overhead of a function call, */ +/* which is disastrously slow. A faster way on IEEE machines might be to */ +/* mask the appropriate bit, but that's difficult to do in C without */ +/* forcing the value to be stored to memory (rather than be kept in the */ +/* register to which the optimizer assigned it). */ + +#define Absolute(a) ((a) >= 0.0 ? (a) : -(a)) +/* #define Absolute(a) fabs(a) */ + +/* Many of the operations are broken up into two pieces, a main part that */ +/* performs an approximate operation, and a "tail" that computes the */ +/* roundoff error of that operation. */ +/* */ +/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */ +/* Split(), and Two_Product() are all implemented as described in the */ +/* reference. Each of these macros requires certain variables to be */ +/* defined in the calling routine. The variables `bvirt', `c', `abig', */ +/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */ +/* they store the result of an operation that may incur roundoff error. */ +/* The input parameter `x' (or the highest numbered `x_' parameter) must */ +/* also be declared `INEXACT'. */ + +#define Fast_Two_Sum_Tail(a, b, x, y) \ + bvirt = x - a; \ + y = b - bvirt + +#define Fast_Two_Sum(a, b, x, y) \ + x = (REAL) (a + b); \ + Fast_Two_Sum_Tail(a, b, x, y) + +#define Two_Sum_Tail(a, b, x, y) \ + bvirt = (REAL) (x - a); \ + avirt = x - bvirt; \ + bround = b - bvirt; \ + around = a - avirt; \ + y = around + bround + +#define Two_Sum(a, b, x, y) \ + x = (REAL) (a + b); \ + Two_Sum_Tail(a, b, x, y) + +#define Two_Diff_Tail(a, b, x, y) \ + bvirt = (REAL) (a - x); \ + avirt = x + bvirt; \ + bround = bvirt - b; \ + around = a - avirt; \ + y = around + bround + +#define Two_Diff(a, b, x, y) \ + x = (REAL) (a - b); \ + Two_Diff_Tail(a, b, x, y) + +#define Split(a, ahi, alo) \ + c = (REAL) (splitter * a); \ + abig = (REAL) (c - a); \ + ahi = c - abig; \ + alo = a - ahi + +#define Two_Product_Tail(a, b, x, y) \ + Split(a, ahi, alo); \ + Split(b, bhi, blo); \ + err1 = x - (ahi * bhi); \ + err2 = err1 - (alo * bhi); \ + err3 = err2 - (ahi * blo); \ + y = (alo * blo) - err3 + +#define Two_Product(a, b, x, y) \ + x = (REAL) (a * b); \ + Two_Product_Tail(a, b, x, y) + +/* Two_Product_Presplit() is Two_Product() where one of the inputs has */ +/* already been split. Avoids redundant splitting. */ + +#define Two_Product_Presplit(a, b, bhi, blo, x, y) \ + x = (REAL) (a * b); \ + Split(a, ahi, alo); \ + err1 = x - (ahi * bhi); \ + err2 = err1 - (alo * bhi); \ + err3 = err2 - (ahi * blo); \ + y = (alo * blo) - err3 + +/* Square() can be done more quickly than Two_Product(). */ + +#define Square_Tail(a, x, y) \ + Split(a, ahi, alo); \ + err1 = x - (ahi * ahi); \ + err3 = err1 - ((ahi + ahi) * alo); \ + y = (alo * alo) - err3 + +#define Square(a, x, y) \ + x = (REAL) (a * a); \ + Square_Tail(a, x, y) + +/* Macros for summing expansions of various fixed lengths. These are all */ +/* unrolled versions of Expansion_Sum(). */ + +#define Two_One_Sum(a1, a0, b, x2, x1, x0) \ + Two_Sum(a0, b , _i, x0); \ + Two_Sum(a1, _i, x2, x1) + +#define Two_One_Diff(a1, a0, b, x2, x1, x0) \ + Two_Diff(a0, b , _i, x0); \ + Two_Sum( a1, _i, x2, x1) + +#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \ + Two_One_Sum(a1, a0, b0, _j, _0, x0); \ + Two_One_Sum(_j, _0, b1, x3, x2, x1) + +#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \ + Two_One_Diff(a1, a0, b0, _j, _0, x0); \ + Two_One_Diff(_j, _0, b1, x3, x2, x1) + +/* Macro for multiplying a two-component expansion by a single component. */ + +#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \ + Split(b, bhi, blo); \ + Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \ + Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, x1); \ + Fast_Two_Sum(_j, _k, x3, x2) + +/*****************************************************************************/ +/* */ +/* exactinit() Initialize the variables used for exact arithmetic. */ +/* */ +/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */ +/* floating-point arithmetic. `epsilon' bounds the relative roundoff */ +/* error. It is used for floating-point error analysis. */ +/* */ +/* `splitter' is used to split floating-point numbers into two half- */ +/* length significands for exact multiplication. */ +/* */ +/* I imagine that a highly optimizing compiler might be too smart for its */ +/* own good, and somehow cause this routine to fail, if it pretends that */ +/* floating-point arithmetic is too much like real arithmetic. */ +/* */ +/* Don't change this routine unless you fully understand it. */ +/* */ +/*****************************************************************************/ + +void exactinit() +{ + REAL half; + REAL check, lastcheck; + int every_other; +#ifdef LINUX + int cword; +#endif /* LINUX */ + +#ifdef CPU86 +#ifdef SINGLE + _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */ +#else /* not SINGLE */ + _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */ +#endif /* not SINGLE */ +#endif /* CPU86 */ +#ifdef LINUX +#ifdef SINGLE + /* cword = 4223; */ + cword = 4210; /* set FPU control word for single precision */ +#else /* not SINGLE */ + /* cword = 4735; */ + cword = 4722; /* set FPU control word for double precision */ +#endif /* not SINGLE */ + _FPU_SETCW(cword); +#endif /* LINUX */ + + every_other = 1; + half = 0.5; + epsilon = 1.0; + splitter = 1.0; + check = 1.0; + /* Repeatedly divide `epsilon' by two until it is too small to add to */ + /* one without causing roundoff. (Also check if the sum is equal to */ + /* the previous sum, for machines that round up instead of using exact */ + /* rounding. Not that these routines will work on such machines.) */ + do { + lastcheck = check; + epsilon *= half; + if (every_other) { + splitter *= 2.0; + } + every_other = !every_other; + check = 1.0 + epsilon; + } while ((check != 1.0) && (check != lastcheck)); + splitter += 1.0; + /* Error bounds for orientation and incircle tests. */ + resulterrbound = (3.0 + 8.0 * epsilon) * epsilon; + ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon; + ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon; + ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon; + iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon; + iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon; + iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon; + o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon; + o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon; + o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon; +} + +/*****************************************************************************/ +/* */ +/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */ +/* components from the output expansion. */ +/* */ +/* Sets h = e + f. See my Robust Predicates paper for details. */ +/* */ +/* If round-to-even is used (as with IEEE 754), maintains the strongly */ +/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */ +/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */ +/* properties. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h) +#else /* not ANSI_DECLARATORS */ +int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */ +int elen; +REAL *e; +int flen; +REAL *f; +REAL *h; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL Q; + INEXACT REAL Qnew; + INEXACT REAL hh; + INEXACT REAL bvirt; + REAL avirt, bround, around; + int eindex, findex, hindex; + REAL enow, fnow; + + enow = e[0]; + fnow = f[0]; + eindex = findex = 0; + if ((fnow > enow) == (fnow > -enow)) { + Q = enow; + enow = e[++eindex]; + } else { + Q = fnow; + fnow = f[++findex]; + } + hindex = 0; + if ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Fast_Two_Sum(enow, Q, Qnew, hh); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, Q, Qnew, hh); + fnow = f[++findex]; + } + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + while ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Two_Sum(Q, enow, Qnew, hh); + enow = e[++eindex]; + } else { + Two_Sum(Q, fnow, Qnew, hh); + fnow = f[++findex]; + } + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + } + while (eindex < elen) { + Two_Sum(Q, enow, Qnew, hh); + enow = e[++eindex]; + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + while (findex < flen) { + Two_Sum(Q, fnow, Qnew, hh); + fnow = f[++findex]; + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */ +/* eliminating zero components from the */ +/* output expansion. */ +/* */ +/* Sets h = be. See my Robust Predicates paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ +/* properties as well. (That is, if e has one of these properties, so */ +/* will h.) */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) +#else /* not ANSI_DECLARATORS */ +int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */ +int elen; +REAL *e; +REAL b; +REAL *h; +#endif /* not ANSI_DECLARATORS */ + +{ + INEXACT REAL Q, sum; + REAL hh; + INEXACT REAL product1; + REAL product0; + int eindex, hindex; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + + Split(b, bhi, blo); + Two_Product_Presplit(e[0], b, bhi, blo, Q, hh); + hindex = 0; + if (hh != 0) { + h[hindex++] = hh; + } + for (eindex = 1; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Product_Presplit(enow, b, bhi, blo, product1, product0); + Two_Sum(Q, product0, sum, hh); + if (hh != 0) { + h[hindex++] = hh; + } + Fast_Two_Sum(product1, sum, Q, hh); + if (hh != 0) { + h[hindex++] = hh; + } + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* estimate() Produce a one-word estimate of an expansion's value. */ +/* */ +/* See my Robust Predicates paper for details. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +REAL estimate(int elen, REAL *e) +#else /* not ANSI_DECLARATORS */ +REAL estimate(elen, e) +int elen; +REAL *e; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL Q; + int eindex; + + Q = e[0]; + for (eindex = 1; eindex < elen; eindex++) { + Q += e[eindex]; + } + return Q; +} + +/*****************************************************************************/ +/* */ +/* counterclockwise() Return a positive value if the points pa, pb, and */ +/* pc occur in counterclockwise order; a negative */ +/* value if they occur in clockwise order; and zero */ +/* if they are collinear. The result is also a rough */ +/* approximation of twice the signed area of the */ +/* triangle defined by the three points. */ +/* */ +/* Uses exact arithmetic if necessary to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. This determinant is */ +/* computed adaptively, in the sense that exact arithmetic is used only to */ +/* the degree it is needed to ensure that the returned value has the */ +/* correct sign. Hence, this function is usually quite fast, but will run */ +/* more slowly when the input points are collinear or nearly so. */ +/* */ +/* See my Robust Predicates paper for details. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum) +#else /* not ANSI_DECLARATORS */ +REAL counterclockwiseadapt(pa, pb, pc, detsum) +vertex pa; +vertex pb; +vertex pc; +REAL detsum; +#endif /* not ANSI_DECLARATORS */ + +{ + INEXACT REAL acx, acy, bcx, bcy; + REAL acxtail, acytail, bcxtail, bcytail; + INEXACT REAL detleft, detright; + REAL detlefttail, detrighttail; + REAL det, errbound; + REAL B[4], C1[8], C2[12], D[16]; + INEXACT REAL B3; + int C1length, C2length, Dlength; + REAL u[4]; + INEXACT REAL u3; + INEXACT REAL s1, t1; + REAL s0, t0; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + acx = (REAL) (pa[0] - pc[0]); + bcx = (REAL) (pb[0] - pc[0]); + acy = (REAL) (pa[1] - pc[1]); + bcy = (REAL) (pb[1] - pc[1]); + + Two_Product(acx, bcy, detleft, detlefttail); + Two_Product(acy, bcx, detright, detrighttail); + + Two_Two_Diff(detleft, detlefttail, detright, detrighttail, + B3, B[2], B[1], B[0]); + B[3] = B3; + + det = estimate(4, B); + errbound = ccwerrboundB * detsum; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pc[0], acx, acxtail); + Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail); + Two_Diff_Tail(pa[1], pc[1], acy, acytail); + Two_Diff_Tail(pb[1], pc[1], bcy, bcytail); + + if ((acxtail == 0.0) && (acytail == 0.0) + && (bcxtail == 0.0) && (bcytail == 0.0)) { + return det; + } + + errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det); + det += (acx * bcytail + bcy * acxtail) + - (acy * bcxtail + bcx * acytail); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Product(acxtail, bcy, s1, s0); + Two_Product(acytail, bcx, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1); + + Two_Product(acx, bcytail, s1, s0); + Two_Product(acy, bcxtail, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2); + + Two_Product(acxtail, bcytail, s1, s0); + Two_Product(acytail, bcxtail, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D); + + return(D[Dlength - 1]); +} + +#ifdef ANSI_DECLARATORS +REAL counterclockwise(struct mesh *m, struct behavior *b, + vertex pa, vertex pb, vertex pc) +#else /* not ANSI_DECLARATORS */ +REAL counterclockwise(m, b, pa, pb, pc) +struct mesh *m; +struct behavior *b; +vertex pa; +vertex pb; +vertex pc; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL detleft, detright, det; + REAL detsum, errbound; + + m->counterclockcount++; + + detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]); + detright = (pa[1] - pc[1]) * (pb[0] - pc[0]); + det = detleft - detright; + + if (b->noexact) { + return det; + } + + if (detleft > 0.0) { + if (detright <= 0.0) { + return det; + } else { + detsum = detleft + detright; + } + } else if (detleft < 0.0) { + if (detright >= 0.0) { + return det; + } else { + detsum = -detleft - detright; + } + } else { + return det; + } + + errbound = ccwerrboundA * detsum; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + return counterclockwiseadapt(pa, pb, pc, detsum); +} + +/*****************************************************************************/ +/* */ +/* incircle() Return a positive value if the point pd lies inside the */ +/* circle passing through pa, pb, and pc; a negative value if */ +/* it lies outside; and zero if the four points are cocircular.*/ +/* The points pa, pb, and pc must be in counterclockwise */ +/* order, or the sign of the result will be reversed. */ +/* */ +/* Uses exact arithmetic if necessary to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. This determinant is */ +/* computed adaptively, in the sense that exact arithmetic is used only to */ +/* the degree it is needed to ensure that the returned value has the */ +/* correct sign. Hence, this function is usually quite fast, but will run */ +/* more slowly when the input points are cocircular or nearly so. */ +/* */ +/* See my Robust Predicates paper for details. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent) +#else /* not ANSI_DECLARATORS */ +REAL incircleadapt(pa, pb, pc, pd, permanent) +vertex pa; +vertex pb; +vertex pc; +vertex pd; +REAL permanent; +#endif /* not ANSI_DECLARATORS */ + +{ + INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; + REAL det, errbound; + + INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; + REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; + REAL bc[4], ca[4], ab[4]; + INEXACT REAL bc3, ca3, ab3; + REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32]; + int axbclen, axxbclen, aybclen, ayybclen, alen; + REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32]; + int bxcalen, bxxcalen, bycalen, byycalen, blen; + REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32]; + int cxablen, cxxablen, cyablen, cyyablen, clen; + REAL abdet[64]; + int ablen; + REAL fin1[1152], fin2[1152]; + REAL *finnow, *finother, *finswap; + int finlength; + + REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail; + INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1; + REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0; + REAL aa[4], bb[4], cc[4]; + INEXACT REAL aa3, bb3, cc3; + INEXACT REAL ti1, tj1; + REAL ti0, tj0; + REAL u[4], v[4]; + INEXACT REAL u3, v3; + REAL temp8[8], temp16a[16], temp16b[16], temp16c[16]; + REAL temp32a[32], temp32b[32], temp48[48], temp64[64]; + int temp8len, temp16alen, temp16blen, temp16clen; + int temp32alen, temp32blen, temp48len, temp64len; + REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8]; + int axtbblen, axtcclen, aytbblen, aytcclen; + REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8]; + int bxtaalen, bxtcclen, bytaalen, bytcclen; + REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; + int cxtaalen, cxtbblen, cytaalen, cytbblen; + REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; + int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen; + REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; + int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; + REAL axtbctt[8], aytbctt[8], bxtcatt[8]; + REAL bytcatt[8], cxtabtt[8], cytabtt[8]; + int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen; + REAL abt[8], bct[8], cat[8]; + int abtlen, bctlen, catlen; + REAL abtt[4], bctt[4], catt[4]; + int abttlen, bcttlen, cattlen; + INEXACT REAL abtt3, bctt3, catt3; + REAL negate; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + adx = (REAL) (pa[0] - pd[0]); + bdx = (REAL) (pb[0] - pd[0]); + cdx = (REAL) (pc[0] - pd[0]); + ady = (REAL) (pa[1] - pd[1]); + bdy = (REAL) (pb[1] - pd[1]); + cdy = (REAL) (pc[1] - pd[1]); + + Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); + Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); + Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + axbclen = scale_expansion_zeroelim(4, bc, adx, axbc); + axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc); + aybclen = scale_expansion_zeroelim(4, bc, ady, aybc); + ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc); + alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet); + + Two_Product(cdx, ady, cdxady1, cdxady0); + Two_Product(adx, cdy, adxcdy1, adxcdy0); + Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); + ca[3] = ca3; + bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca); + bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca); + bycalen = scale_expansion_zeroelim(4, ca, bdy, byca); + byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca); + blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet); + + Two_Product(adx, bdy, adxbdy1, adxbdy0); + Two_Product(bdx, ady, bdxady1, bdxady0); + Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab); + cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab); + cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab); + cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab); + clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); + + det = estimate(finlength, fin1); + errbound = iccerrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pd[0], adx, adxtail); + Two_Diff_Tail(pa[1], pd[1], ady, adytail); + Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); + Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); + Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); + Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); + if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) + && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) { + return det; + } + + errbound = iccerrboundC * permanent + resulterrbound * Absolute(det); + det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) + - (bdy * cdxtail + cdx * bdytail)) + + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) + + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) + - (cdy * adxtail + adx * cdytail)) + + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) + + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) + - (ady * bdxtail + bdx * adytail)) + + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx)); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + finnow = fin1; + finother = fin2; + + if ((bdxtail != 0.0) || (bdytail != 0.0) + || (cdxtail != 0.0) || (cdytail != 0.0)) { + Square(adx, adxadx1, adxadx0); + Square(ady, adyady1, adyady0); + Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]); + aa[3] = aa3; + } + if ((cdxtail != 0.0) || (cdytail != 0.0) + || (adxtail != 0.0) || (adytail != 0.0)) { + Square(bdx, bdxbdx1, bdxbdx0); + Square(bdy, bdybdy1, bdybdy0); + Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]); + bb[3] = bb3; + } + if ((adxtail != 0.0) || (adytail != 0.0) + || (bdxtail != 0.0) || (bdytail != 0.0)) { + Square(cdx, cdxcdx1, cdxcdx0); + Square(cdy, cdycdy1, cdycdy0); + Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]); + cc[3] = cc3; + } + + if (adxtail != 0.0) { + axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc); + temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx, + temp16a); + + axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc); + temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b); + + axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb); + temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc); + temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady, + temp16a); + + aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb); + temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b); + + aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc); + temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdxtail != 0.0) { + bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca); + temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx, + temp16a); + + bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa); + temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b); + + bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc); + temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca); + temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy, + temp16a); + + bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc); + temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b); + + bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa); + temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdxtail != 0.0) { + cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab); + temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx, + temp16a); + + cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb); + temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b); + + cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa); + temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab); + temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy, + temp16a); + + cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa); + temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b); + + cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb); + temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + if ((adxtail != 0.0) || (adytail != 0.0)) { + if ((bdxtail != 0.0) || (bdytail != 0.0) + || (cdxtail != 0.0) || (cdytail != 0.0)) { + Two_Product(bdxtail, cdy, ti1, ti0); + Two_Product(bdx, cdytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -bdy; + Two_Product(cdxtail, negate, ti1, ti0); + negate = -bdytail; + Two_Product(cdx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct); + + Two_Product(bdxtail, cdytail, ti1, ti0); + Two_Product(cdxtail, bdytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]); + bctt[3] = bctt3; + bcttlen = 4; + } else { + bct[0] = 0.0; + bctlen = 1; + bctt[0] = 0.0; + bcttlen = 1; + } + + if (adxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a); + axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct); + temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail, + temp32a); + axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt); + temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx, + temp16a); + temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a); + aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct); + temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail, + temp32a); + aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt); + temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady, + temp16a); + temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if ((bdxtail != 0.0) || (bdytail != 0.0)) { + if ((cdxtail != 0.0) || (cdytail != 0.0) + || (adxtail != 0.0) || (adytail != 0.0)) { + Two_Product(cdxtail, ady, ti1, ti0); + Two_Product(cdx, adytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -cdy; + Two_Product(adxtail, negate, ti1, ti0); + negate = -cdytail; + Two_Product(adx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat); + + Two_Product(cdxtail, adytail, ti1, ti0); + Two_Product(adxtail, cdytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]); + catt[3] = catt3; + cattlen = 4; + } else { + cat[0] = 0.0; + catlen = 1; + catt[0] = 0.0; + cattlen = 1; + } + + if (bdxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a); + bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat); + temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail, + temp32a); + bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt); + temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx, + temp16a); + temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a); + bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat); + temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail, + temp32a); + bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt); + temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy, + temp16a); + temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if ((cdxtail != 0.0) || (cdytail != 0.0)) { + if ((adxtail != 0.0) || (adytail != 0.0) + || (bdxtail != 0.0) || (bdytail != 0.0)) { + Two_Product(adxtail, bdy, ti1, ti0); + Two_Product(adx, bdytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -ady; + Two_Product(bdxtail, negate, ti1, ti0); + negate = -adytail; + Two_Product(bdx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt); + + Two_Product(adxtail, bdytail, ti1, ti0); + Two_Product(bdxtail, adytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]); + abtt[3] = abtt3; + abttlen = 4; + } else { + abt[0] = 0.0; + abtlen = 1; + abtt[0] = 0.0; + abttlen = 1; + } + + if (cdxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a); + cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt); + temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail, + temp32a); + cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt); + temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx, + temp16a); + temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a); + cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt); + temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail, + temp32a); + cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt); + temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy, + temp16a); + temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + + return finnow[finlength - 1]; +} + +#ifdef ANSI_DECLARATORS +REAL incircle(struct mesh *m, struct behavior *b, + vertex pa, vertex pb, vertex pc, vertex pd) +#else /* not ANSI_DECLARATORS */ +REAL incircle(m, b, pa, pb, pc, pd) +struct mesh *m; +struct behavior *b; +vertex pa; +vertex pb; +vertex pc; +vertex pd; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL adx, bdx, cdx, ady, bdy, cdy; + REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; + REAL alift, blift, clift; + REAL det; + REAL permanent, errbound; + + m->incirclecount++; + + adx = pa[0] - pd[0]; + bdx = pb[0] - pd[0]; + cdx = pc[0] - pd[0]; + ady = pa[1] - pd[1]; + bdy = pb[1] - pd[1]; + cdy = pc[1] - pd[1]; + + bdxcdy = bdx * cdy; + cdxbdy = cdx * bdy; + alift = adx * adx + ady * ady; + + cdxady = cdx * ady; + adxcdy = adx * cdy; + blift = bdx * bdx + bdy * bdy; + + adxbdy = adx * bdy; + bdxady = bdx * ady; + clift = cdx * cdx + cdy * cdy; + + det = alift * (bdxcdy - cdxbdy) + + blift * (cdxady - adxcdy) + + clift * (adxbdy - bdxady); + + if (b->noexact) { + return det; + } + + permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift + + (Absolute(cdxady) + Absolute(adxcdy)) * blift + + (Absolute(adxbdy) + Absolute(bdxady)) * clift; + errbound = iccerrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return incircleadapt(pa, pb, pc, pd, permanent); +} + +/*****************************************************************************/ +/* */ +/* orient3d() Return a positive value if the point pd lies below the */ +/* plane passing through pa, pb, and pc; "below" is defined so */ +/* that pa, pb, and pc appear in counterclockwise order when */ +/* viewed from above the plane. Returns a negative value if */ +/* pd lies above the plane. Returns zero if the points are */ +/* coplanar. The result is also a rough approximation of six */ +/* times the signed volume of the tetrahedron defined by the */ +/* four points. */ +/* */ +/* Uses exact arithmetic if necessary to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. This determinant is */ +/* computed adaptively, in the sense that exact arithmetic is used only to */ +/* the degree it is needed to ensure that the returned value has the */ +/* correct sign. Hence, this function is usually quite fast, but will run */ +/* more slowly when the input points are coplanar or nearly so. */ +/* */ +/* See my Robust Predicates paper for details. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, + REAL aheight, REAL bheight, REAL cheight, REAL dheight, + REAL permanent) +#else /* not ANSI_DECLARATORS */ +REAL orient3dadapt(pa, pb, pc, pd, + aheight, bheight, cheight, dheight, permanent) +vertex pa; +vertex pb; +vertex pc; +vertex pd; +REAL aheight; +REAL bheight; +REAL cheight; +REAL dheight; +REAL permanent; +#endif /* not ANSI_DECLARATORS */ + +{ + INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight; + REAL det, errbound; + + INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; + REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; + REAL bc[4], ca[4], ab[4]; + INEXACT REAL bc3, ca3, ab3; + REAL adet[8], bdet[8], cdet[8]; + int alen, blen, clen; + REAL abdet[16]; + int ablen; + REAL *finnow, *finother, *finswap; + REAL fin1[192], fin2[192]; + int finlength; + + REAL adxtail, bdxtail, cdxtail; + REAL adytail, bdytail, cdytail; + REAL adheighttail, bdheighttail, cdheighttail; + INEXACT REAL at_blarge, at_clarge; + INEXACT REAL bt_clarge, bt_alarge; + INEXACT REAL ct_alarge, ct_blarge; + REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4]; + int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen; + INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1; + INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1; + REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0; + REAL adxt_cdy0, adxt_bdy0, bdxt_ady0; + INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1; + INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1; + REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0; + REAL adyt_cdx0, adyt_bdx0, bdyt_adx0; + REAL bct[8], cat[8], abt[8]; + int bctlen, catlen, abtlen; + INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1; + INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1; + REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0; + REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0; + REAL u[4], v[12], w[16]; + INEXACT REAL u3; + int vlength, wlength; + REAL negate; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k; + REAL _0; + + adx = (REAL) (pa[0] - pd[0]); + bdx = (REAL) (pb[0] - pd[0]); + cdx = (REAL) (pc[0] - pd[0]); + ady = (REAL) (pa[1] - pd[1]); + bdy = (REAL) (pb[1] - pd[1]); + cdy = (REAL) (pc[1] - pd[1]); + adheight = (REAL) (aheight - dheight); + bdheight = (REAL) (bheight - dheight); + cdheight = (REAL) (cheight - dheight); + + Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); + Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); + Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + alen = scale_expansion_zeroelim(4, bc, adheight, adet); + + Two_Product(cdx, ady, cdxady1, cdxady0); + Two_Product(adx, cdy, adxcdy1, adxcdy0); + Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); + ca[3] = ca3; + blen = scale_expansion_zeroelim(4, ca, bdheight, bdet); + + Two_Product(adx, bdy, adxbdy1, adxbdy0); + Two_Product(bdx, ady, bdxady1, bdxady0); + Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + clen = scale_expansion_zeroelim(4, ab, cdheight, cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); + + det = estimate(finlength, fin1); + errbound = o3derrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pd[0], adx, adxtail); + Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); + Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); + Two_Diff_Tail(pa[1], pd[1], ady, adytail); + Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); + Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); + Two_Diff_Tail(aheight, dheight, adheight, adheighttail); + Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail); + Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail); + + if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) && + (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) && + (adheighttail == 0.0) && + (bdheighttail == 0.0) && + (cdheighttail == 0.0)) { + return det; + } + + errbound = o3derrboundC * permanent + resulterrbound * Absolute(det); + det += (adheight * ((bdx * cdytail + cdy * bdxtail) - + (bdy * cdxtail + cdx * bdytail)) + + adheighttail * (bdx * cdy - bdy * cdx)) + + (bdheight * ((cdx * adytail + ady * cdxtail) - + (cdy * adxtail + adx * cdytail)) + + bdheighttail * (cdx * ady - cdy * adx)) + + (cdheight * ((adx * bdytail + bdy * adxtail) - + (ady * bdxtail + bdx * adytail)) + + cdheighttail * (adx * bdy - ady * bdx)); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + finnow = fin1; + finother = fin2; + + if (adxtail == 0.0) { + if (adytail == 0.0) { + at_b[0] = 0.0; + at_blen = 1; + at_c[0] = 0.0; + at_clen = 1; + } else { + negate = -adytail; + Two_Product(negate, bdx, at_blarge, at_b[0]); + at_b[1] = at_blarge; + at_blen = 2; + Two_Product(adytail, cdx, at_clarge, at_c[0]); + at_c[1] = at_clarge; + at_clen = 2; + } + } else { + if (adytail == 0.0) { + Two_Product(adxtail, bdy, at_blarge, at_b[0]); + at_b[1] = at_blarge; + at_blen = 2; + negate = -adxtail; + Two_Product(negate, cdy, at_clarge, at_c[0]); + at_c[1] = at_clarge; + at_clen = 2; + } else { + Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0); + Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0); + Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0, + at_blarge, at_b[2], at_b[1], at_b[0]); + at_b[3] = at_blarge; + at_blen = 4; + Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0); + Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0); + Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0, + at_clarge, at_c[2], at_c[1], at_c[0]); + at_c[3] = at_clarge; + at_clen = 4; + } + } + if (bdxtail == 0.0) { + if (bdytail == 0.0) { + bt_c[0] = 0.0; + bt_clen = 1; + bt_a[0] = 0.0; + bt_alen = 1; + } else { + negate = -bdytail; + Two_Product(negate, cdx, bt_clarge, bt_c[0]); + bt_c[1] = bt_clarge; + bt_clen = 2; + Two_Product(bdytail, adx, bt_alarge, bt_a[0]); + bt_a[1] = bt_alarge; + bt_alen = 2; + } + } else { + if (bdytail == 0.0) { + Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]); + bt_c[1] = bt_clarge; + bt_clen = 2; + negate = -bdxtail; + Two_Product(negate, ady, bt_alarge, bt_a[0]); + bt_a[1] = bt_alarge; + bt_alen = 2; + } else { + Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0); + Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0); + Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0, + bt_clarge, bt_c[2], bt_c[1], bt_c[0]); + bt_c[3] = bt_clarge; + bt_clen = 4; + Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0); + Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0); + Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0, + bt_alarge, bt_a[2], bt_a[1], bt_a[0]); + bt_a[3] = bt_alarge; + bt_alen = 4; + } + } + if (cdxtail == 0.0) { + if (cdytail == 0.0) { + ct_a[0] = 0.0; + ct_alen = 1; + ct_b[0] = 0.0; + ct_blen = 1; + } else { + negate = -cdytail; + Two_Product(negate, adx, ct_alarge, ct_a[0]); + ct_a[1] = ct_alarge; + ct_alen = 2; + Two_Product(cdytail, bdx, ct_blarge, ct_b[0]); + ct_b[1] = ct_blarge; + ct_blen = 2; + } + } else { + if (cdytail == 0.0) { + Two_Product(cdxtail, ady, ct_alarge, ct_a[0]); + ct_a[1] = ct_alarge; + ct_alen = 2; + negate = -cdxtail; + Two_Product(negate, bdy, ct_blarge, ct_b[0]); + ct_b[1] = ct_blarge; + ct_blen = 2; + } else { + Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0); + Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0); + Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0, + ct_alarge, ct_a[2], ct_a[1], ct_a[0]); + ct_a[3] = ct_alarge; + ct_alen = 4; + Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0); + Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0); + Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0, + ct_blarge, ct_b[2], ct_b[1], ct_b[0]); + ct_b[3] = ct_blarge; + ct_blen = 4; + } + } + + bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct); + wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat); + wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt); + wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + if (adheighttail != 0.0) { + vlength = scale_expansion_zeroelim(4, bc, adheighttail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdheighttail != 0.0) { + vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdheighttail != 0.0) { + vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + if (adxtail != 0.0) { + if (bdytail != 0.0) { + Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0); + Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdheighttail != 0.0) { + Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (cdytail != 0.0) { + negate = -adxtail; + Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0); + Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdheighttail != 0.0) { + Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + if (bdxtail != 0.0) { + if (cdytail != 0.0) { + Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0); + Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adheighttail != 0.0) { + Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (adytail != 0.0) { + negate = -bdxtail; + Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0); + Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdheighttail != 0.0) { + Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + if (cdxtail != 0.0) { + if (adytail != 0.0) { + Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0); + Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdheighttail != 0.0) { + Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (bdytail != 0.0) { + negate = -cdxtail; + Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0); + Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adheighttail != 0.0) { + Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail, + u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + + if (adheighttail != 0.0) { + wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdheighttail != 0.0) { + wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdheighttail != 0.0) { + wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + return finnow[finlength - 1]; +} + +#ifdef ANSI_DECLARATORS +REAL orient3d(struct mesh *m, struct behavior *b, + vertex pa, vertex pb, vertex pc, vertex pd, + REAL aheight, REAL bheight, REAL cheight, REAL dheight) +#else /* not ANSI_DECLARATORS */ +REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight) +struct mesh *m; +struct behavior *b; +vertex pa; +vertex pb; +vertex pc; +vertex pd; +REAL aheight; +REAL bheight; +REAL cheight; +REAL dheight; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight; + REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; + REAL det; + REAL permanent, errbound; + + m->orient3dcount++; + + adx = pa[0] - pd[0]; + bdx = pb[0] - pd[0]; + cdx = pc[0] - pd[0]; + ady = pa[1] - pd[1]; + bdy = pb[1] - pd[1]; + cdy = pc[1] - pd[1]; + adheight = aheight - dheight; + bdheight = bheight - dheight; + cdheight = cheight - dheight; + + bdxcdy = bdx * cdy; + cdxbdy = cdx * bdy; + + cdxady = cdx * ady; + adxcdy = adx * cdy; + + adxbdy = adx * bdy; + bdxady = bdx * ady; + + det = adheight * (bdxcdy - cdxbdy) + + bdheight * (cdxady - adxcdy) + + cdheight * (adxbdy - bdxady); + + if (b->noexact) { + return det; + } + + permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight) + + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight) + + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight); + errbound = o3derrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight, + permanent); +} + +/*****************************************************************************/ +/* */ +/* nonregular() Return a positive value if the point pd is incompatible */ +/* with the circle or plane passing through pa, pb, and pc */ +/* (meaning that pd is inside the circle or below the */ +/* plane); a negative value if it is compatible; and zero if */ +/* the four points are cocircular/coplanar. The points pa, */ +/* pb, and pc must be in counterclockwise order, or the sign */ +/* of the result will be reversed. */ +/* */ +/* If the -w switch is used, the points are lifted onto the parabolic */ +/* lifting map, then they are dropped according to their weights, then the */ +/* 3D orientation test is applied. If the -W switch is used, the points' */ +/* heights are already provided, so the 3D orientation test is applied */ +/* directly. If neither switch is used, the incircle test is applied. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +REAL nonregular(struct mesh *m, struct behavior *b, + vertex pa, vertex pb, vertex pc, vertex pd) +#else /* not ANSI_DECLARATORS */ +REAL nonregular(m, b, pa, pb, pc, pd) +struct mesh *m; +struct behavior *b; +vertex pa; +vertex pb; +vertex pc; +vertex pd; +#endif /* not ANSI_DECLARATORS */ + +{ + if (b->weighted == 0) { + return incircle(m, b, pa, pb, pc, pd); + } else if (b->weighted == 1) { + return orient3d(m, b, pa, pb, pc, pd, + pa[0] * pa[0] + pa[1] * pa[1] - pa[2], + pb[0] * pb[0] + pb[1] * pb[1] - pb[2], + pc[0] * pc[0] + pc[1] * pc[1] - pc[2], + pd[0] * pd[0] + pd[1] * pd[1] - pd[2]); + } else { + return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]); + } +} + +/*****************************************************************************/ +/* */ +/* findcircumcenter() Find the circumcenter of a triangle. */ +/* */ +/* The result is returned both in terms of x-y coordinates and xi-eta */ +/* (barycentric) coordinates. The xi-eta coordinate system is defined in */ +/* terms of the triangle: the origin of the triangle is the origin of the */ +/* coordinate system; the destination of the triangle is one unit along the */ +/* xi axis; and the apex of the triangle is one unit along the eta axis. */ +/* This procedure also returns the square of the length of the triangle's */ +/* shortest edge. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void findcircumcenter(struct mesh *m, struct behavior *b, + vertex torg, vertex tdest, vertex tapex, + vertex circumcenter, REAL *xi, REAL *eta, int offcenter) +#else /* not ANSI_DECLARATORS */ +void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta, + offcenter) +struct mesh *m; +struct behavior *b; +vertex torg; +vertex tdest; +vertex tapex; +vertex circumcenter; +REAL *xi; +REAL *eta; +int offcenter; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL xdo, ydo, xao, yao; + REAL dodist, aodist, dadist; + REAL denominator; + REAL dx, dy, dxoff, dyoff; + + m->circumcentercount++; + + /* Compute the circumcenter of the triangle. */ + xdo = tdest[0] - torg[0]; + ydo = tdest[1] - torg[1]; + xao = tapex[0] - torg[0]; + yao = tapex[1] - torg[1]; + dodist = xdo * xdo + ydo * ydo; + aodist = xao * xao + yao * yao; + dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) + + (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]); + if (b->noexact) { + denominator = 0.5 / (xdo * yao - xao * ydo); + } else { + /* Use the counterclockwise() routine to ensure a positive (and */ + /* reasonably accurate) result, avoiding any possibility of */ + /* division by zero. */ + denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg); + /* Don't count the above as an orientation test. */ + m->counterclockcount--; + } + dx = (yao * dodist - ydo * aodist) * denominator; + dy = (xdo * aodist - xao * dodist) * denominator; + + /* Find the (squared) length of the triangle's shortest edge. This */ + /* serves as a conservative estimate of the insertion radius of the */ + /* circumcenter's parent. The estimate is used to ensure that */ + /* the algorithm terminates even if very small angles appear in */ + /* the input PSLG. */ + if ((dodist < aodist) && (dodist < dadist)) { + if (offcenter && (b->offconstant > 0.0)) { + /* Find the position of the off-center, as described by Alper Ungor. */ + dxoff = 0.5 * xdo - b->offconstant * ydo; + dyoff = 0.5 * ydo + b->offconstant * xdo; + /* If the off-center is closer to the origin than the */ + /* circumcenter, use the off-center instead. */ + if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) { + dx = dxoff; + dy = dyoff; + } + } + } else if (aodist < dadist) { + if (offcenter && (b->offconstant > 0.0)) { + dxoff = 0.5 * xao + b->offconstant * yao; + dyoff = 0.5 * yao - b->offconstant * xao; + /* If the off-center is closer to the origin than the */ + /* circumcenter, use the off-center instead. */ + if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) { + dx = dxoff; + dy = dyoff; + } + } + } else { + if (offcenter && (b->offconstant > 0.0)) { + dxoff = 0.5 * (tapex[0] - tdest[0]) - + b->offconstant * (tapex[1] - tdest[1]); + dyoff = 0.5 * (tapex[1] - tdest[1]) + + b->offconstant * (tapex[0] - tdest[0]); + /* If the off-center is closer to the destination than the */ + /* circumcenter, use the off-center instead. */ + if (dxoff * dxoff + dyoff * dyoff < + (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) { + dx = xdo + dxoff; + dy = ydo + dyoff; + } + } + } + + circumcenter[0] = torg[0] + dx; + circumcenter[1] = torg[1] + dy; + + /* To interpolate vertex attributes for the new vertex inserted at */ + /* the circumcenter, define a coordinate system with a xi-axis, */ + /* directed from the triangle's origin to its destination, and */ + /* an eta-axis, directed from its origin to its apex. */ + /* Calculate the xi and eta coordinates of the circumcenter. */ + *xi = (yao * dx - xao * dy) * (2.0 * denominator); + *eta = (xdo * dy - ydo * dx) * (2.0 * denominator); +} + +/** **/ +/** **/ +/********* Geometric primitives end here *********/ + +/*****************************************************************************/ +/* */ +/* triangleinit() Initialize some variables. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void triangleinit(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +void triangleinit(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + poolzero(&m->vertices); + poolzero(&m->triangles); + poolzero(&m->subsegs); + poolzero(&m->viri); + poolzero(&m->badsubsegs); + poolzero(&m->badtriangles); + poolzero(&m->flipstackers); + poolzero(&m->splaynodes); + + m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */ + m->undeads = 0; /* No eliminated input vertices yet. */ + m->samples = 1; /* Point location should take at least one sample. */ + m->checksegments = 0; /* There are no segments in the triangulation yet. */ + m->checkquality = 0; /* The quality triangulation stage has not begun. */ + m->incirclecount = m->counterclockcount = m->orient3dcount = 0; + m->hyperbolacount = m->circletopcount = m->circumcentercount = 0; + randomseed = 1; + + exactinit(); /* Initialize exact arithmetic constants. */ +} + +/*****************************************************************************/ +/* */ +/* randomnation() Generate a random number between 0 and `choices' - 1. */ +/* */ +/* This is a simple linear congruential random number generator. Hence, it */ +/* is a bad random number generator, but good enough for most randomized */ +/* geometric algorithms. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +unsigned long randomnation(unsigned int choices) +#else /* not ANSI_DECLARATORS */ +unsigned long randomnation(choices) +unsigned int choices; +#endif /* not ANSI_DECLARATORS */ + +{ + randomseed = (randomseed * 1366l + 150889l) % 714025l; + return randomseed / (714025l / choices + 1); +} + +/********* Mesh quality testing routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* checkmesh() Test the mesh for topological consistency. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void checkmesh(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void checkmesh(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop; + struct otri oppotri, oppooppotri; + vertex triorg, tridest, triapex; + vertex oppoorg, oppodest; + int horrors; + int saveexact; + triangle ptr; /* Temporary variable used by sym(). */ + + /* Temporarily turn on exact arithmetic if it's off. */ + saveexact = b->noexact; + b->noexact = 0; + if (!b->quiet) { + printf(" Checking consistency of mesh...\n"); + } + horrors = 0; + /* Run through the list of triangles, checking each one. */ + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + while (triangleloop.tri != (triangle *) NULL) { + /* Check all three edges of the triangle. */ + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + org(triangleloop, triorg); + dest(triangleloop, tridest); + if (triangleloop.orient == 0) { /* Only test for inversion once. */ + /* Test if the triangle is flat or inverted. */ + apex(triangleloop, triapex); + if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) { + printf(" !! !! Inverted "); + printtriangle(m, b, &triangleloop); + horrors++; + } + } + /* Find the neighboring triangle on this edge. */ + sym(triangleloop, oppotri); + if (oppotri.tri != m->dummytri) { + /* Check that the triangle's neighbor knows it's a neighbor. */ + sym(oppotri, oppooppotri); + if ((triangleloop.tri != oppooppotri.tri) + || (triangleloop.orient != oppooppotri.orient)) { + printf(" !! !! Asymmetric triangle-triangle bond:\n"); + if (triangleloop.tri == oppooppotri.tri) { + printf(" (Right triangle, wrong orientation)\n"); + } + printf(" First "); + printtriangle(m, b, &triangleloop); + printf(" Second (nonreciprocating) "); + printtriangle(m, b, &oppotri); + horrors++; + } + /* Check that both triangles agree on the identities */ + /* of their shared vertices. */ + org(oppotri, oppoorg); + dest(oppotri, oppodest); + if ((triorg != oppodest) || (tridest != oppoorg)) { + printf(" !! !! Mismatched edge coordinates between two triangles:\n" + ); + printf(" First mismatched "); + printtriangle(m, b, &triangleloop); + printf(" Second mismatched "); + printtriangle(m, b, &oppotri); + horrors++; + } + } + } + triangleloop.tri = triangletraverse(m); + } + if (horrors == 0) { + if (!b->quiet) { + printf(" In my studied opinion, the mesh appears to be consistent.\n"); + } + } else if (horrors == 1) { + printf(" !! !! !! !! Precisely one festering wound discovered.\n"); + } else { + printf(" !! !! !! !! %d abominations witnessed.\n", horrors); + } + /* Restore the status of exact arithmetic. */ + b->noexact = saveexact; +} + +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void checkdelaunay(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void checkdelaunay(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop; + struct otri oppotri; + struct osub opposubseg; + vertex triorg, tridest, triapex; + vertex oppoapex; + int shouldbedelaunay; + int horrors; + int saveexact; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + /* Temporarily turn on exact arithmetic if it's off. */ + saveexact = b->noexact; + b->noexact = 0; + if (!b->quiet) { + printf(" Checking Delaunay property of mesh...\n"); + } + horrors = 0; + /* Run through the list of triangles, checking each one. */ + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + while (triangleloop.tri != (triangle *) NULL) { + /* Check all three edges of the triangle. */ + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + org(triangleloop, triorg); + dest(triangleloop, tridest); + apex(triangleloop, triapex); + sym(triangleloop, oppotri); + apex(oppotri, oppoapex); + /* Only test that the edge is locally Delaunay if there is an */ + /* adjoining triangle whose pointer is larger (to ensure that */ + /* each pair isn't tested twice). */ + shouldbedelaunay = (oppotri.tri != m->dummytri) && + !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) && + (triorg != m->infvertex1) && (triorg != m->infvertex2) && + (triorg != m->infvertex3) && + (tridest != m->infvertex1) && (tridest != m->infvertex2) && + (tridest != m->infvertex3) && + (triapex != m->infvertex1) && (triapex != m->infvertex2) && + (triapex != m->infvertex3) && + (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) && + (oppoapex != m->infvertex3); + if (m->checksegments && shouldbedelaunay) { + /* If a subsegment separates the triangles, then the edge is */ + /* constrained, so no local Delaunay test should be done. */ + tspivot(triangleloop, opposubseg); + if (opposubseg.ss != m->dummysub){ + shouldbedelaunay = 0; + } + } + if (shouldbedelaunay) { + if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) { + if (!b->weighted) { + printf(" !! !! Non-Delaunay pair of triangles:\n"); + printf(" First non-Delaunay "); + printtriangle(m, b, &triangleloop); + printf(" Second non-Delaunay "); + } else { + printf(" !! !! Non-regular pair of triangles:\n"); + printf(" First non-regular "); + printtriangle(m, b, &triangleloop); + printf(" Second non-regular "); + } + printtriangle(m, b, &oppotri); + horrors++; + } + } + } + triangleloop.tri = triangletraverse(m); + } + if (horrors == 0) { + if (!b->quiet) { + printf( + " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n"); + } + } else if (horrors == 1) { + printf( + " !! !! !! !! Precisely one terrifying transgression identified.\n"); + } else { + printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors); + } + /* Restore the status of exact arithmetic. */ + b->noexact = saveexact; +} + +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* enqueuebadtriang() Add a bad triangle data structure to the end of a */ +/* queue. */ +/* */ +/* The queue is actually a set of 4096 queues. I use multiple queues to */ +/* give priority to smaller angles. I originally implemented a heap, but */ +/* the queues are faster by a larger margin than I'd suspected. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void enqueuebadtriang(struct mesh *m, struct behavior *b, + struct badtriang *badtri) +#else /* not ANSI_DECLARATORS */ +void enqueuebadtriang(m, b, badtri) +struct mesh *m; +struct behavior *b; +struct badtriang *badtri; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL length, multiplier; + int exponent, expincrement; + int queuenumber; + int posexponent; + int i; + + if (b->verbose > 2) { + printf(" Queueing bad triangle:\n"); + printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + badtri->triangorg[0], badtri->triangorg[1], + badtri->triangdest[0], badtri->triangdest[1], + badtri->triangapex[0], badtri->triangapex[1]); + } + + /* Determine the appropriate queue to put the bad triangle into. */ + /* Recall that the key is the square of its shortest edge length. */ + if (badtri->key >= 1.0) { + length = badtri->key; + posexponent = 1; + } else { + /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */ + /* fact and use the reciprocal of `badtri->key', which is > 1.0. */ + length = 1.0 / badtri->key; + posexponent = 0; + } + /* `length' is approximately 2.0 to what exponent? The following code */ + /* determines the answer in time logarithmic in the exponent. */ + exponent = 0; + while (length > 2.0) { + /* Find an approximation by repeated squaring of two. */ + expincrement = 1; + multiplier = 0.5; + while (length * multiplier * multiplier > 1.0) { + expincrement *= 2; + multiplier *= multiplier; + } + /* Reduce the value of `length', then iterate if necessary. */ + exponent += expincrement; + length *= multiplier; + } + /* `length' is approximately squareroot(2.0) to what exponent? */ + exponent = 2.0 * exponent + (length > SQUAREROOTTWO); + /* `exponent' is now in the range 0...2047 for IEEE double precision. */ + /* Choose a queue in the range 0...4095. The shortest edges have the */ + /* highest priority (queue 4095). */ + if (posexponent) { + queuenumber = 2047 - exponent; + } else { + queuenumber = 2048 + exponent; + } + + /* Are we inserting into an empty queue? */ + if (m->queuefront[queuenumber] == (struct badtriang *) NULL) { + /* Yes, we are inserting into an empty queue. */ + /* Will this become the highest-priority queue? */ + if (queuenumber > m->firstnonemptyq) { + /* Yes, this is the highest-priority queue. */ + m->nextnonemptyq[queuenumber] = m->firstnonemptyq; + m->firstnonemptyq = queuenumber; + } else { + /* No, this is not the highest-priority queue. */ + /* Find the queue with next higher priority. */ + i = queuenumber + 1; + while (m->queuefront[i] == (struct badtriang *) NULL) { + i++; + } + /* Mark the newly nonempty queue as following a higher-priority queue. */ + m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i]; + m->nextnonemptyq[i] = queuenumber; + } + /* Put the bad triangle at the beginning of the (empty) queue. */ + m->queuefront[queuenumber] = badtri; + } else { + /* Add the bad triangle to the end of an already nonempty queue. */ + m->queuetail[queuenumber]->nexttriang = badtri; + } + /* Maintain a pointer to the last triangle of the queue. */ + m->queuetail[queuenumber] = badtri; + /* Newly enqueued bad triangle has no successor in the queue. */ + badtri->nexttriang = (struct badtriang *) NULL; +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* enqueuebadtri() Add a bad triangle to the end of a queue. */ +/* */ +/* Allocates a badtriang data structure for the triangle, then passes it to */ +/* enqueuebadtriang(). */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri, + REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest) +#else /* not ANSI_DECLARATORS */ +void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest) +struct mesh *m; +struct behavior *b; +struct otri *enqtri; +REAL minedge; +vertex enqapex; +vertex enqorg; +vertex enqdest; +#endif /* not ANSI_DECLARATORS */ + +{ + struct badtriang *newbad; + + /* Allocate space for the bad triangle. */ + newbad = (struct badtriang *) poolalloc(&m->badtriangles); + newbad->poortri = encode(*enqtri); + newbad->key = minedge; + newbad->triangapex = enqapex; + newbad->triangorg = enqorg; + newbad->triangdest = enqdest; + enqueuebadtriang(m, b, newbad); +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* dequeuebadtriang() Remove a triangle from the front of the queue. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +struct badtriang *dequeuebadtriang(struct mesh *m) +#else /* not ANSI_DECLARATORS */ +struct badtriang *dequeuebadtriang(m) +struct mesh *m; +#endif /* not ANSI_DECLARATORS */ + +{ + struct badtriang *result; + + /* If no queues are nonempty, return NULL. */ + if (m->firstnonemptyq < 0) { + return (struct badtriang *) NULL; + } + /* Find the first triangle of the highest-priority queue. */ + result = m->queuefront[m->firstnonemptyq]; + /* Remove the triangle from the queue. */ + m->queuefront[m->firstnonemptyq] = result->nexttriang; + /* If this queue is now empty, note the new highest-priority */ + /* nonempty queue. */ + if (result == m->queuetail[m->firstnonemptyq]) { + m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq]; + } + return result; +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* checkseg4encroach() Check a subsegment to see if it is encroached; add */ +/* it to the list if it is. */ +/* */ +/* A subsegment is encroached if there is a vertex in its diametral lens. */ +/* For Ruppert's algorithm (-D switch), the "diametral lens" is the */ +/* diametral circle. For Chew's algorithm (default), the diametral lens is */ +/* just big enough to enclose two isosceles triangles whose bases are the */ +/* subsegment. Each of the two isosceles triangles has two angles equal */ +/* to `b->minangle'. */ +/* */ +/* Chew's algorithm does not require diametral lenses at all--but they save */ +/* time. Any vertex inside a subsegment's diametral lens implies that the */ +/* triangle adjoining the subsegment will be too skinny, so it's only a */ +/* matter of time before the encroaching vertex is deleted by Chew's */ +/* algorithm. It's faster to simply not insert the doomed vertex in the */ +/* first place, which is why I use diametral lenses with Chew's algorithm. */ +/* */ +/* Returns a nonzero value if the subsegment is encroached. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +int checkseg4encroach(struct mesh *m, struct behavior *b, + struct osub *testsubseg) +#else /* not ANSI_DECLARATORS */ +int checkseg4encroach(m, b, testsubseg) +struct mesh *m; +struct behavior *b; +struct osub *testsubseg; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri neighbortri; + struct osub testsym; + struct badsubseg *encroachedseg; + REAL dotproduct; + int encroached; + int sides; + vertex eorg, edest, eapex; + triangle ptr; /* Temporary variable used by stpivot(). */ + + encroached = 0; + sides = 0; + + sorg(*testsubseg, eorg); + sdest(*testsubseg, edest); + /* Check one neighbor of the subsegment. */ + stpivot(*testsubseg, neighbortri); + /* Does the neighbor exist, or is this a boundary edge? */ + if (neighbortri.tri != m->dummytri) { + sides++; + /* Find a vertex opposite this subsegment. */ + apex(neighbortri, eapex); + /* Check whether the apex is in the diametral lens of the subsegment */ + /* (the diametral circle if `conformdel' is set). A dot product */ + /* of two sides of the triangle is used to check whether the angle */ + /* at the apex is greater than (180 - 2 `minangle') degrees (for */ + /* lenses; 90 degrees for diametral circles). */ + dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (edest[1] - eapex[1]); + if (dotproduct < 0.0) { + if (b->conformdel || + (dotproduct * dotproduct >= + (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) * + ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) * + ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) + + (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) { + encroached = 1; + } + } + } + /* Check the other neighbor of the subsegment. */ + ssym(*testsubseg, testsym); + stpivot(testsym, neighbortri); + /* Does the neighbor exist, or is this a boundary edge? */ + if (neighbortri.tri != m->dummytri) { + sides++; + /* Find the other vertex opposite this subsegment. */ + apex(neighbortri, eapex); + /* Check whether the apex is in the diametral lens of the subsegment */ + /* (or the diametral circle, if `conformdel' is set). */ + dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (edest[1] - eapex[1]); + if (dotproduct < 0.0) { + if (b->conformdel || + (dotproduct * dotproduct >= + (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) * + ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) * + ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) + + (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) { + encroached += 2; + } + } + } + + if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) { + if (b->verbose > 2) { + printf( + " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n", + eorg[0], eorg[1], edest[0], edest[1]); + } + /* Add the subsegment to the list of encroached subsegments. */ + /* Be sure to get the orientation right. */ + encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs); + if (encroached == 1) { + encroachedseg->encsubseg = sencode(*testsubseg); + encroachedseg->subsegorg = eorg; + encroachedseg->subsegdest = edest; + } else { + encroachedseg->encsubseg = sencode(testsym); + encroachedseg->subsegorg = edest; + encroachedseg->subsegdest = eorg; + } + } + + return encroached; +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* testtriangle() Test a triangle for quality and size. */ +/* */ +/* Tests a triangle to see if it satisfies the minimum angle condition and */ +/* the maximum area condition. Triangles that aren't up to spec are added */ +/* to the bad triangle queue. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri) +#else /* not ANSI_DECLARATORS */ +void testtriangle(m, b, testtri) +struct mesh *m; +struct behavior *b; +struct otri *testtri; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri tri1, tri2; + struct osub testsub; + vertex torg, tdest, tapex; + vertex base1, base2; + vertex org1, dest1, org2, dest2; + vertex joinvertex; + REAL dxod, dyod, dxda, dyda, dxao, dyao; + REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2; + REAL apexlen, orglen, destlen, minedge; + REAL angle; + REAL area; + REAL dist1, dist2; + subseg sptr; /* Temporary variable used by tspivot(). */ + triangle ptr; /* Temporary variable used by oprev() and dnext(). */ + + org(*testtri, torg); + dest(*testtri, tdest); + apex(*testtri, tapex); + dxod = torg[0] - tdest[0]; + dyod = torg[1] - tdest[1]; + dxda = tdest[0] - tapex[0]; + dyda = tdest[1] - tapex[1]; + dxao = tapex[0] - torg[0]; + dyao = tapex[1] - torg[1]; + dxod2 = dxod * dxod; + dyod2 = dyod * dyod; + dxda2 = dxda * dxda; + dyda2 = dyda * dyda; + dxao2 = dxao * dxao; + dyao2 = dyao * dyao; + /* Find the lengths of the triangle's three edges. */ + apexlen = dxod2 + dyod2; + orglen = dxda2 + dyda2; + destlen = dxao2 + dyao2; + + if ((apexlen < orglen) && (apexlen < destlen)) { + /* The edge opposite the apex is shortest. */ + minedge = apexlen; + /* Find the square of the cosine of the angle at the apex. */ + angle = dxda * dxao + dyda * dyao; + angle = angle * angle / (orglen * destlen); + base1 = torg; + base2 = tdest; + otricopy(*testtri, tri1); + } else if (orglen < destlen) { + /* The edge opposite the origin is shortest. */ + minedge = orglen; + /* Find the square of the cosine of the angle at the origin. */ + angle = dxod * dxao + dyod * dyao; + angle = angle * angle / (apexlen * destlen); + base1 = tdest; + base2 = tapex; + lnext(*testtri, tri1); + } else { + /* The edge opposite the destination is shortest. */ + minedge = destlen; + /* Find the square of the cosine of the angle at the destination. */ + angle = dxod * dxda + dyod * dyda; + angle = angle * angle / (apexlen * orglen); + base1 = tapex; + base2 = torg; + lprev(*testtri, tri1); + } + + if (b->vararea || b->fixedarea || b->usertest) { + /* Check whether the area is larger than permitted. */ + area = 0.5 * (dxod * dyda - dyod * dxda); + if (b->fixedarea && (area > b->maxarea)) { + /* Add this triangle to the list of bad triangles. */ + enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); + return; + } + + /* Nonpositive area constraints are treated as unconstrained. */ + if ((b->vararea) && (area > areabound(*testtri)) && + (areabound(*testtri) > 0.0)) { + /* Add this triangle to the list of bad triangles. */ + enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); + return; + } + + if (b->usertest) { + /* Check whether the user thinks this triangle is too large. */ + if (triunsuitable(torg, tdest, tapex, area)) { + enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); + return; + } + } + } + + /* Check whether the angle is smaller than permitted. */ + if (angle > b->goodangle) { + /* Use the rules of Miller, Pav, and Walkington to decide that certain */ + /* triangles should not be split, even if they have bad angles. */ + /* A skinny triangle is not split if its shortest edge subtends a */ + /* small input angle, and both endpoints of the edge lie on a */ + /* concentric circular shell. For convenience, I make a small */ + /* adjustment to that rule: I check if the endpoints of the edge */ + /* both lie in segment interiors, equidistant from the apex where */ + /* the two segments meet. */ + /* First, check if both points lie in segment interiors. */ + if ((vertextype(base1) == SEGMENTVERTEX) && + (vertextype(base2) == SEGMENTVERTEX)) { + /* Check if both points lie in a common segment. If they do, the */ + /* skinny triangle is enqueued to be split as usual. */ + tspivot(tri1, testsub); + if (testsub.ss == m->dummysub) { + /* No common segment. Find a subsegment that contains `torg'. */ + otricopy(tri1, tri2); + do { + oprevself(tri1); + tspivot(tri1, testsub); + } while (testsub.ss == m->dummysub); + /* Find the endpoints of the containing segment. */ + segorg(testsub, org1); + segdest(testsub, dest1); + /* Find a subsegment that contains `tdest'. */ + do { + dnextself(tri2); + tspivot(tri2, testsub); + } while (testsub.ss == m->dummysub); + /* Find the endpoints of the containing segment. */ + segorg(testsub, org2); + segdest(testsub, dest2); + /* Check if the two containing segments have an endpoint in common. */ + joinvertex = (vertex) NULL; + if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) { + joinvertex = dest1; + } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) { + joinvertex = org1; + } + if (joinvertex != (vertex) NULL) { + /* Compute the distance from the common endpoint (of the two */ + /* segments) to each of the endpoints of the shortest edge. */ + dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) + + (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1])); + dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) + + (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1])); + /* If the two distances are equal, don't split the triangle. */ + if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) { + /* Return now to avoid enqueueing the bad triangle. */ + return; + } + } + } + } + + /* Add this triangle to the list of bad triangles. */ + enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); + } +} + +#endif /* not CDT_ONLY */ + +/** **/ +/** **/ +/********* Mesh quality testing routines end here *********/ + +/********* Point location routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* makevertexmap() Construct a mapping from vertices to triangles to */ +/* improve the speed of point location for segment */ +/* insertion. */ +/* */ +/* Traverses all the triangles, and provides each corner of each triangle */ +/* with a pointer to that triangle. Of course, pointers will be */ +/* overwritten by other pointers because (almost) each vertex is a corner */ +/* of several triangles, but in the end every vertex will point to some */ +/* triangle that contains it. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void makevertexmap(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void makevertexmap(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop; + vertex triorg; + + if (b->verbose) { + printf(" Constructing mapping from vertices to triangles.\n"); + } + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + while (triangleloop.tri != (triangle *) NULL) { + /* Check all three vertices of the triangle. */ + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + org(triangleloop, triorg); + setvertex2tri(triorg, encode(triangleloop)); + } + triangleloop.tri = triangletraverse(m); + } +} + +/*****************************************************************************/ +/* */ +/* preciselocate() Find a triangle or edge containing a given point. */ +/* */ +/* Begins its search from `searchtri'. It is important that `searchtri' */ +/* be a handle with the property that `searchpoint' is strictly to the left */ +/* of the edge denoted by `searchtri', or is collinear with that edge and */ +/* does not intersect that edge. (In particular, `searchpoint' should not */ +/* be the origin or destination of that edge.) */ +/* */ +/* These conditions are imposed because preciselocate() is normally used in */ +/* one of two situations: */ +/* */ +/* (1) To try to find the location to insert a new point. Normally, we */ +/* know an edge that the point is strictly to the left of. In the */ +/* incremental Delaunay algorithm, that edge is a bounding box edge. */ +/* In Ruppert's Delaunay refinement algorithm for quality meshing, */ +/* that edge is the shortest edge of the triangle whose circumcenter */ +/* is being inserted. */ +/* */ +/* (2) To try to find an existing point. In this case, any edge on the */ +/* convex hull is a good starting edge. You must screen out the */ +/* possibility that the vertex sought is an endpoint of the starting */ +/* edge before you call preciselocate(). */ +/* */ +/* On completion, `searchtri' is a triangle that contains `searchpoint'. */ +/* */ +/* This implementation differs from that given by Guibas and Stolfi. It */ +/* walks from triangle to triangle, crossing an edge only if `searchpoint' */ +/* is on the other side of the line containing that edge. After entering */ +/* a triangle, there are two edges by which one can leave that triangle. */ +/* If both edges are valid (`searchpoint' is on the other side of both */ +/* edges), one of the two is chosen by drawing a line perpendicular to */ +/* the entry edge (whose endpoints are `forg' and `fdest') passing through */ +/* `fapex'. Depending on which side of this perpendicular `searchpoint' */ +/* falls on, an exit edge is chosen. */ +/* */ +/* This implementation is empirically faster than the Guibas and Stolfi */ +/* point location routine (which I originally used), which tends to spiral */ +/* in toward its target. */ +/* */ +/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */ +/* is a handle whose origin is the existing vertex. */ +/* */ +/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */ +/* handle whose primary edge is the edge on which the point lies. */ +/* */ +/* Returns INTRIANGLE if the point lies strictly within a triangle. */ +/* `searchtri' is a handle on the triangle that contains the point. */ +/* */ +/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */ +/* handle whose primary edge the point is to the right of. This might */ +/* occur when the circumcenter of a triangle falls just slightly outside */ +/* the mesh due to floating-point roundoff error. It also occurs when */ +/* seeking a hole or region point that a foolish user has placed outside */ +/* the mesh. */ +/* */ +/* If `stopatsubsegment' is nonzero, the search will stop if it tries to */ +/* walk through a subsegment, and will return OUTSIDE. */ +/* */ +/* WARNING: This routine is designed for convex triangulations, and will */ +/* not generally work after the holes and concavities have been carved. */ +/* However, it can still be used to find the circumcenter of a triangle, as */ +/* long as the search is begun from the triangle in question. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +enum locateresult preciselocate(struct mesh *m, struct behavior *b, + vertex searchpoint, struct otri *searchtri, + int stopatsubsegment) +#else /* not ANSI_DECLARATORS */ +enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment) +struct mesh *m; +struct behavior *b; +vertex searchpoint; +struct otri *searchtri; +int stopatsubsegment; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri backtracktri; + struct osub checkedge; + vertex forg, fdest, fapex; + REAL orgorient, destorient; + int moveleft; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (b->verbose > 2) { + printf(" Searching for point (%.12g, %.12g).\n", + searchpoint[0], searchpoint[1]); + } + /* Where are we? */ + org(*searchtri, forg); + dest(*searchtri, fdest); + apex(*searchtri, fapex); + while (1) { + if (b->verbose > 2) { + printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]); + } + /* Check whether the apex is the point we seek. */ + if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) { + lprevself(*searchtri); + return ONVERTEX; + } + /* Does the point lie on the other side of the line defined by the */ + /* triangle edge opposite the triangle's destination? */ + destorient = counterclockwise(m, b, forg, fapex, searchpoint); + /* Does the point lie on the other side of the line defined by the */ + /* triangle edge opposite the triangle's origin? */ + orgorient = counterclockwise(m, b, fapex, fdest, searchpoint); + if (destorient > 0.0) { + if (orgorient > 0.0) { + /* Move left if the inner product of (fapex - searchpoint) and */ + /* (fdest - forg) is positive. This is equivalent to drawing */ + /* a line perpendicular to the line (forg, fdest) and passing */ + /* through `fapex', and determining which side of this line */ + /* `searchpoint' falls on. */ + moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) + + (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0; + } else { + moveleft = 1; + } + } else { + if (orgorient > 0.0) { + moveleft = 0; + } else { + /* The point we seek must be on the boundary of or inside this */ + /* triangle. */ + if (destorient == 0.0) { + lprevself(*searchtri); + return ONEDGE; + } + if (orgorient == 0.0) { + lnextself(*searchtri); + return ONEDGE; + } + return INTRIANGLE; + } + } + + /* Move to another triangle. Leave a trace `backtracktri' in case */ + /* floating-point roundoff or some such bogey causes us to walk */ + /* off a boundary of the triangulation. */ + if (moveleft) { + lprev(*searchtri, backtracktri); + fdest = fapex; + } else { + lnext(*searchtri, backtracktri); + forg = fapex; + } + sym(backtracktri, *searchtri); + + if (m->checksegments && stopatsubsegment) { + /* Check for walking through a subsegment. */ + tspivot(backtracktri, checkedge); + if (checkedge.ss != m->dummysub) { + /* Go back to the last triangle. */ + otricopy(backtracktri, *searchtri); + return OUTSIDE; + } + } + /* Check for walking right out of the triangulation. */ + if (searchtri->tri == m->dummytri) { + /* Go back to the last triangle. */ + otricopy(backtracktri, *searchtri); + return OUTSIDE; + } + + apex(*searchtri, fapex); + } +} + +/*****************************************************************************/ +/* */ +/* locate() Find a triangle or edge containing a given point. */ +/* */ +/* Searching begins from one of: the input `searchtri', a recently */ +/* encountered triangle `recenttri', or from a triangle chosen from a */ +/* random sample. The choice is made by determining which triangle's */ +/* origin is closest to the point we are searching for. Normally, */ +/* `searchtri' should be a handle on the convex hull of the triangulation. */ +/* */ +/* Details on the random sampling method can be found in the Mucke, Saias, */ +/* and Zhu paper cited in the header of this code. */ +/* */ +/* On completion, `searchtri' is a triangle that contains `searchpoint'. */ +/* */ +/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */ +/* is a handle whose origin is the existing vertex. */ +/* */ +/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */ +/* handle whose primary edge is the edge on which the point lies. */ +/* */ +/* Returns INTRIANGLE if the point lies strictly within a triangle. */ +/* `searchtri' is a handle on the triangle that contains the point. */ +/* */ +/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */ +/* handle whose primary edge the point is to the right of. This might */ +/* occur when the circumcenter of a triangle falls just slightly outside */ +/* the mesh due to floating-point roundoff error. It also occurs when */ +/* seeking a hole or region point that a foolish user has placed outside */ +/* the mesh. */ +/* */ +/* WARNING: This routine is designed for convex triangulations, and will */ +/* not generally work after the holes and concavities have been carved. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +enum locateresult locate(struct mesh *m, struct behavior *b, + vertex searchpoint, struct otri *searchtri) +#else /* not ANSI_DECLARATORS */ +enum locateresult locate(m, b, searchpoint, searchtri) +struct mesh *m; +struct behavior *b; +vertex searchpoint; +struct otri *searchtri; +#endif /* not ANSI_DECLARATORS */ + +{ + VOID **sampleblock; + char *firsttri; + struct otri sampletri; + vertex torg, tdest; + unsigned long alignptr; + REAL searchdist, dist; + REAL ahead; + long samplesperblock, totalsamplesleft, samplesleft; + long population, totalpopulation; + triangle ptr; /* Temporary variable used by sym(). */ + + if (b->verbose > 2) { + printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n", + searchpoint[0], searchpoint[1]); + } + /* Record the distance from the suggested starting triangle to the */ + /* point we seek. */ + org(*searchtri, torg); + searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); + if (b->verbose > 2) { + printf(" Boundary triangle has origin (%.12g, %.12g).\n", + torg[0], torg[1]); + } + + /* If a recently encountered triangle has been recorded and has not been */ + /* deallocated, test it as a good starting point. */ + if (m->recenttri.tri != (triangle *) NULL) { + if (!deadtri(m->recenttri.tri)) { + org(m->recenttri, torg); + if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) { + otricopy(m->recenttri, *searchtri); + return ONVERTEX; + } + dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); + if (dist < searchdist) { + otricopy(m->recenttri, *searchtri); + searchdist = dist; + if (b->verbose > 2) { + printf(" Choosing recent triangle with origin (%.12g, %.12g).\n", + torg[0], torg[1]); + } + } + } + } + + /* The number of random samples taken is proportional to the cube root of */ + /* the number of triangles in the mesh. The next bit of code assumes */ + /* that the number of triangles increases monotonically (or at least */ + /* doesn't decrease enough to matter). */ + while (SAMPLEFACTOR * m->samples * m->samples * m->samples < + m->triangles.items) { + m->samples++; + } + + /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */ + /* from each block of triangles (except the first)--until we meet the */ + /* sample quota. The ceiling means that blocks at the end might be */ + /* neglected, but I don't care. */ + samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1; + /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */ + /* from the first block of triangles. */ + samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) / + m->triangles.maxitems + 1; + totalsamplesleft = m->samples; + population = m->triangles.itemsfirstblock; + totalpopulation = m->triangles.maxitems; + sampleblock = m->triangles.firstblock; + sampletri.orient = 0; + while (totalsamplesleft > 0) { + /* If we're in the last block, `population' needs to be corrected. */ + if (population > totalpopulation) { + population = totalpopulation; + } + /* Find a pointer to the first triangle in the block. */ + alignptr = (unsigned long) (sampleblock + 1); + firsttri = (char *) (alignptr + + (unsigned long) m->triangles.alignbytes - + (alignptr % + (unsigned long) m->triangles.alignbytes)); + + /* Choose `samplesleft' randomly sampled triangles in this block. */ + do { + sampletri.tri = (triangle *) (firsttri + + (randomnation((unsigned int) population) * + m->triangles.itembytes)); + if (!deadtri(sampletri.tri)) { + org(sampletri, torg); + dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); + if (dist < searchdist) { + otricopy(sampletri, *searchtri); + searchdist = dist; + if (b->verbose > 2) { + printf(" Choosing triangle with origin (%.12g, %.12g).\n", + torg[0], torg[1]); + } + } + } + + samplesleft--; + totalsamplesleft--; + } while ((samplesleft > 0) && (totalsamplesleft > 0)); + + if (totalsamplesleft > 0) { + sampleblock = (VOID **) *sampleblock; + samplesleft = samplesperblock; + totalpopulation -= population; + population = TRIPERBLOCK; + } + } + + /* Where are we? */ + org(*searchtri, torg); + dest(*searchtri, tdest); + /* Check the starting triangle's vertices. */ + if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) { + return ONVERTEX; + } + if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) { + lnextself(*searchtri); + return ONVERTEX; + } + /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */ + ahead = counterclockwise(m, b, torg, tdest, searchpoint); + if (ahead < 0.0) { + /* Turn around so that `searchpoint' is to the left of the */ + /* edge specified by `searchtri'. */ + symself(*searchtri); + } else if (ahead == 0.0) { + /* Check if `searchpoint' is between `torg' and `tdest'. */ + if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) && + ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) { + return ONEDGE; + } + } + return preciselocate(m, b, searchpoint, searchtri, 0); +} + +/** **/ +/** **/ +/********* Point location routines end here *********/ + +/********* Mesh transformation routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* insertsubseg() Create a new subsegment and insert it between two */ +/* triangles. */ +/* */ +/* The new subsegment is inserted at the edge described by the handle */ +/* `tri'. Its vertices are properly initialized. The marker `subsegmark' */ +/* is applied to the subsegment and, if appropriate, its vertices. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, + int subsegmark) +#else /* not ANSI_DECLARATORS */ +void insertsubseg(m, b, tri, subsegmark) +struct mesh *m; +struct behavior *b; +struct otri *tri; /* Edge at which to insert the new subsegment. */ +int subsegmark; /* Marker for the new subsegment. */ +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri oppotri; + struct osub newsubseg; + vertex triorg, tridest; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + org(*tri, triorg); + dest(*tri, tridest); + /* Mark vertices if possible. */ + if (vertexmark(triorg) == 0) { + setvertexmark(triorg, subsegmark); + } + if (vertexmark(tridest) == 0) { + setvertexmark(tridest, subsegmark); + } + /* Check if there's already a subsegment here. */ + tspivot(*tri, newsubseg); + if (newsubseg.ss == m->dummysub) { + /* Make new subsegment and initialize its vertices. */ + makesubseg(m, &newsubseg); + setsorg(newsubseg, tridest); + setsdest(newsubseg, triorg); + setsegorg(newsubseg, tridest); + setsegdest(newsubseg, triorg); + /* Bond new subsegment to the two triangles it is sandwiched between. */ + /* Note that the facing triangle `oppotri' might be equal to */ + /* `dummytri' (outer space), but the new subsegment is bonded to it */ + /* all the same. */ + tsbond(*tri, newsubseg); + sym(*tri, oppotri); + ssymself(newsubseg); + tsbond(oppotri, newsubseg); + setmark(newsubseg, subsegmark); + if (b->verbose > 2) { + printf(" Inserting new "); + printsubseg(m, b, &newsubseg); + } + } else { + if (mark(newsubseg) == 0) { + setmark(newsubseg, subsegmark); + } + } +} + +/*****************************************************************************/ +/* */ +/* Terminology */ +/* */ +/* A "local transformation" replaces a small set of triangles with another */ +/* set of triangles. This may or may not involve inserting or deleting a */ +/* vertex. */ +/* */ +/* The term "casing" is used to describe the set of triangles that are */ +/* attached to the triangles being transformed, but are not transformed */ +/* themselves. Think of the casing as a fixed hollow structure inside */ +/* which all the action happens. A "casing" is only defined relative to */ +/* a single transformation; each occurrence of a transformation will */ +/* involve a different casing. */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* flip() Transform two triangles to two different triangles by flipping */ +/* an edge counterclockwise within a quadrilateral. */ +/* */ +/* Imagine the original triangles, abc and bad, oriented so that the */ +/* shared edge ab lies in a horizontal plane, with the vertex b on the left */ +/* and the vertex a on the right. The vertex c lies below the edge, and */ +/* the vertex d lies above the edge. The `flipedge' handle holds the edge */ +/* ab of triangle abc, and is directed left, from vertex a to vertex b. */ +/* */ +/* The triangles abc and bad are deleted and replaced by the triangles cdb */ +/* and dca. The triangles that represent abc and bad are NOT deallocated; */ +/* they are reused for dca and cdb, respectively. Hence, any handles that */ +/* may have held the original triangles are still valid, although not */ +/* directed as they were before. */ +/* */ +/* Upon completion of this routine, the `flipedge' handle holds the edge */ +/* dc of triangle dca, and is directed down, from vertex d to vertex c. */ +/* (Hence, the two triangles have rotated counterclockwise.) */ +/* */ +/* WARNING: This transformation is geometrically valid only if the */ +/* quadrilateral adbc is convex. Furthermore, this transformation is */ +/* valid only if there is not a subsegment between the triangles abc and */ +/* bad. This routine does not check either of these preconditions, and */ +/* it is the responsibility of the calling routine to ensure that they are */ +/* met. If they are not, the streets shall be filled with wailing and */ +/* gnashing of teeth. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void flip(struct mesh *m, struct behavior *b, struct otri *flipedge) +#else /* not ANSI_DECLARATORS */ +void flip(m, b, flipedge) +struct mesh *m; +struct behavior *b; +struct otri *flipedge; /* Handle for the triangle abc. */ +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri botleft, botright; + struct otri topleft, topright; + struct otri top; + struct otri botlcasing, botrcasing; + struct otri toplcasing, toprcasing; + struct osub botlsubseg, botrsubseg; + struct osub toplsubseg, toprsubseg; + vertex leftvertex, rightvertex, botvertex; + vertex farvertex; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + /* Identify the vertices of the quadrilateral. */ + org(*flipedge, rightvertex); + dest(*flipedge, leftvertex); + apex(*flipedge, botvertex); + sym(*flipedge, top); +#ifdef SELF_CHECK + if (top.tri == m->dummytri) { + printf("Internal error in flip(): Attempt to flip on boundary.\n"); + lnextself(*flipedge); + return; + } + if (m->checksegments) { + tspivot(*flipedge, toplsubseg); + if (toplsubseg.ss != m->dummysub) { + printf("Internal error in flip(): Attempt to flip a segment.\n"); + lnextself(*flipedge); + return; + } + } +#endif /* SELF_CHECK */ + apex(top, farvertex); + + /* Identify the casing of the quadrilateral. */ + lprev(top, topleft); + sym(topleft, toplcasing); + lnext(top, topright); + sym(topright, toprcasing); + lnext(*flipedge, botleft); + sym(botleft, botlcasing); + lprev(*flipedge, botright); + sym(botright, botrcasing); + /* Rotate the quadrilateral one-quarter turn counterclockwise. */ + bond(topleft, botlcasing); + bond(botleft, botrcasing); + bond(botright, toprcasing); + bond(topright, toplcasing); + + if (m->checksegments) { + /* Check for subsegments and rebond them to the quadrilateral. */ + tspivot(topleft, toplsubseg); + tspivot(botleft, botlsubseg); + tspivot(botright, botrsubseg); + tspivot(topright, toprsubseg); + if (toplsubseg.ss == m->dummysub) { + tsdissolve(topright); + } else { + tsbond(topright, toplsubseg); + } + if (botlsubseg.ss == m->dummysub) { + tsdissolve(topleft); + } else { + tsbond(topleft, botlsubseg); + } + if (botrsubseg.ss == m->dummysub) { + tsdissolve(botleft); + } else { + tsbond(botleft, botrsubseg); + } + if (toprsubseg.ss == m->dummysub) { + tsdissolve(botright); + } else { + tsbond(botright, toprsubseg); + } + } + + /* New vertex assignments for the rotated quadrilateral. */ + setorg(*flipedge, farvertex); + setdest(*flipedge, botvertex); + setapex(*flipedge, rightvertex); + setorg(top, botvertex); + setdest(top, farvertex); + setapex(top, leftvertex); + if (b->verbose > 2) { + printf(" Edge flip results in left "); + printtriangle(m, b, &top); + printf(" and right "); + printtriangle(m, b, flipedge); + } +} + +/*****************************************************************************/ +/* */ +/* unflip() Transform two triangles to two different triangles by */ +/* flipping an edge clockwise within a quadrilateral. Reverses */ +/* the flip() operation so that the data structures representing */ +/* the triangles are back where they were before the flip(). */ +/* */ +/* Imagine the original triangles, abc and bad, oriented so that the */ +/* shared edge ab lies in a horizontal plane, with the vertex b on the left */ +/* and the vertex a on the right. The vertex c lies below the edge, and */ +/* the vertex d lies above the edge. The `flipedge' handle holds the edge */ +/* ab of triangle abc, and is directed left, from vertex a to vertex b. */ +/* */ +/* The triangles abc and bad are deleted and replaced by the triangles cdb */ +/* and dca. The triangles that represent abc and bad are NOT deallocated; */ +/* they are reused for cdb and dca, respectively. Hence, any handles that */ +/* may have held the original triangles are still valid, although not */ +/* directed as they were before. */ +/* */ +/* Upon completion of this routine, the `flipedge' handle holds the edge */ +/* cd of triangle cdb, and is directed up, from vertex c to vertex d. */ +/* (Hence, the two triangles have rotated clockwise.) */ +/* */ +/* WARNING: This transformation is geometrically valid only if the */ +/* quadrilateral adbc is convex. Furthermore, this transformation is */ +/* valid only if there is not a subsegment between the triangles abc and */ +/* bad. This routine does not check either of these preconditions, and */ +/* it is the responsibility of the calling routine to ensure that they are */ +/* met. If they are not, the streets shall be filled with wailing and */ +/* gnashing of teeth. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge) +#else /* not ANSI_DECLARATORS */ +void unflip(m, b, flipedge) +struct mesh *m; +struct behavior *b; +struct otri *flipedge; /* Handle for the triangle abc. */ +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri botleft, botright; + struct otri topleft, topright; + struct otri top; + struct otri botlcasing, botrcasing; + struct otri toplcasing, toprcasing; + struct osub botlsubseg, botrsubseg; + struct osub toplsubseg, toprsubseg; + vertex leftvertex, rightvertex, botvertex; + vertex farvertex; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + /* Identify the vertices of the quadrilateral. */ + org(*flipedge, rightvertex); + dest(*flipedge, leftvertex); + apex(*flipedge, botvertex); + sym(*flipedge, top); +#ifdef SELF_CHECK + if (top.tri == m->dummytri) { + printf("Internal error in unflip(): Attempt to flip on boundary.\n"); + lnextself(*flipedge); + return; + } + if (m->checksegments) { + tspivot(*flipedge, toplsubseg); + if (toplsubseg.ss != m->dummysub) { + printf("Internal error in unflip(): Attempt to flip a subsegment.\n"); + lnextself(*flipedge); + return; + } + } +#endif /* SELF_CHECK */ + apex(top, farvertex); + + /* Identify the casing of the quadrilateral. */ + lprev(top, topleft); + sym(topleft, toplcasing); + lnext(top, topright); + sym(topright, toprcasing); + lnext(*flipedge, botleft); + sym(botleft, botlcasing); + lprev(*flipedge, botright); + sym(botright, botrcasing); + /* Rotate the quadrilateral one-quarter turn clockwise. */ + bond(topleft, toprcasing); + bond(botleft, toplcasing); + bond(botright, botlcasing); + bond(topright, botrcasing); + + if (m->checksegments) { + /* Check for subsegments and rebond them to the quadrilateral. */ + tspivot(topleft, toplsubseg); + tspivot(botleft, botlsubseg); + tspivot(botright, botrsubseg); + tspivot(topright, toprsubseg); + if (toplsubseg.ss == m->dummysub) { + tsdissolve(botleft); + } else { + tsbond(botleft, toplsubseg); + } + if (botlsubseg.ss == m->dummysub) { + tsdissolve(botright); + } else { + tsbond(botright, botlsubseg); + } + if (botrsubseg.ss == m->dummysub) { + tsdissolve(topright); + } else { + tsbond(topright, botrsubseg); + } + if (toprsubseg.ss == m->dummysub) { + tsdissolve(topleft); + } else { + tsbond(topleft, toprsubseg); + } + } + + /* New vertex assignments for the rotated quadrilateral. */ + setorg(*flipedge, botvertex); + setdest(*flipedge, farvertex); + setapex(*flipedge, leftvertex); + setorg(top, farvertex); + setdest(top, botvertex); + setapex(top, rightvertex); + if (b->verbose > 2) { + printf(" Edge unflip results in left "); + printtriangle(m, b, flipedge); + printf(" and right "); + printtriangle(m, b, &top); + } +} + +/*****************************************************************************/ +/* */ +/* insertvertex() Insert a vertex into a Delaunay triangulation, */ +/* performing flips as necessary to maintain the Delaunay */ +/* property. */ +/* */ +/* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */ +/* the search for the containing triangle begins from `searchtri'. If */ +/* `searchtri.tri' is NULL, a full point location procedure is called. */ +/* If `insertvertex' is found inside a triangle, the triangle is split into */ +/* three; if `insertvertex' lies on an edge, the edge is split in two, */ +/* thereby splitting the two adjacent triangles into four. Edge flips are */ +/* used to restore the Delaunay property. If `insertvertex' lies on an */ +/* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */ +/* returned. On return, `searchtri' is set to a handle whose origin is the */ +/* existing vertex. */ +/* */ +/* Normally, the parameter `splitseg' is set to NULL, implying that no */ +/* subsegment should be split. In this case, if `insertvertex' is found to */ +/* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */ +/* returned. On return, `searchtri' is set to a handle whose primary edge */ +/* is the violated subsegment. */ +/* */ +/* If the calling routine wishes to split a subsegment by inserting a */ +/* vertex in it, the parameter `splitseg' should be that subsegment. In */ +/* this case, `searchtri' MUST be the triangle handle reached by pivoting */ +/* from that subsegment; no point location is done. */ +/* */ +/* `segmentflaws' and `triflaws' are flags that indicate whether or not */ +/* there should be checks for the creation of encroached subsegments or bad */ +/* quality triangles. If a newly inserted vertex encroaches upon */ +/* subsegments, these subsegments are added to the list of subsegments to */ +/* be split if `segmentflaws' is set. If bad triangles are created, these */ +/* are added to the queue if `triflaws' is set. */ +/* */ +/* If a duplicate vertex or violated segment does not prevent the vertex */ +/* from being inserted, the return value will be ENCROACHINGVERTEX if the */ +/* vertex encroaches upon a subsegment (and checking is enabled), or */ +/* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */ +/* handle whose origin is the newly inserted vertex. */ +/* */ +/* insertvertex() does not use flip() for reasons of speed; some */ +/* information can be reused from edge flip to edge flip, like the */ +/* locations of subsegments. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, + vertex newvertex, struct otri *searchtri, + struct osub *splitseg, + int segmentflaws, int triflaws) +#else /* not ANSI_DECLARATORS */ +enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg, + segmentflaws, triflaws) +struct mesh *m; +struct behavior *b; +vertex newvertex; +struct otri *searchtri; +struct osub *splitseg; +int segmentflaws; +int triflaws; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri horiz; + struct otri top; + struct otri botleft, botright; + struct otri topleft, topright; + struct otri newbotleft, newbotright; + struct otri newtopright; + struct otri botlcasing, botrcasing; + struct otri toplcasing, toprcasing; + struct otri testtri; + struct osub botlsubseg, botrsubseg; + struct osub toplsubseg, toprsubseg; + struct osub brokensubseg; + struct osub checksubseg; + struct osub rightsubseg; + struct osub newsubseg; + struct badsubseg *encroached; + struct flipstacker *newflip; + vertex first; + vertex leftvertex, rightvertex, botvertex, topvertex, farvertex; + vertex segmentorg, segmentdest; + REAL attrib; + REAL area; + enum insertvertexresult success; + enum locateresult intersect; + int doflip; + int mirrorflag; + int enq; + int i; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by spivot() and tspivot(). */ + + if (b->verbose > 1) { + printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]); + } + + if (splitseg == (struct osub *) NULL) { + /* Find the location of the vertex to be inserted. Check if a good */ + /* starting triangle has already been provided by the caller. */ + if (searchtri->tri == m->dummytri) { + /* Find a boundary triangle. */ + horiz.tri = m->dummytri; + horiz.orient = 0; + symself(horiz); + /* Search for a triangle containing `newvertex'. */ + intersect = locate(m, b, newvertex, &horiz); + } else { + /* Start searching from the triangle provided by the caller. */ + otricopy(*searchtri, horiz); + intersect = preciselocate(m, b, newvertex, &horiz, 1); + } + } else { + /* The calling routine provides the subsegment in which */ + /* the vertex is inserted. */ + otricopy(*searchtri, horiz); + intersect = ONEDGE; + } + + if (intersect == ONVERTEX) { + /* There's already a vertex there. Return in `searchtri' a triangle */ + /* whose origin is the existing vertex. */ + otricopy(horiz, *searchtri); + otricopy(horiz, m->recenttri); + return DUPLICATEVERTEX; + } + if ((intersect == ONEDGE) || (intersect == OUTSIDE)) { + /* The vertex falls on an edge or boundary. */ + if (m->checksegments && (splitseg == (struct osub *) NULL)) { + /* Check whether the vertex falls on a subsegment. */ + tspivot(horiz, brokensubseg); + if (brokensubseg.ss != m->dummysub) { + /* The vertex falls on a subsegment, and hence will not be inserted. */ + if (segmentflaws) { + enq = b->nobisect != 2; + if (enq && (b->nobisect == 1)) { + /* This subsegment may be split only if it is an */ + /* internal boundary. */ + sym(horiz, testtri); + enq = testtri.tri != m->dummytri; + } + if (enq) { + /* Add the subsegment to the list of encroached subsegments. */ + encroached = (struct badsubseg *) poolalloc(&m->badsubsegs); + encroached->encsubseg = sencode(brokensubseg); + sorg(brokensubseg, encroached->subsegorg); + sdest(brokensubseg, encroached->subsegdest); + if (b->verbose > 2) { + printf( + " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n", + encroached->subsegorg[0], encroached->subsegorg[1], + encroached->subsegdest[0], encroached->subsegdest[1]); + } + } + } + /* Return a handle whose primary edge contains the vertex, */ + /* which has not been inserted. */ + otricopy(horiz, *searchtri); + otricopy(horiz, m->recenttri); + return VIOLATINGVERTEX; + } + } + + /* Insert the vertex on an edge, dividing one triangle into two (if */ + /* the edge lies on a boundary) or two triangles into four. */ + lprev(horiz, botright); + sym(botright, botrcasing); + sym(horiz, topright); + /* Is there a second triangle? (Or does this edge lie on a boundary?) */ + mirrorflag = topright.tri != m->dummytri; + if (mirrorflag) { + lnextself(topright); + sym(topright, toprcasing); + maketriangle(m, b, &newtopright); + } else { + /* Splitting a boundary edge increases the number of boundary edges. */ + m->hullsize++; + } + maketriangle(m, b, &newbotright); + + /* Set the vertices of changed and new triangles. */ + org(horiz, rightvertex); + dest(horiz, leftvertex); + apex(horiz, botvertex); + setorg(newbotright, botvertex); + setdest(newbotright, rightvertex); + setapex(newbotright, newvertex); + setorg(horiz, newvertex); + for (i = 0; i < m->eextras; i++) { + /* Set the element attributes of a new triangle. */ + setelemattribute(newbotright, i, elemattribute(botright, i)); + } + if (b->vararea) { + /* Set the area constraint of a new triangle. */ + setareabound(newbotright, areabound(botright)); + } + if (mirrorflag) { + dest(topright, topvertex); + setorg(newtopright, rightvertex); + setdest(newtopright, topvertex); + setapex(newtopright, newvertex); + setorg(topright, newvertex); + for (i = 0; i < m->eextras; i++) { + /* Set the element attributes of another new triangle. */ + setelemattribute(newtopright, i, elemattribute(topright, i)); + } + if (b->vararea) { + /* Set the area constraint of another new triangle. */ + setareabound(newtopright, areabound(topright)); + } + } + + /* There may be subsegments that need to be bonded */ + /* to the new triangle(s). */ + if (m->checksegments) { + tspivot(botright, botrsubseg); + if (botrsubseg.ss != m->dummysub) { + tsdissolve(botright); + tsbond(newbotright, botrsubseg); + } + if (mirrorflag) { + tspivot(topright, toprsubseg); + if (toprsubseg.ss != m->dummysub) { + tsdissolve(topright); + tsbond(newtopright, toprsubseg); + } + } + } + + /* Bond the new triangle(s) to the surrounding triangles. */ + bond(newbotright, botrcasing); + lprevself(newbotright); + bond(newbotright, botright); + lprevself(newbotright); + if (mirrorflag) { + bond(newtopright, toprcasing); + lnextself(newtopright); + bond(newtopright, topright); + lnextself(newtopright); + bond(newtopright, newbotright); + } + + if (splitseg != (struct osub *) NULL) { + /* Split the subsegment into two. */ + setsdest(*splitseg, newvertex); + segorg(*splitseg, segmentorg); + segdest(*splitseg, segmentdest); + ssymself(*splitseg); + spivot(*splitseg, rightsubseg); + insertsubseg(m, b, &newbotright, mark(*splitseg)); + tspivot(newbotright, newsubseg); + setsegorg(newsubseg, segmentorg); + setsegdest(newsubseg, segmentdest); + sbond(*splitseg, newsubseg); + ssymself(newsubseg); + sbond(newsubseg, rightsubseg); + ssymself(*splitseg); + /* Transfer the subsegment's boundary marker to the vertex */ + /* if required. */ + if (vertexmark(newvertex) == 0) { + setvertexmark(newvertex, mark(*splitseg)); + } + } + + if (m->checkquality) { + poolrestart(&m->flipstackers); + m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers); + m->lastflip->flippedtri = encode(horiz); + m->lastflip->prevflip = (struct flipstacker *) &insertvertex; + } + +#ifdef SELF_CHECK + if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf( + " Clockwise triangle prior to edge vertex insertion (bottom).\n"); + } + if (mirrorflag) { + if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle prior to edge vertex insertion (top).\n"); + } + if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf( + " Clockwise triangle after edge vertex insertion (top right).\n"); + } + if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf( + " Clockwise triangle after edge vertex insertion (top left).\n"); + } + } + if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf( + " Clockwise triangle after edge vertex insertion (bottom left).\n"); + } + if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf( + " Clockwise triangle after edge vertex insertion (bottom right).\n"); + } +#endif /* SELF_CHECK */ + if (b->verbose > 2) { + printf(" Updating bottom left "); + printtriangle(m, b, &botright); + if (mirrorflag) { + printf(" Updating top left "); + printtriangle(m, b, &topright); + printf(" Creating top right "); + printtriangle(m, b, &newtopright); + } + printf(" Creating bottom right "); + printtriangle(m, b, &newbotright); + } + + /* Position `horiz' on the first edge to check for */ + /* the Delaunay property. */ + lnextself(horiz); + } else { + /* Insert the vertex in a triangle, splitting it into three. */ + lnext(horiz, botleft); + lprev(horiz, botright); + sym(botleft, botlcasing); + sym(botright, botrcasing); + maketriangle(m, b, &newbotleft); + maketriangle(m, b, &newbotright); + + /* Set the vertices of changed and new triangles. */ + org(horiz, rightvertex); + dest(horiz, leftvertex); + apex(horiz, botvertex); + setorg(newbotleft, leftvertex); + setdest(newbotleft, botvertex); + setapex(newbotleft, newvertex); + setorg(newbotright, botvertex); + setdest(newbotright, rightvertex); + setapex(newbotright, newvertex); + setapex(horiz, newvertex); + for (i = 0; i < m->eextras; i++) { + /* Set the element attributes of the new triangles. */ + attrib = elemattribute(horiz, i); + setelemattribute(newbotleft, i, attrib); + setelemattribute(newbotright, i, attrib); + } + if (b->vararea) { + /* Set the area constraint of the new triangles. */ + area = areabound(horiz); + setareabound(newbotleft, area); + setareabound(newbotright, area); + } + + /* There may be subsegments that need to be bonded */ + /* to the new triangles. */ + if (m->checksegments) { + tspivot(botleft, botlsubseg); + if (botlsubseg.ss != m->dummysub) { + tsdissolve(botleft); + tsbond(newbotleft, botlsubseg); + } + tspivot(botright, botrsubseg); + if (botrsubseg.ss != m->dummysub) { + tsdissolve(botright); + tsbond(newbotright, botrsubseg); + } + } + + /* Bond the new triangles to the surrounding triangles. */ + bond(newbotleft, botlcasing); + bond(newbotright, botrcasing); + lnextself(newbotleft); + lprevself(newbotright); + bond(newbotleft, newbotright); + lnextself(newbotleft); + bond(botleft, newbotleft); + lprevself(newbotright); + bond(botright, newbotright); + + if (m->checkquality) { + poolrestart(&m->flipstackers); + m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers); + m->lastflip->flippedtri = encode(horiz); + m->lastflip->prevflip = (struct flipstacker *) NULL; + } + +#ifdef SELF_CHECK + if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle prior to vertex insertion.\n"); + } + if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle after vertex insertion (top).\n"); + } + if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle after vertex insertion (left).\n"); + } + if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle after vertex insertion (right).\n"); + } +#endif /* SELF_CHECK */ + if (b->verbose > 2) { + printf(" Updating top "); + printtriangle(m, b, &horiz); + printf(" Creating left "); + printtriangle(m, b, &newbotleft); + printf(" Creating right "); + printtriangle(m, b, &newbotright); + } + } + + /* The insertion is successful by default, unless an encroached */ + /* subsegment is found. */ + success = SUCCESSFULVERTEX; + /* Circle around the newly inserted vertex, checking each edge opposite */ + /* it for the Delaunay property. Non-Delaunay edges are flipped. */ + /* `horiz' is always the edge being checked. `first' marks where to */ + /* stop circling. */ + org(horiz, first); + rightvertex = first; + dest(horiz, leftvertex); + /* Circle until finished. */ + while (1) { + /* By default, the edge will be flipped. */ + doflip = 1; + + if (m->checksegments) { + /* Check for a subsegment, which cannot be flipped. */ + tspivot(horiz, checksubseg); + if (checksubseg.ss != m->dummysub) { + /* The edge is a subsegment and cannot be flipped. */ + doflip = 0; +#ifndef CDT_ONLY + if (segmentflaws) { + /* Does the new vertex encroach upon this subsegment? */ + if (checkseg4encroach(m, b, &checksubseg)) { + success = ENCROACHINGVERTEX; + } + } +#endif /* not CDT_ONLY */ + } + } + + if (doflip) { + /* Check if the edge is a boundary edge. */ + sym(horiz, top); + if (top.tri == m->dummytri) { + /* The edge is a boundary edge and cannot be flipped. */ + doflip = 0; + } else { + /* Find the vertex on the other side of the edge. */ + apex(top, farvertex); + /* In the incremental Delaunay triangulation algorithm, any of */ + /* `leftvertex', `rightvertex', and `farvertex' could be vertices */ + /* of the triangular bounding box. These vertices must be */ + /* treated as if they are infinitely distant, even though their */ + /* "coordinates" are not. */ + if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) || + (leftvertex == m->infvertex3)) { + /* `leftvertex' is infinitely distant. Check the convexity of */ + /* the boundary of the triangulation. 'farvertex' might be */ + /* infinite as well, but trust me, this same condition should */ + /* be applied. */ + doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex) + > 0.0; + } else if ((rightvertex == m->infvertex1) || + (rightvertex == m->infvertex2) || + (rightvertex == m->infvertex3)) { + /* `rightvertex' is infinitely distant. Check the convexity of */ + /* the boundary of the triangulation. 'farvertex' might be */ + /* infinite as well, but trust me, this same condition should */ + /* be applied. */ + doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex) + > 0.0; + } else if ((farvertex == m->infvertex1) || + (farvertex == m->infvertex2) || + (farvertex == m->infvertex3)) { + /* `farvertex' is infinitely distant and cannot be inside */ + /* the circumcircle of the triangle `horiz'. */ + doflip = 0; + } else { + /* Test whether the edge is locally Delaunay. */ + doflip = incircle(m, b, leftvertex, newvertex, rightvertex, + farvertex) > 0.0; + } + if (doflip) { + /* We made it! Flip the edge `horiz' by rotating its containing */ + /* quadrilateral (the two triangles adjacent to `horiz'). */ + /* Identify the casing of the quadrilateral. */ + lprev(top, topleft); + sym(topleft, toplcasing); + lnext(top, topright); + sym(topright, toprcasing); + lnext(horiz, botleft); + sym(botleft, botlcasing); + lprev(horiz, botright); + sym(botright, botrcasing); + /* Rotate the quadrilateral one-quarter turn counterclockwise. */ + bond(topleft, botlcasing); + bond(botleft, botrcasing); + bond(botright, toprcasing); + bond(topright, toplcasing); + if (m->checksegments) { + /* Check for subsegments and rebond them to the quadrilateral. */ + tspivot(topleft, toplsubseg); + tspivot(botleft, botlsubseg); + tspivot(botright, botrsubseg); + tspivot(topright, toprsubseg); + if (toplsubseg.ss == m->dummysub) { + tsdissolve(topright); + } else { + tsbond(topright, toplsubseg); + } + if (botlsubseg.ss == m->dummysub) { + tsdissolve(topleft); + } else { + tsbond(topleft, botlsubseg); + } + if (botrsubseg.ss == m->dummysub) { + tsdissolve(botleft); + } else { + tsbond(botleft, botrsubseg); + } + if (toprsubseg.ss == m->dummysub) { + tsdissolve(botright); + } else { + tsbond(botright, toprsubseg); + } + } + /* New vertex assignments for the rotated quadrilateral. */ + setorg(horiz, farvertex); + setdest(horiz, newvertex); + setapex(horiz, rightvertex); + setorg(top, newvertex); + setdest(top, farvertex); + setapex(top, leftvertex); + for (i = 0; i < m->eextras; i++) { + /* Take the average of the two triangles' attributes. */ + attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i)); + setelemattribute(top, i, attrib); + setelemattribute(horiz, i, attrib); + } + if (b->vararea) { + if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) { + area = -1.0; + } else { + /* Take the average of the two triangles' area constraints. */ + /* This prevents small area constraints from migrating a */ + /* long, long way from their original location due to flips. */ + area = 0.5 * (areabound(top) + areabound(horiz)); + } + setareabound(top, area); + setareabound(horiz, area); + } + + if (m->checkquality) { + newflip = (struct flipstacker *) poolalloc(&m->flipstackers); + newflip->flippedtri = encode(horiz); + newflip->prevflip = m->lastflip; + m->lastflip = newflip; + } + +#ifdef SELF_CHECK + if (newvertex != (vertex) NULL) { + if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) < + 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle prior to edge flip (bottom).\n"); + } + /* The following test has been removed because constrainededge() */ + /* sometimes generates inverted triangles that insertvertex() */ + /* removes. */ +/* + if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) < + 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle prior to edge flip (top).\n"); + } +*/ + if (counterclockwise(m, b, farvertex, leftvertex, newvertex) < + 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle after edge flip (left).\n"); + } + if (counterclockwise(m, b, newvertex, rightvertex, farvertex) < + 0.0) { + printf("Internal error in insertvertex():\n"); + printf(" Clockwise triangle after edge flip (right).\n"); + } + } +#endif /* SELF_CHECK */ + if (b->verbose > 2) { + printf(" Edge flip results in left "); + lnextself(topleft); + printtriangle(m, b, &topleft); + printf(" and right "); + printtriangle(m, b, &horiz); + } + /* On the next iterations, consider the two edges that were */ + /* exposed (this is, are now visible to the newly inserted */ + /* vertex) by the edge flip. */ + lprevself(horiz); + leftvertex = farvertex; + } + } + } + if (!doflip) { + /* The handle `horiz' is accepted as locally Delaunay. */ +#ifndef CDT_ONLY + if (triflaws) { + /* Check the triangle `horiz' for quality. */ + testtriangle(m, b, &horiz); + } +#endif /* not CDT_ONLY */ + /* Look for the next edge around the newly inserted vertex. */ + lnextself(horiz); + sym(horiz, testtri); + /* Check for finishing a complete revolution about the new vertex, or */ + /* falling outside of the triangulation. The latter will happen */ + /* when a vertex is inserted at a boundary. */ + if ((leftvertex == first) || (testtri.tri == m->dummytri)) { + /* We're done. Return a triangle whose origin is the new vertex. */ + lnext(horiz, *searchtri); + lnext(horiz, m->recenttri); + return success; + } + /* Finish finding the next edge around the newly inserted vertex. */ + lnext(testtri, horiz); + rightvertex = leftvertex; + dest(horiz, leftvertex); + } + } +} + +/*****************************************************************************/ +/* */ +/* triangulatepolygon() Find the Delaunay triangulation of a polygon that */ +/* has a certain "nice" shape. This includes the */ +/* polygons that result from deletion of a vertex or */ +/* insertion of a segment. */ +/* */ +/* This is a conceptually difficult routine. The starting assumption is */ +/* that we have a polygon with n sides. n - 1 of these sides are currently */ +/* represented as edges in the mesh. One side, called the "base", need not */ +/* be. */ +/* */ +/* Inside the polygon is a structure I call a "fan", consisting of n - 1 */ +/* triangles that share a common origin. For each of these triangles, the */ +/* edge opposite the origin is one of the sides of the polygon. The */ +/* primary edge of each triangle is the edge directed from the origin to */ +/* the destination; note that this is not the same edge that is a side of */ +/* the polygon. `firstedge' is the primary edge of the first triangle. */ +/* From there, the triangles follow in counterclockwise order about the */ +/* polygon, until `lastedge', the primary edge of the last triangle. */ +/* `firstedge' and `lastedge' are probably connected to other triangles */ +/* beyond the extremes of the fan, but their identity is not important, as */ +/* long as the fan remains connected to them. */ +/* */ +/* Imagine the polygon oriented so that its base is at the bottom. This */ +/* puts `firstedge' on the far right, and `lastedge' on the far left. */ +/* The right vertex of the base is the destination of `firstedge', and the */ +/* left vertex of the base is the apex of `lastedge'. */ +/* */ +/* The challenge now is to find the right sequence of edge flips to */ +/* transform the fan into a Delaunay triangulation of the polygon. Each */ +/* edge flip effectively removes one triangle from the fan, committing it */ +/* to the polygon. The resulting polygon has one fewer edge. If `doflip' */ +/* is set, the final flip will be performed, resulting in a fan of one */ +/* (useless?) triangle. If `doflip' is not set, the final flip is not */ +/* performed, resulting in a fan of two triangles, and an unfinished */ +/* triangular polygon that is not yet filled out with a single triangle. */ +/* On completion of the routine, `lastedge' is the last remaining triangle, */ +/* or the leftmost of the last two. */ +/* */ +/* Although the flips are performed in the order described above, the */ +/* decisions about what flips to perform are made in precisely the reverse */ +/* order. The recursive triangulatepolygon() procedure makes a decision, */ +/* uses up to two recursive calls to triangulate the "subproblems" */ +/* (polygons with fewer edges), and then performs an edge flip. */ +/* */ +/* The "decision" it makes is which vertex of the polygon should be */ +/* connected to the base. This decision is made by testing every possible */ +/* vertex. Once the best vertex is found, the two edges that connect this */ +/* vertex to the base become the bases for two smaller polygons. These */ +/* are triangulated recursively. Unfortunately, this approach can take */ +/* O(n^2) time not only in the worst case, but in many common cases. It's */ +/* rarely a big deal for vertex deletion, where n is rarely larger than */ +/* ten, but it could be a big deal for segment insertion, especially if */ +/* there's a lot of long segments that each cut many triangles. I ought to */ +/* code a faster algorithm some day. */ +/* */ +/* The `edgecount' parameter is the number of sides of the polygon, */ +/* including its base. `triflaws' is a flag that determines whether the */ +/* new triangles should be tested for quality, and enqueued if they are */ +/* bad. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void triangulatepolygon(struct mesh *m, struct behavior *b, + struct otri *firstedge, struct otri *lastedge, + int edgecount, int doflip, int triflaws) +#else /* not ANSI_DECLARATORS */ +void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws) +struct mesh *m; +struct behavior *b; +struct otri *firstedge; +struct otri *lastedge; +int edgecount; +int doflip; +int triflaws; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri testtri; + struct otri besttri; + struct otri tempedge; + vertex leftbasevertex, rightbasevertex; + vertex testvertex; + vertex bestvertex; + int bestnumber; + int i; + triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ + + /* Identify the base vertices. */ + apex(*lastedge, leftbasevertex); + dest(*firstedge, rightbasevertex); + if (b->verbose > 2) { + printf(" Triangulating interior polygon at edge\n"); + printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0], + leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]); + } + /* Find the best vertex to connect the base to. */ + onext(*firstedge, besttri); + dest(besttri, bestvertex); + otricopy(besttri, testtri); + bestnumber = 1; + for (i = 2; i <= edgecount - 2; i++) { + onextself(testtri); + dest(testtri, testvertex); + /* Is this a better vertex? */ + if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex, + testvertex) > 0.0) { + otricopy(testtri, besttri); + bestvertex = testvertex; + bestnumber = i; + } + } + if (b->verbose > 2) { + printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0], + bestvertex[1]); + } + if (bestnumber > 1) { + /* Recursively triangulate the smaller polygon on the right. */ + oprev(besttri, tempedge); + triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1, + triflaws); + } + if (bestnumber < edgecount - 2) { + /* Recursively triangulate the smaller polygon on the left. */ + sym(besttri, tempedge); + triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1, + triflaws); + /* Find `besttri' again; it may have been lost to edge flips. */ + sym(tempedge, besttri); + } + if (doflip) { + /* Do one final edge flip. */ + flip(m, b, &besttri); +#ifndef CDT_ONLY + if (triflaws) { + /* Check the quality of the newly committed triangle. */ + sym(besttri, testtri); + testtriangle(m, b, &testtri); + } +#endif /* not CDT_ONLY */ + } + /* Return the base triangle. */ + otricopy(besttri, *lastedge); +} + +/*****************************************************************************/ +/* */ +/* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */ +/* that the triangulation remains Delaunay. */ +/* */ +/* The origin of `deltri' is deleted. The union of the triangles adjacent */ +/* to this vertex is a polygon, for which the Delaunay triangulation is */ +/* found. Two triangles are removed from the mesh. */ +/* */ +/* Only interior vertices that do not lie on segments or boundaries may be */ +/* deleted. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri) +#else /* not ANSI_DECLARATORS */ +void deletevertex(m, b, deltri) +struct mesh *m; +struct behavior *b; +struct otri *deltri; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri countingtri; + struct otri firstedge, lastedge; + struct otri deltriright; + struct otri lefttri, righttri; + struct otri leftcasing, rightcasing; + struct osub leftsubseg, rightsubseg; + vertex delvertex; + vertex neworg; + int edgecount; + triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + org(*deltri, delvertex); + if (b->verbose > 1) { + printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]); + } + vertexdealloc(m, delvertex); + + /* Count the degree of the vertex being deleted. */ + onext(*deltri, countingtri); + edgecount = 1; + while (!otriequal(*deltri, countingtri)) { +#ifdef SELF_CHECK + if (countingtri.tri == m->dummytri) { + printf("Internal error in deletevertex():\n"); + printf(" Attempt to delete boundary vertex.\n"); + internalerror(); + } +#endif /* SELF_CHECK */ + edgecount++; + onextself(countingtri); + } + +#ifdef SELF_CHECK + if (edgecount < 3) { + printf("Internal error in deletevertex():\n Vertex has degree %d.\n", + edgecount); + internalerror(); + } +#endif /* SELF_CHECK */ + if (edgecount > 3) { + /* Triangulate the polygon defined by the union of all triangles */ + /* adjacent to the vertex being deleted. Check the quality of */ + /* the resulting triangles. */ + onext(*deltri, firstedge); + oprev(*deltri, lastedge); + triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0, + !b->nobisect); + } + /* Splice out two triangles. */ + lprev(*deltri, deltriright); + dnext(*deltri, lefttri); + sym(lefttri, leftcasing); + oprev(deltriright, righttri); + sym(righttri, rightcasing); + bond(*deltri, leftcasing); + bond(deltriright, rightcasing); + tspivot(lefttri, leftsubseg); + if (leftsubseg.ss != m->dummysub) { + tsbond(*deltri, leftsubseg); + } + tspivot(righttri, rightsubseg); + if (rightsubseg.ss != m->dummysub) { + tsbond(deltriright, rightsubseg); + } + + /* Set the new origin of `deltri' and check its quality. */ + org(lefttri, neworg); + setorg(*deltri, neworg); + if (!b->nobisect) { + testtriangle(m, b, deltri); + } + + /* Delete the two spliced-out triangles. */ + triangledealloc(m, lefttri.tri); + triangledealloc(m, righttri.tri); +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* undovertex() Undo the most recent vertex insertion. */ +/* */ +/* Walks through the list of transformations (flips and a vertex insertion) */ +/* in the reverse of the order in which they were done, and undoes them. */ +/* The inserted vertex is removed from the triangulation and deallocated. */ +/* Two triangles (possibly just one) are also deallocated. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void undovertex(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void undovertex(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri fliptri; + struct otri botleft, botright, topright; + struct otri botlcasing, botrcasing, toprcasing; + struct otri gluetri; + struct osub botlsubseg, botrsubseg, toprsubseg; + vertex botvertex, rightvertex; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + /* Walk through the list of transformations (flips and a vertex insertion) */ + /* in the reverse of the order in which they were done, and undo them. */ + while (m->lastflip != (struct flipstacker *) NULL) { + /* Find a triangle involved in the last unreversed transformation. */ + decode(m->lastflip->flippedtri, fliptri); + + /* We are reversing one of three transformations: a trisection of one */ + /* triangle into three (by inserting a vertex in the triangle), a */ + /* bisection of two triangles into four (by inserting a vertex in an */ + /* edge), or an edge flip. */ + if (m->lastflip->prevflip == (struct flipstacker *) NULL) { + /* Restore a triangle that was split into three triangles, */ + /* so it is again one triangle. */ + dprev(fliptri, botleft); + lnextself(botleft); + onext(fliptri, botright); + lprevself(botright); + sym(botleft, botlcasing); + sym(botright, botrcasing); + dest(botleft, botvertex); + + setapex(fliptri, botvertex); + lnextself(fliptri); + bond(fliptri, botlcasing); + tspivot(botleft, botlsubseg); + tsbond(fliptri, botlsubseg); + lnextself(fliptri); + bond(fliptri, botrcasing); + tspivot(botright, botrsubseg); + tsbond(fliptri, botrsubseg); + + /* Delete the two spliced-out triangles. */ + triangledealloc(m, botleft.tri); + triangledealloc(m, botright.tri); + } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) { + /* Restore two triangles that were split into four triangles, */ + /* so they are again two triangles. */ + lprev(fliptri, gluetri); + sym(gluetri, botright); + lnextself(botright); + sym(botright, botrcasing); + dest(botright, rightvertex); + + setorg(fliptri, rightvertex); + bond(gluetri, botrcasing); + tspivot(botright, botrsubseg); + tsbond(gluetri, botrsubseg); + + /* Delete the spliced-out triangle. */ + triangledealloc(m, botright.tri); + + sym(fliptri, gluetri); + if (gluetri.tri != m->dummytri) { + lnextself(gluetri); + dnext(gluetri, topright); + sym(topright, toprcasing); + + setorg(gluetri, rightvertex); + bond(gluetri, toprcasing); + tspivot(topright, toprsubseg); + tsbond(gluetri, toprsubseg); + + /* Delete the spliced-out triangle. */ + triangledealloc(m, topright.tri); + } + + /* This is the end of the list, sneakily encoded. */ + m->lastflip->prevflip = (struct flipstacker *) NULL; + } else { + /* Undo an edge flip. */ + unflip(m, b, &fliptri); + } + + /* Go on and process the next transformation. */ + m->lastflip = m->lastflip->prevflip; + } +} + +#endif /* not CDT_ONLY */ + +/** **/ +/** **/ +/********* Mesh transformation routines end here *********/ + +/********* Divide-and-conquer Delaunay triangulation begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* The divide-and-conquer bounding box */ +/* */ +/* I originally implemented the divide-and-conquer and incremental Delaunay */ +/* triangulations using the edge-based data structure presented by Guibas */ +/* and Stolfi. Switching to a triangle-based data structure doubled the */ +/* speed. However, I had to think of a few extra tricks to maintain the */ +/* elegance of the original algorithms. */ +/* */ +/* The "bounding box" used by my variant of the divide-and-conquer */ +/* algorithm uses one triangle for each edge of the convex hull of the */ +/* triangulation. These bounding triangles all share a common apical */ +/* vertex, which is represented by NULL and which represents nothing. */ +/* The bounding triangles are linked in a circular fan about this NULL */ +/* vertex, and the edges on the convex hull of the triangulation appear */ +/* opposite the NULL vertex. You might find it easiest to imagine that */ +/* the NULL vertex is a point in 3D space behind the center of the */ +/* triangulation, and that the bounding triangles form a sort of cone. */ +/* */ +/* This bounding box makes it easy to represent degenerate cases. For */ +/* instance, the triangulation of two vertices is a single edge. This edge */ +/* is represented by two bounding box triangles, one on each "side" of the */ +/* edge. These triangles are also linked together in a fan about the NULL */ +/* vertex. */ +/* */ +/* The bounding box also makes it easy to traverse the convex hull, as the */ +/* divide-and-conquer algorithm needs to do. */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* vertexsort() Sort an array of vertices by x-coordinate, using the */ +/* y-coordinate as a secondary key. */ +/* */ +/* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */ +/* the usual quicksort mistakes. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void vertexsort(vertex *sortarray, int arraysize) +#else /* not ANSI_DECLARATORS */ +void vertexsort(sortarray, arraysize) +vertex *sortarray; +int arraysize; +#endif /* not ANSI_DECLARATORS */ + +{ + int left, right; + int pivot; + REAL pivotx, pivoty; + vertex temp; + + if (arraysize == 2) { + /* Recursive base case. */ + if ((sortarray[0][0] > sortarray[1][0]) || + ((sortarray[0][0] == sortarray[1][0]) && + (sortarray[0][1] > sortarray[1][1]))) { + temp = sortarray[1]; + sortarray[1] = sortarray[0]; + sortarray[0] = temp; + } + return; + } + /* Choose a random pivot to split the array. */ + pivot = (int) randomnation((unsigned int) arraysize); + pivotx = sortarray[pivot][0]; + pivoty = sortarray[pivot][1]; + /* Split the array. */ + left = -1; + right = arraysize; + while (left < right) { + /* Search for a vertex whose x-coordinate is too large for the left. */ + do { + left++; + } while ((left <= right) && ((sortarray[left][0] < pivotx) || + ((sortarray[left][0] == pivotx) && + (sortarray[left][1] < pivoty)))); + /* Search for a vertex whose x-coordinate is too small for the right. */ + do { + right--; + } while ((left <= right) && ((sortarray[right][0] > pivotx) || + ((sortarray[right][0] == pivotx) && + (sortarray[right][1] > pivoty)))); + if (left < right) { + /* Swap the left and right vertices. */ + temp = sortarray[left]; + sortarray[left] = sortarray[right]; + sortarray[right] = temp; + } + } + if (left > 1) { + /* Recursively sort the left subset. */ + vertexsort(sortarray, left); + } + if (right < arraysize - 2) { + /* Recursively sort the right subset. */ + vertexsort(&sortarray[right + 1], arraysize - right - 1); + } +} + +/*****************************************************************************/ +/* */ +/* vertexmedian() An order statistic algorithm, almost. Shuffles an */ +/* array of vertices so that the first `median' vertices */ +/* occur lexicographically before the remaining vertices. */ +/* */ +/* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */ +/* if axis == 1. Very similar to the vertexsort() procedure, but runs in */ +/* randomized linear time. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void vertexmedian(vertex *sortarray, int arraysize, int median, int axis) +#else /* not ANSI_DECLARATORS */ +void vertexmedian(sortarray, arraysize, median, axis) +vertex *sortarray; +int arraysize; +int median; +int axis; +#endif /* not ANSI_DECLARATORS */ + +{ + int left, right; + int pivot; + REAL pivot1, pivot2; + vertex temp; + + if (arraysize == 2) { + /* Recursive base case. */ + if ((sortarray[0][axis] > sortarray[1][axis]) || + ((sortarray[0][axis] == sortarray[1][axis]) && + (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) { + temp = sortarray[1]; + sortarray[1] = sortarray[0]; + sortarray[0] = temp; + } + return; + } + /* Choose a random pivot to split the array. */ + pivot = (int) randomnation((unsigned int) arraysize); + pivot1 = sortarray[pivot][axis]; + pivot2 = sortarray[pivot][1 - axis]; + /* Split the array. */ + left = -1; + right = arraysize; + while (left < right) { + /* Search for a vertex whose x-coordinate is too large for the left. */ + do { + left++; + } while ((left <= right) && ((sortarray[left][axis] < pivot1) || + ((sortarray[left][axis] == pivot1) && + (sortarray[left][1 - axis] < pivot2)))); + /* Search for a vertex whose x-coordinate is too small for the right. */ + do { + right--; + } while ((left <= right) && ((sortarray[right][axis] > pivot1) || + ((sortarray[right][axis] == pivot1) && + (sortarray[right][1 - axis] > pivot2)))); + if (left < right) { + /* Swap the left and right vertices. */ + temp = sortarray[left]; + sortarray[left] = sortarray[right]; + sortarray[right] = temp; + } + } + /* Unlike in vertexsort(), at most one of the following */ + /* conditionals is true. */ + if (left > median) { + /* Recursively shuffle the left subset. */ + vertexmedian(sortarray, left, median, axis); + } + if (right < median - 1) { + /* Recursively shuffle the right subset. */ + vertexmedian(&sortarray[right + 1], arraysize - right - 1, + median - right - 1, axis); + } +} + +/*****************************************************************************/ +/* */ +/* alternateaxes() Sorts the vertices as appropriate for the divide-and- */ +/* conquer algorithm with alternating cuts. */ +/* */ +/* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */ +/* For the base case, subsets containing only two or three vertices are */ +/* always sorted by x-coordinate. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void alternateaxes(vertex *sortarray, int arraysize, int axis) +#else /* not ANSI_DECLARATORS */ +void alternateaxes(sortarray, arraysize, axis) +vertex *sortarray; +int arraysize; +int axis; +#endif /* not ANSI_DECLARATORS */ + +{ + int divider; + + divider = arraysize >> 1; + if (arraysize <= 3) { + /* Recursive base case: subsets of two or three vertices will be */ + /* handled specially, and should always be sorted by x-coordinate. */ + axis = 0; + } + /* Partition with a horizontal or vertical cut. */ + vertexmedian(sortarray, arraysize, divider, axis); + /* Recursively partition the subsets with a cross cut. */ + if (arraysize - divider >= 2) { + if (divider >= 2) { + alternateaxes(sortarray, divider, 1 - axis); + } + alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis); + } +} + +/*****************************************************************************/ +/* */ +/* mergehulls() Merge two adjacent Delaunay triangulations into a */ +/* single Delaunay triangulation. */ +/* */ +/* This is similar to the algorithm given by Guibas and Stolfi, but uses */ +/* a triangle-based, rather than edge-based, data structure. */ +/* */ +/* The algorithm walks up the gap between the two triangulations, knitting */ +/* them together. As they are merged, some of their bounding triangles */ +/* are converted into real triangles of the triangulation. The procedure */ +/* pulls each hull's bounding triangles apart, then knits them together */ +/* like the teeth of two gears. The Delaunay property determines, at each */ +/* step, whether the next "tooth" is a bounding triangle of the left hull */ +/* or the right. When a bounding triangle becomes real, its apex is */ +/* changed from NULL to a real vertex. */ +/* */ +/* Only two new triangles need to be allocated. These become new bounding */ +/* triangles at the top and bottom of the seam. They are used to connect */ +/* the remaining bounding triangles (those that have not been converted */ +/* into real triangles) into a single fan. */ +/* */ +/* On entry, `farleft' and `innerleft' are bounding triangles of the left */ +/* triangulation. The origin of `farleft' is the leftmost vertex, and */ +/* the destination of `innerleft' is the rightmost vertex of the */ +/* triangulation. Similarly, `innerright' and `farright' are bounding */ +/* triangles of the right triangulation. The origin of `innerright' and */ +/* destination of `farright' are the leftmost and rightmost vertices. */ +/* */ +/* On completion, the origin of `farleft' is the leftmost vertex of the */ +/* merged triangulation, and the destination of `farright' is the rightmost */ +/* vertex. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, + struct otri *innerleft, struct otri *innerright, + struct otri *farright, int axis) +#else /* not ANSI_DECLARATORS */ +void mergehulls(m, b, farleft, innerleft, innerright, farright, axis) +struct mesh *m; +struct behavior *b; +struct otri *farleft; +struct otri *innerleft; +struct otri *innerright; +struct otri *farright; +int axis; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri leftcand, rightcand; + struct otri baseedge; + struct otri nextedge; + struct otri sidecasing, topcasing, outercasing; + struct otri checkedge; + vertex innerleftdest; + vertex innerrightorg; + vertex innerleftapex, innerrightapex; + vertex farleftpt, farrightpt; + vertex farleftapex, farrightapex; + vertex lowerleft, lowerright; + vertex upperleft, upperright; + vertex nextapex; + vertex checkvertex; + int changemade; + int badedge; + int leftfinished, rightfinished; + triangle ptr; /* Temporary variable used by sym(). */ + + dest(*innerleft, innerleftdest); + apex(*innerleft, innerleftapex); + org(*innerright, innerrightorg); + apex(*innerright, innerrightapex); + /* Special treatment for horizontal cuts. */ + if (b->dwyer && (axis == 1)) { + org(*farleft, farleftpt); + apex(*farleft, farleftapex); + dest(*farright, farrightpt); + apex(*farright, farrightapex); + /* The pointers to the extremal vertices are shifted to point to the */ + /* topmost and bottommost vertex of each hull, rather than the */ + /* leftmost and rightmost vertices. */ + while (farleftapex[1] < farleftpt[1]) { + lnextself(*farleft); + symself(*farleft); + farleftpt = farleftapex; + apex(*farleft, farleftapex); + } + sym(*innerleft, checkedge); + apex(checkedge, checkvertex); + while (checkvertex[1] > innerleftdest[1]) { + lnext(checkedge, *innerleft); + innerleftapex = innerleftdest; + innerleftdest = checkvertex; + sym(*innerleft, checkedge); + apex(checkedge, checkvertex); + } + while (innerrightapex[1] < innerrightorg[1]) { + lnextself(*innerright); + symself(*innerright); + innerrightorg = innerrightapex; + apex(*innerright, innerrightapex); + } + sym(*farright, checkedge); + apex(checkedge, checkvertex); + while (checkvertex[1] > farrightpt[1]) { + lnext(checkedge, *farright); + farrightapex = farrightpt; + farrightpt = checkvertex; + sym(*farright, checkedge); + apex(checkedge, checkvertex); + } + } + /* Find a line tangent to and below both hulls. */ + do { + changemade = 0; + /* Make innerleftdest the "bottommost" vertex of the left hull. */ + if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) > + 0.0) { + lprevself(*innerleft); + symself(*innerleft); + innerleftdest = innerleftapex; + apex(*innerleft, innerleftapex); + changemade = 1; + } + /* Make innerrightorg the "bottommost" vertex of the right hull. */ + if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) > + 0.0) { + lnextself(*innerright); + symself(*innerright); + innerrightorg = innerrightapex; + apex(*innerright, innerrightapex); + changemade = 1; + } + } while (changemade); + /* Find the two candidates to be the next "gear tooth." */ + sym(*innerleft, leftcand); + sym(*innerright, rightcand); + /* Create the bottom new bounding triangle. */ + maketriangle(m, b, &baseedge); + /* Connect it to the bounding boxes of the left and right triangulations. */ + bond(baseedge, *innerleft); + lnextself(baseedge); + bond(baseedge, *innerright); + lnextself(baseedge); + setorg(baseedge, innerrightorg); + setdest(baseedge, innerleftdest); + /* Apex is intentionally left NULL. */ + if (b->verbose > 2) { + printf(" Creating base bounding "); + printtriangle(m, b, &baseedge); + } + /* Fix the extreme triangles if necessary. */ + org(*farleft, farleftpt); + if (innerleftdest == farleftpt) { + lnext(baseedge, *farleft); + } + dest(*farright, farrightpt); + if (innerrightorg == farrightpt) { + lprev(baseedge, *farright); + } + /* The vertices of the current knitting edge. */ + lowerleft = innerleftdest; + lowerright = innerrightorg; + /* The candidate vertices for knitting. */ + apex(leftcand, upperleft); + apex(rightcand, upperright); + /* Walk up the gap between the two triangulations, knitting them together. */ + while (1) { + /* Have we reached the top? (This isn't quite the right question, */ + /* because even though the left triangulation might seem finished now, */ + /* moving up on the right triangulation might reveal a new vertex of */ + /* the left triangulation. And vice-versa.) */ + leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <= + 0.0; + rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright) + <= 0.0; + if (leftfinished && rightfinished) { + /* Create the top new bounding triangle. */ + maketriangle(m, b, &nextedge); + setorg(nextedge, lowerleft); + setdest(nextedge, lowerright); + /* Apex is intentionally left NULL. */ + /* Connect it to the bounding boxes of the two triangulations. */ + bond(nextedge, baseedge); + lnextself(nextedge); + bond(nextedge, rightcand); + lnextself(nextedge); + bond(nextedge, leftcand); + if (b->verbose > 2) { + printf(" Creating top bounding "); + printtriangle(m, b, &nextedge); + } + /* Special treatment for horizontal cuts. */ + if (b->dwyer && (axis == 1)) { + org(*farleft, farleftpt); + apex(*farleft, farleftapex); + dest(*farright, farrightpt); + apex(*farright, farrightapex); + sym(*farleft, checkedge); + apex(checkedge, checkvertex); + /* The pointers to the extremal vertices are restored to the */ + /* leftmost and rightmost vertices (rather than topmost and */ + /* bottommost). */ + while (checkvertex[0] < farleftpt[0]) { + lprev(checkedge, *farleft); + farleftapex = farleftpt; + farleftpt = checkvertex; + sym(*farleft, checkedge); + apex(checkedge, checkvertex); + } + while (farrightapex[0] > farrightpt[0]) { + lprevself(*farright); + symself(*farright); + farrightpt = farrightapex; + apex(*farright, farrightapex); + } + } + return; + } + /* Consider eliminating edges from the left triangulation. */ + if (!leftfinished) { + /* What vertex would be exposed if an edge were deleted? */ + lprev(leftcand, nextedge); + symself(nextedge); + apex(nextedge, nextapex); + /* If nextapex is NULL, then no vertex would be exposed; the */ + /* triangulation would have been eaten right through. */ + if (nextapex != (vertex) NULL) { + /* Check whether the edge is Delaunay. */ + badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) > + 0.0; + while (badedge) { + /* Eliminate the edge with an edge flip. As a result, the */ + /* left triangulation will have one more boundary triangle. */ + lnextself(nextedge); + sym(nextedge, topcasing); + lnextself(nextedge); + sym(nextedge, sidecasing); + bond(nextedge, topcasing); + bond(leftcand, sidecasing); + lnextself(leftcand); + sym(leftcand, outercasing); + lprevself(nextedge); + bond(nextedge, outercasing); + /* Correct the vertices to reflect the edge flip. */ + setorg(leftcand, lowerleft); + setdest(leftcand, NULL); + setapex(leftcand, nextapex); + setorg(nextedge, NULL); + setdest(nextedge, upperleft); + setapex(nextedge, nextapex); + /* Consider the newly exposed vertex. */ + upperleft = nextapex; + /* What vertex would be exposed if another edge were deleted? */ + otricopy(sidecasing, nextedge); + apex(nextedge, nextapex); + if (nextapex != (vertex) NULL) { + /* Check whether the edge is Delaunay. */ + badedge = incircle(m, b, lowerleft, lowerright, upperleft, + nextapex) > 0.0; + } else { + /* Avoid eating right through the triangulation. */ + badedge = 0; + } + } + } + } + /* Consider eliminating edges from the right triangulation. */ + if (!rightfinished) { + /* What vertex would be exposed if an edge were deleted? */ + lnext(rightcand, nextedge); + symself(nextedge); + apex(nextedge, nextapex); + /* If nextapex is NULL, then no vertex would be exposed; the */ + /* triangulation would have been eaten right through. */ + if (nextapex != (vertex) NULL) { + /* Check whether the edge is Delaunay. */ + badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) > + 0.0; + while (badedge) { + /* Eliminate the edge with an edge flip. As a result, the */ + /* right triangulation will have one more boundary triangle. */ + lprevself(nextedge); + sym(nextedge, topcasing); + lprevself(nextedge); + sym(nextedge, sidecasing); + bond(nextedge, topcasing); + bond(rightcand, sidecasing); + lprevself(rightcand); + sym(rightcand, outercasing); + lnextself(nextedge); + bond(nextedge, outercasing); + /* Correct the vertices to reflect the edge flip. */ + setorg(rightcand, NULL); + setdest(rightcand, lowerright); + setapex(rightcand, nextapex); + setorg(nextedge, upperright); + setdest(nextedge, NULL); + setapex(nextedge, nextapex); + /* Consider the newly exposed vertex. */ + upperright = nextapex; + /* What vertex would be exposed if another edge were deleted? */ + otricopy(sidecasing, nextedge); + apex(nextedge, nextapex); + if (nextapex != (vertex) NULL) { + /* Check whether the edge is Delaunay. */ + badedge = incircle(m, b, lowerleft, lowerright, upperright, + nextapex) > 0.0; + } else { + /* Avoid eating right through the triangulation. */ + badedge = 0; + } + } + } + } + if (leftfinished || (!rightfinished && + (incircle(m, b, upperleft, lowerleft, lowerright, upperright) > + 0.0))) { + /* Knit the triangulations, adding an edge from `lowerleft' */ + /* to `upperright'. */ + bond(baseedge, rightcand); + lprev(rightcand, baseedge); + setdest(baseedge, lowerleft); + lowerright = upperright; + sym(baseedge, rightcand); + apex(rightcand, upperright); + } else { + /* Knit the triangulations, adding an edge from `upperleft' */ + /* to `lowerright'. */ + bond(baseedge, leftcand); + lnext(leftcand, baseedge); + setorg(baseedge, lowerright); + lowerleft = upperleft; + sym(baseedge, leftcand); + apex(leftcand, upperleft); + } + if (b->verbose > 2) { + printf(" Connecting "); + printtriangle(m, b, &baseedge); + } + } +} + +/*****************************************************************************/ +/* */ +/* divconqrecurse() Recursively form a Delaunay triangulation by the */ +/* divide-and-conquer method. */ +/* */ +/* Recursively breaks down the problem into smaller pieces, which are */ +/* knitted together by mergehulls(). The base cases (problems of two or */ +/* three vertices) are handled specially here. */ +/* */ +/* On completion, `farleft' and `farright' are bounding triangles such that */ +/* the origin of `farleft' is the leftmost vertex (breaking ties by */ +/* choosing the highest leftmost vertex), and the destination of */ +/* `farright' is the rightmost vertex (breaking ties by choosing the */ +/* lowest rightmost vertex). */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, + int vertices, int axis, + struct otri *farleft, struct otri *farright) +#else /* not ANSI_DECLARATORS */ +void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright) +struct mesh *m; +struct behavior *b; +vertex *sortarray; +int vertices; +int axis; +struct otri *farleft; +struct otri *farright; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri midtri, tri1, tri2, tri3; + struct otri innerleft, innerright; + REAL area; + int divider; + + if (b->verbose > 2) { + printf(" Triangulating %d vertices.\n", vertices); + } + if (vertices == 2) { + /* The triangulation of two vertices is an edge. An edge is */ + /* represented by two bounding triangles. */ + maketriangle(m, b, farleft); + setorg(*farleft, sortarray[0]); + setdest(*farleft, sortarray[1]); + /* The apex is intentionally left NULL. */ + maketriangle(m, b, farright); + setorg(*farright, sortarray[1]); + setdest(*farright, sortarray[0]); + /* The apex is intentionally left NULL. */ + bond(*farleft, *farright); + lprevself(*farleft); + lnextself(*farright); + bond(*farleft, *farright); + lprevself(*farleft); + lnextself(*farright); + bond(*farleft, *farright); + if (b->verbose > 2) { + printf(" Creating "); + printtriangle(m, b, farleft); + printf(" Creating "); + printtriangle(m, b, farright); + } + /* Ensure that the origin of `farleft' is sortarray[0]. */ + lprev(*farright, *farleft); + return; + } else if (vertices == 3) { + /* The triangulation of three vertices is either a triangle (with */ + /* three bounding triangles) or two edges (with four bounding */ + /* triangles). In either case, four triangles are created. */ + maketriangle(m, b, &midtri); + maketriangle(m, b, &tri1); + maketriangle(m, b, &tri2); + maketriangle(m, b, &tri3); + area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]); + if (area == 0.0) { + /* Three collinear vertices; the triangulation is two edges. */ + setorg(midtri, sortarray[0]); + setdest(midtri, sortarray[1]); + setorg(tri1, sortarray[1]); + setdest(tri1, sortarray[0]); + setorg(tri2, sortarray[2]); + setdest(tri2, sortarray[1]); + setorg(tri3, sortarray[1]); + setdest(tri3, sortarray[2]); + /* All apices are intentionally left NULL. */ + bond(midtri, tri1); + bond(tri2, tri3); + lnextself(midtri); + lprevself(tri1); + lnextself(tri2); + lprevself(tri3); + bond(midtri, tri3); + bond(tri1, tri2); + lnextself(midtri); + lprevself(tri1); + lnextself(tri2); + lprevself(tri3); + bond(midtri, tri1); + bond(tri2, tri3); + /* Ensure that the origin of `farleft' is sortarray[0]. */ + otricopy(tri1, *farleft); + /* Ensure that the destination of `farright' is sortarray[2]. */ + otricopy(tri2, *farright); + } else { + /* The three vertices are not collinear; the triangulation is one */ + /* triangle, namely `midtri'. */ + setorg(midtri, sortarray[0]); + setdest(tri1, sortarray[0]); + setorg(tri3, sortarray[0]); + /* Apices of tri1, tri2, and tri3 are left NULL. */ + if (area > 0.0) { + /* The vertices are in counterclockwise order. */ + setdest(midtri, sortarray[1]); + setorg(tri1, sortarray[1]); + setdest(tri2, sortarray[1]); + setapex(midtri, sortarray[2]); + setorg(tri2, sortarray[2]); + setdest(tri3, sortarray[2]); + } else { + /* The vertices are in clockwise order. */ + setdest(midtri, sortarray[2]); + setorg(tri1, sortarray[2]); + setdest(tri2, sortarray[2]); + setapex(midtri, sortarray[1]); + setorg(tri2, sortarray[1]); + setdest(tri3, sortarray[1]); + } + /* The topology does not depend on how the vertices are ordered. */ + bond(midtri, tri1); + lnextself(midtri); + bond(midtri, tri2); + lnextself(midtri); + bond(midtri, tri3); + lprevself(tri1); + lnextself(tri2); + bond(tri1, tri2); + lprevself(tri1); + lprevself(tri3); + bond(tri1, tri3); + lnextself(tri2); + lprevself(tri3); + bond(tri2, tri3); + /* Ensure that the origin of `farleft' is sortarray[0]. */ + otricopy(tri1, *farleft); + /* Ensure that the destination of `farright' is sortarray[2]. */ + if (area > 0.0) { + otricopy(tri2, *farright); + } else { + lnext(*farleft, *farright); + } + } + if (b->verbose > 2) { + printf(" Creating "); + printtriangle(m, b, &midtri); + printf(" Creating "); + printtriangle(m, b, &tri1); + printf(" Creating "); + printtriangle(m, b, &tri2); + printf(" Creating "); + printtriangle(m, b, &tri3); + } + return; + } else { + /* Split the vertices in half. */ + divider = vertices >> 1; + /* Recursively triangulate each half. */ + divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft); + divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis, + &innerright, farright); + if (b->verbose > 1) { + printf(" Joining triangulations with %d and %d vertices.\n", divider, + vertices - divider); + } + /* Merge the two triangulations into one. */ + mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis); + } +} + +#ifdef ANSI_DECLARATORS +long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost) +#else /* not ANSI_DECLARATORS */ +long removeghosts(m, b, startghost) +struct mesh *m; +struct behavior *b; +struct otri *startghost; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri searchedge; + struct otri dissolveedge; + struct otri deadtriangle; + vertex markorg; + long hullsize; + triangle ptr; /* Temporary variable used by sym(). */ + + if (b->verbose) { + printf(" Removing ghost triangles.\n"); + } + /* Find an edge on the convex hull to start point location from. */ + lprev(*startghost, searchedge); + symself(searchedge); + m->dummytri[0] = encode(searchedge); + /* Remove the bounding box and count the convex hull edges. */ + otricopy(*startghost, dissolveedge); + hullsize = 0; + do { + hullsize++; + lnext(dissolveedge, deadtriangle); + lprevself(dissolveedge); + symself(dissolveedge); + /* If no PSLG is involved, set the boundary markers of all the vertices */ + /* on the convex hull. If a PSLG is used, this step is done later. */ + if (!b->poly) { + /* Watch out for the case where all the input vertices are collinear. */ + if (dissolveedge.tri != m->dummytri) { + org(dissolveedge, markorg); + if (vertexmark(markorg) == 0) { + setvertexmark(markorg, 1); + } + } + } + /* Remove a bounding triangle from a convex hull triangle. */ + dissolve(dissolveedge); + /* Find the next bounding triangle. */ + sym(deadtriangle, dissolveedge); + /* Delete the bounding triangle. */ + triangledealloc(m, deadtriangle.tri); + } while (!otriequal(dissolveedge, *startghost)); + return hullsize; +} + +/*****************************************************************************/ +/* */ +/* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */ +/* conquer method. */ +/* */ +/* Sorts the vertices, calls a recursive procedure to triangulate them, and */ +/* removes the bounding box, setting boundary markers as appropriate. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +long divconqdelaunay(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +long divconqdelaunay(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex *sortarray; + struct otri hullleft, hullright; + int divider; + int i, j; + + if (b->verbose) { + printf(" Sorting vertices.\n"); + } + + /* Allocate an array of pointers to vertices for sorting. */ + sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex)); + traversalinit(&m->vertices); + for (i = 0; i < m->invertices; i++) { + sortarray[i] = vertextraverse(m); + } + /* Sort the vertices. */ + vertexsort(sortarray, m->invertices); + /* Discard duplicate vertices, which can really mess up the algorithm. */ + i = 0; + for (j = 1; j < m->invertices; j++) { + if ((sortarray[i][0] == sortarray[j][0]) + && (sortarray[i][1] == sortarray[j][1])) { + if (!b->quiet) { + printf( +"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", + sortarray[j][0], sortarray[j][1]); + } + setvertextype(sortarray[j], UNDEADVERTEX); + m->undeads++; + } else { + i++; + sortarray[i] = sortarray[j]; + } + } + i++; + if (b->dwyer) { + /* Re-sort the array of vertices to accommodate alternating cuts. */ + divider = i >> 1; + if (i - divider >= 2) { + if (divider >= 2) { + alternateaxes(sortarray, divider, 1); + } + alternateaxes(&sortarray[divider], i - divider, 1); + } + } + + if (b->verbose) { + printf(" Forming triangulation.\n"); + } + + /* Form the Delaunay triangulation. */ + divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright); + trifree((VOID *) sortarray); + + return removeghosts(m, b, &hullleft); +} + +/** **/ +/** **/ +/********* Divide-and-conquer Delaunay triangulation ends here *********/ + +/********* Incremental Delaunay triangulation begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* boundingbox() Form an "infinite" bounding triangle to insert vertices */ +/* into. */ +/* */ +/* The vertices at "infinity" are assigned finite coordinates, which are */ +/* used by the point location routines, but (mostly) ignored by the */ +/* Delaunay edge flip routines. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void boundingbox(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void boundingbox(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri inftri; /* Handle for the triangular bounding box. */ + REAL width; + + if (b->verbose) { + printf(" Creating triangular bounding box.\n"); + } + /* Find the width (or height, whichever is larger) of the triangulation. */ + width = m->xmax - m->xmin; + if (m->ymax - m->ymin > width) { + width = m->ymax - m->ymin; + } + if (width == 0.0) { + width = 1.0; + } + /* Create the vertices of the bounding box. */ + m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes); + m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes); + m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes); + m->infvertex1[0] = m->xmin - 50.0 * width; + m->infvertex1[1] = m->ymin - 40.0 * width; + m->infvertex2[0] = m->xmax + 50.0 * width; + m->infvertex2[1] = m->ymin - 40.0 * width; + m->infvertex3[0] = 0.5 * (m->xmin + m->xmax); + m->infvertex3[1] = m->ymax + 60.0 * width; + + /* Create the bounding box. */ + maketriangle(m, b, &inftri); + setorg(inftri, m->infvertex1); + setdest(inftri, m->infvertex2); + setapex(inftri, m->infvertex3); + /* Link dummytri to the bounding box so we can always find an */ + /* edge to begin searching (point location) from. */ + m->dummytri[0] = (triangle) inftri.tri; + if (b->verbose > 2) { + printf(" Creating "); + printtriangle(m, b, &inftri); + } +} + +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* removebox() Remove the "infinite" bounding triangle, setting boundary */ +/* markers as appropriate. */ +/* */ +/* The triangular bounding box has three boundary triangles (one for each */ +/* side of the bounding box), and a bunch of triangles fanning out from */ +/* the three bounding box vertices (one triangle for each edge of the */ +/* convex hull of the inner mesh). This routine removes these triangles. */ +/* */ +/* Returns the number of edges on the convex hull of the triangulation. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +long removebox(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +long removebox(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri deadtriangle; + struct otri searchedge; + struct otri checkedge; + struct otri nextedge, finaledge, dissolveedge; + vertex markorg; + long hullsize; + triangle ptr; /* Temporary variable used by sym(). */ + + if (b->verbose) { + printf(" Removing triangular bounding box.\n"); + } + /* Find a boundary triangle. */ + nextedge.tri = m->dummytri; + nextedge.orient = 0; + symself(nextedge); + /* Mark a place to stop. */ + lprev(nextedge, finaledge); + lnextself(nextedge); + symself(nextedge); + /* Find a triangle (on the boundary of the vertex set) that isn't */ + /* a bounding box triangle. */ + lprev(nextedge, searchedge); + symself(searchedge); + /* Check whether nextedge is another boundary triangle */ + /* adjacent to the first one. */ + lnext(nextedge, checkedge); + symself(checkedge); + if (checkedge.tri == m->dummytri) { + /* Go on to the next triangle. There are only three boundary */ + /* triangles, and this next triangle cannot be the third one, */ + /* so it's safe to stop here. */ + lprevself(searchedge); + symself(searchedge); + } + /* Find a new boundary edge to search from, as the current search */ + /* edge lies on a bounding box triangle and will be deleted. */ + m->dummytri[0] = encode(searchedge); + hullsize = -2l; + while (!otriequal(nextedge, finaledge)) { + hullsize++; + lprev(nextedge, dissolveedge); + symself(dissolveedge); + /* If not using a PSLG, the vertices should be marked now. */ + /* (If using a PSLG, markhull() will do the job.) */ + if (!b->poly) { + /* Be careful! One must check for the case where all the input */ + /* vertices are collinear, and thus all the triangles are part of */ + /* the bounding box. Otherwise, the setvertexmark() call below */ + /* will cause a bad pointer reference. */ + if (dissolveedge.tri != m->dummytri) { + org(dissolveedge, markorg); + if (vertexmark(markorg) == 0) { + setvertexmark(markorg, 1); + } + } + } + /* Disconnect the bounding box triangle from the mesh triangle. */ + dissolve(dissolveedge); + lnext(nextedge, deadtriangle); + sym(deadtriangle, nextedge); + /* Get rid of the bounding box triangle. */ + triangledealloc(m, deadtriangle.tri); + /* Do we need to turn the corner? */ + if (nextedge.tri == m->dummytri) { + /* Turn the corner. */ + otricopy(dissolveedge, nextedge); + } + } + triangledealloc(m, finaledge.tri); + + trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */ + trifree((VOID *) m->infvertex2); + trifree((VOID *) m->infvertex3); + + return hullsize; +} + +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* incrementaldelaunay() Form a Delaunay triangulation by incrementally */ +/* inserting vertices. */ +/* */ +/* Returns the number of edges on the convex hull of the triangulation. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +long incrementaldelaunay(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +long incrementaldelaunay(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri starttri; + vertex vertexloop; + + /* Create a triangular bounding box. */ + boundingbox(m, b); + if (b->verbose) { + printf(" Incrementally inserting vertices.\n"); + } + traversalinit(&m->vertices); + vertexloop = vertextraverse(m); + while (vertexloop != (vertex) NULL) { + starttri.tri = m->dummytri; + if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0) + == DUPLICATEVERTEX) { + if (!b->quiet) { + printf( +"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", + vertexloop[0], vertexloop[1]); + } + setvertextype(vertexloop, UNDEADVERTEX); + m->undeads++; + } + vertexloop = vertextraverse(m); + } + /* Remove the bounding box. */ + return removebox(m, b); +} + +#endif /* not REDUCED */ + +/** **/ +/** **/ +/********* Incremental Delaunay triangulation ends here *********/ + +/********* Sweepline Delaunay triangulation begins here *********/ +/** **/ +/** **/ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void eventheapinsert(struct event **heap, int heapsize, struct event *newevent) +#else /* not ANSI_DECLARATORS */ +void eventheapinsert(heap, heapsize, newevent) +struct event **heap; +int heapsize; +struct event *newevent; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL eventx, eventy; + int eventnum; + int parent; + int notdone; + + eventx = newevent->xkey; + eventy = newevent->ykey; + eventnum = heapsize; + notdone = eventnum > 0; + while (notdone) { + parent = (eventnum - 1) >> 1; + if ((heap[parent]->ykey < eventy) || + ((heap[parent]->ykey == eventy) + && (heap[parent]->xkey <= eventx))) { + notdone = 0; + } else { + heap[eventnum] = heap[parent]; + heap[eventnum]->heapposition = eventnum; + + eventnum = parent; + notdone = eventnum > 0; + } + } + heap[eventnum] = newevent; + newevent->heapposition = eventnum; +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void eventheapify(struct event **heap, int heapsize, int eventnum) +#else /* not ANSI_DECLARATORS */ +void eventheapify(heap, heapsize, eventnum) +struct event **heap; +int heapsize; +int eventnum; +#endif /* not ANSI_DECLARATORS */ + +{ + struct event *thisevent; + REAL eventx, eventy; + int leftchild, rightchild; + int smallest; + int notdone; + + thisevent = heap[eventnum]; + eventx = thisevent->xkey; + eventy = thisevent->ykey; + leftchild = 2 * eventnum + 1; + notdone = leftchild < heapsize; + while (notdone) { + if ((heap[leftchild]->ykey < eventy) || + ((heap[leftchild]->ykey == eventy) + && (heap[leftchild]->xkey < eventx))) { + smallest = leftchild; + } else { + smallest = eventnum; + } + rightchild = leftchild + 1; + if (rightchild < heapsize) { + if ((heap[rightchild]->ykey < heap[smallest]->ykey) || + ((heap[rightchild]->ykey == heap[smallest]->ykey) + && (heap[rightchild]->xkey < heap[smallest]->xkey))) { + smallest = rightchild; + } + } + if (smallest == eventnum) { + notdone = 0; + } else { + heap[eventnum] = heap[smallest]; + heap[eventnum]->heapposition = eventnum; + heap[smallest] = thisevent; + thisevent->heapposition = smallest; + + eventnum = smallest; + leftchild = 2 * eventnum + 1; + notdone = leftchild < heapsize; + } + } +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void eventheapdelete(struct event **heap, int heapsize, int eventnum) +#else /* not ANSI_DECLARATORS */ +void eventheapdelete(heap, heapsize, eventnum) +struct event **heap; +int heapsize; +int eventnum; +#endif /* not ANSI_DECLARATORS */ + +{ + struct event *moveevent; + REAL eventx, eventy; + int parent; + int notdone; + + moveevent = heap[heapsize - 1]; + if (eventnum > 0) { + eventx = moveevent->xkey; + eventy = moveevent->ykey; + do { + parent = (eventnum - 1) >> 1; + if ((heap[parent]->ykey < eventy) || + ((heap[parent]->ykey == eventy) + && (heap[parent]->xkey <= eventx))) { + notdone = 0; + } else { + heap[eventnum] = heap[parent]; + heap[eventnum]->heapposition = eventnum; + + eventnum = parent; + notdone = eventnum > 0; + } + } while (notdone); + } + heap[eventnum] = moveevent; + moveevent->heapposition = eventnum; + eventheapify(heap, heapsize - 1, eventnum); +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void createeventheap(struct mesh *m, struct event ***eventheap, + struct event **events, struct event **freeevents) +#else /* not ANSI_DECLARATORS */ +void createeventheap(m, eventheap, events, freeevents) +struct mesh *m; +struct event ***eventheap; +struct event **events; +struct event **freeevents; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex thisvertex; + int maxevents; + int i; + + maxevents = (3 * m->invertices) / 2; + *eventheap = (struct event **) trimalloc(maxevents * + (int) sizeof(struct event *)); + *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event)); + traversalinit(&m->vertices); + for (i = 0; i < m->invertices; i++) { + thisvertex = vertextraverse(m); + (*events)[i].eventptr = (VOID *) thisvertex; + (*events)[i].xkey = thisvertex[0]; + (*events)[i].ykey = thisvertex[1]; + eventheapinsert(*eventheap, i, *events + i); + } + *freeevents = (struct event *) NULL; + for (i = maxevents - 1; i >= m->invertices; i--) { + (*events)[i].eventptr = (VOID *) *freeevents; + *freeevents = *events + i; + } +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite) +#else /* not ANSI_DECLARATORS */ +int rightofhyperbola(m, fronttri, newsite) +struct mesh *m; +struct otri *fronttri; +vertex newsite; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex leftvertex, rightvertex; + REAL dxa, dya, dxb, dyb; + + m->hyperbolacount++; + + dest(*fronttri, leftvertex); + apex(*fronttri, rightvertex); + if ((leftvertex[1] < rightvertex[1]) || + ((leftvertex[1] == rightvertex[1]) && + (leftvertex[0] < rightvertex[0]))) { + if (newsite[0] >= rightvertex[0]) { + return 1; + } + } else { + if (newsite[0] <= leftvertex[0]) { + return 0; + } + } + dxa = leftvertex[0] - newsite[0]; + dya = leftvertex[1] - newsite[1]; + dxb = rightvertex[0] - newsite[0]; + dyb = rightvertex[1] - newsite[1]; + return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya); +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc) +#else /* not ANSI_DECLARATORS */ +REAL circletop(m, pa, pb, pc, ccwabc) +struct mesh *m; +vertex pa; +vertex pb; +vertex pc; +REAL ccwabc; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL xac, yac, xbc, ybc, xab, yab; + REAL aclen2, bclen2, ablen2; + + m->circletopcount++; + + xac = pa[0] - pc[0]; + yac = pa[1] - pc[1]; + xbc = pb[0] - pc[0]; + ybc = pb[1] - pc[1]; + xab = pa[0] - pb[0]; + yab = pa[1] - pb[1]; + aclen2 = xac * xac + yac * yac; + bclen2 = xbc * xbc + ybc * ybc; + ablen2 = xab * xab + yab * yab; + return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2)) + / (2.0 * ccwabc); +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +void check4deadevent(struct otri *checktri, struct event **freeevents, + struct event **eventheap, int *heapsize) +#else /* not ANSI_DECLARATORS */ +void check4deadevent(checktri, freeevents, eventheap, heapsize) +struct otri *checktri; +struct event **freeevents; +struct event **eventheap; +int *heapsize; +#endif /* not ANSI_DECLARATORS */ + +{ + struct event *deadevent; + vertex eventvertex; + int eventnum; + + org(*checktri, eventvertex); + if (eventvertex != (vertex) NULL) { + deadevent = (struct event *) eventvertex; + eventnum = deadevent->heapposition; + deadevent->eventptr = (VOID *) *freeevents; + *freeevents = deadevent; + eventheapdelete(eventheap, *heapsize, eventnum); + (*heapsize)--; + setorg(*checktri, NULL); + } +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +struct splaynode *splay(struct mesh *m, struct splaynode *splaytree, + vertex searchpoint, struct otri *searchtri) +#else /* not ANSI_DECLARATORS */ +struct splaynode *splay(m, splaytree, searchpoint, searchtri) +struct mesh *m; +struct splaynode *splaytree; +vertex searchpoint; +struct otri *searchtri; +#endif /* not ANSI_DECLARATORS */ + +{ + struct splaynode *child, *grandchild; + struct splaynode *lefttree, *righttree; + struct splaynode *leftright; + vertex checkvertex; + int rightofroot, rightofchild; + + if (splaytree == (struct splaynode *) NULL) { + return (struct splaynode *) NULL; + } + dest(splaytree->keyedge, checkvertex); + if (checkvertex == splaytree->keydest) { + rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint); + if (rightofroot) { + otricopy(splaytree->keyedge, *searchtri); + child = splaytree->rchild; + } else { + child = splaytree->lchild; + } + if (child == (struct splaynode *) NULL) { + return splaytree; + } + dest(child->keyedge, checkvertex); + if (checkvertex != child->keydest) { + child = splay(m, child, searchpoint, searchtri); + if (child == (struct splaynode *) NULL) { + if (rightofroot) { + splaytree->rchild = (struct splaynode *) NULL; + } else { + splaytree->lchild = (struct splaynode *) NULL; + } + return splaytree; + } + } + rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint); + if (rightofchild) { + otricopy(child->keyedge, *searchtri); + grandchild = splay(m, child->rchild, searchpoint, searchtri); + child->rchild = grandchild; + } else { + grandchild = splay(m, child->lchild, searchpoint, searchtri); + child->lchild = grandchild; + } + if (grandchild == (struct splaynode *) NULL) { + if (rightofroot) { + splaytree->rchild = child->lchild; + child->lchild = splaytree; + } else { + splaytree->lchild = child->rchild; + child->rchild = splaytree; + } + return child; + } + if (rightofchild) { + if (rightofroot) { + splaytree->rchild = child->lchild; + child->lchild = splaytree; + } else { + splaytree->lchild = grandchild->rchild; + grandchild->rchild = splaytree; + } + child->rchild = grandchild->lchild; + grandchild->lchild = child; + } else { + if (rightofroot) { + splaytree->rchild = grandchild->lchild; + grandchild->lchild = splaytree; + } else { + splaytree->lchild = child->rchild; + child->rchild = splaytree; + } + child->lchild = grandchild->rchild; + grandchild->rchild = child; + } + return grandchild; + } else { + lefttree = splay(m, splaytree->lchild, searchpoint, searchtri); + righttree = splay(m, splaytree->rchild, searchpoint, searchtri); + + pooldealloc(&m->splaynodes, (VOID *) splaytree); + if (lefttree == (struct splaynode *) NULL) { + return righttree; + } else if (righttree == (struct splaynode *) NULL) { + return lefttree; + } else if (lefttree->rchild == (struct splaynode *) NULL) { + lefttree->rchild = righttree->lchild; + righttree->lchild = lefttree; + return righttree; + } else if (righttree->lchild == (struct splaynode *) NULL) { + righttree->lchild = lefttree->rchild; + lefttree->rchild = righttree; + return lefttree; + } else { +/* printf("Holy Toledo!!!\n"); */ + leftright = lefttree->rchild; + while (leftright->rchild != (struct splaynode *) NULL) { + leftright = leftright->rchild; + } + leftright->rchild = righttree; + return lefttree; + } + } +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot, + struct otri *newkey, vertex searchpoint) +#else /* not ANSI_DECLARATORS */ +struct splaynode *splayinsert(m, splayroot, newkey, searchpoint) +struct mesh *m; +struct splaynode *splayroot; +struct otri *newkey; +vertex searchpoint; +#endif /* not ANSI_DECLARATORS */ + +{ + struct splaynode *newsplaynode; + + newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes); + otricopy(*newkey, newsplaynode->keyedge); + dest(*newkey, newsplaynode->keydest); + if (splayroot == (struct splaynode *) NULL) { + newsplaynode->lchild = (struct splaynode *) NULL; + newsplaynode->rchild = (struct splaynode *) NULL; + } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) { + newsplaynode->lchild = splayroot; + newsplaynode->rchild = splayroot->rchild; + splayroot->rchild = (struct splaynode *) NULL; + } else { + newsplaynode->lchild = splayroot->lchild; + newsplaynode->rchild = splayroot; + splayroot->lchild = (struct splaynode *) NULL; + } + return newsplaynode; +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +struct splaynode *circletopinsert(struct mesh *m, struct behavior *b, + struct splaynode *splayroot, + struct otri *newkey, + vertex pa, vertex pb, vertex pc, REAL topy) +#else /* not ANSI_DECLARATORS */ +struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy) +struct mesh *m; +struct behavior *b; +struct splaynode *splayroot; +struct otri *newkey; +vertex pa; +vertex pb; +vertex pc; +REAL topy; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL ccwabc; + REAL xac, yac, xbc, ybc; + REAL aclen2, bclen2; + REAL searchpoint[2]; + struct otri dummytri; + + ccwabc = counterclockwise(m, b, pa, pb, pc); + xac = pa[0] - pc[0]; + yac = pa[1] - pc[1]; + xbc = pb[0] - pc[0]; + ybc = pb[1] - pc[1]; + aclen2 = xac * xac + yac * yac; + bclen2 = xbc * xbc + ybc * ybc; + searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc); + searchpoint[1] = topy; + return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri), + newkey, (vertex) searchpoint); +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot, + struct otri *bottommost, vertex searchvertex, + struct otri *searchtri, int *farright) +#else /* not ANSI_DECLARATORS */ +struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex, + searchtri, farright) +struct mesh *m; +struct splaynode *splayroot; +struct otri *bottommost; +vertex searchvertex; +struct otri *searchtri; +int *farright; +#endif /* not ANSI_DECLARATORS */ + +{ + int farrightflag; + triangle ptr; /* Temporary variable used by onext(). */ + + otricopy(*bottommost, *searchtri); + splayroot = splay(m, splayroot, searchvertex, searchtri); + + farrightflag = 0; + while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) { + onextself(*searchtri); + farrightflag = otriequal(*searchtri, *bottommost); + } + *farright = farrightflag; + return splayroot; +} + +#endif /* not REDUCED */ + +#ifndef REDUCED + +#ifdef ANSI_DECLARATORS +long sweeplinedelaunay(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +long sweeplinedelaunay(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct event **eventheap; + struct event *events; + struct event *freeevents; + struct event *nextevent; + struct event *newevent; + struct splaynode *splayroot; + struct otri bottommost; + struct otri searchtri; + struct otri fliptri; + struct otri lefttri, righttri, farlefttri, farrighttri; + struct otri inserttri; + vertex firstvertex, secondvertex; + vertex nextvertex, lastvertex; + vertex connectvertex; + vertex leftvertex, midvertex, rightvertex; + REAL lefttest, righttest; + int heapsize; + int check4events, farrightflag; + triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ + + poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK, + SPLAYNODEPERBLOCK, 0); + splayroot = (struct splaynode *) NULL; + + if (b->verbose) { + printf(" Placing vertices in event heap.\n"); + } + createeventheap(m, &eventheap, &events, &freeevents); + heapsize = m->invertices; + + if (b->verbose) { + printf(" Forming triangulation.\n"); + } + maketriangle(m, b, &lefttri); + maketriangle(m, b, &righttri); + bond(lefttri, righttri); + lnextself(lefttri); + lprevself(righttri); + bond(lefttri, righttri); + lnextself(lefttri); + lprevself(righttri); + bond(lefttri, righttri); + firstvertex = (vertex) eventheap[0]->eventptr; + eventheap[0]->eventptr = (VOID *) freeevents; + freeevents = eventheap[0]; + eventheapdelete(eventheap, heapsize, 0); + heapsize--; + do { + if (heapsize == 0) { + printf("Error: Input vertices are all identical.\n"); + triexit(1); + } + secondvertex = (vertex) eventheap[0]->eventptr; + eventheap[0]->eventptr = (VOID *) freeevents; + freeevents = eventheap[0]; + eventheapdelete(eventheap, heapsize, 0); + heapsize--; + if ((firstvertex[0] == secondvertex[0]) && + (firstvertex[1] == secondvertex[1])) { + if (!b->quiet) { + printf( +"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", + secondvertex[0], secondvertex[1]); + } + setvertextype(secondvertex, UNDEADVERTEX); + m->undeads++; + } + } while ((firstvertex[0] == secondvertex[0]) && + (firstvertex[1] == secondvertex[1])); + setorg(lefttri, firstvertex); + setdest(lefttri, secondvertex); + setorg(righttri, secondvertex); + setdest(righttri, firstvertex); + lprev(lefttri, bottommost); + lastvertex = secondvertex; + while (heapsize > 0) { + nextevent = eventheap[0]; + eventheapdelete(eventheap, heapsize, 0); + heapsize--; + check4events = 1; + if (nextevent->xkey < m->xmin) { + decode(nextevent->eventptr, fliptri); + oprev(fliptri, farlefttri); + check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize); + onext(fliptri, farrighttri); + check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize); + + if (otriequal(farlefttri, bottommost)) { + lprev(fliptri, bottommost); + } + flip(m, b, &fliptri); + setapex(fliptri, NULL); + lprev(fliptri, lefttri); + lnext(fliptri, righttri); + sym(lefttri, farlefttri); + + if (randomnation(SAMPLERATE) == 0) { + symself(fliptri); + dest(fliptri, leftvertex); + apex(fliptri, midvertex); + org(fliptri, rightvertex); + splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex, + midvertex, rightvertex, nextevent->ykey); + } + } else { + nextvertex = (vertex) nextevent->eventptr; + if ((nextvertex[0] == lastvertex[0]) && + (nextvertex[1] == lastvertex[1])) { + if (!b->quiet) { + printf( +"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", + nextvertex[0], nextvertex[1]); + } + setvertextype(nextvertex, UNDEADVERTEX); + m->undeads++; + check4events = 0; + } else { + lastvertex = nextvertex; + + splayroot = frontlocate(m, splayroot, &bottommost, nextvertex, + &searchtri, &farrightflag); +/* + otricopy(bottommost, searchtri); + farrightflag = 0; + while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) { + onextself(searchtri); + farrightflag = otriequal(searchtri, bottommost); + } +*/ + + check4deadevent(&searchtri, &freeevents, eventheap, &heapsize); + + otricopy(searchtri, farrighttri); + sym(searchtri, farlefttri); + maketriangle(m, b, &lefttri); + maketriangle(m, b, &righttri); + dest(farrighttri, connectvertex); + setorg(lefttri, connectvertex); + setdest(lefttri, nextvertex); + setorg(righttri, nextvertex); + setdest(righttri, connectvertex); + bond(lefttri, righttri); + lnextself(lefttri); + lprevself(righttri); + bond(lefttri, righttri); + lnextself(lefttri); + lprevself(righttri); + bond(lefttri, farlefttri); + bond(righttri, farrighttri); + if (!farrightflag && otriequal(farrighttri, bottommost)) { + otricopy(lefttri, bottommost); + } + + if (randomnation(SAMPLERATE) == 0) { + splayroot = splayinsert(m, splayroot, &lefttri, nextvertex); + } else if (randomnation(SAMPLERATE) == 0) { + lnext(righttri, inserttri); + splayroot = splayinsert(m, splayroot, &inserttri, nextvertex); + } + } + } + nextevent->eventptr = (VOID *) freeevents; + freeevents = nextevent; + + if (check4events) { + apex(farlefttri, leftvertex); + dest(lefttri, midvertex); + apex(lefttri, rightvertex); + lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex); + if (lefttest > 0.0) { + newevent = freeevents; + freeevents = (struct event *) freeevents->eventptr; + newevent->xkey = m->xminextreme; + newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex, + lefttest); + newevent->eventptr = (VOID *) encode(lefttri); + eventheapinsert(eventheap, heapsize, newevent); + heapsize++; + setorg(lefttri, newevent); + } + apex(righttri, leftvertex); + org(righttri, midvertex); + apex(farrighttri, rightvertex); + righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex); + if (righttest > 0.0) { + newevent = freeevents; + freeevents = (struct event *) freeevents->eventptr; + newevent->xkey = m->xminextreme; + newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex, + righttest); + newevent->eventptr = (VOID *) encode(farrighttri); + eventheapinsert(eventheap, heapsize, newevent); + heapsize++; + setorg(farrighttri, newevent); + } + } + } + + pooldeinit(&m->splaynodes); + lprevself(bottommost); + return removeghosts(m, b, &bottommost); +} + +#endif /* not REDUCED */ + +/** **/ +/** **/ +/********* Sweepline Delaunay triangulation ends here *********/ + +/********* General mesh construction routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* delaunay() Form a Delaunay triangulation. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +long delaunay(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +long delaunay(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + long hulledges; + + m->eextras = 0; + initializetrisubpools(m, b); + +#ifdef REDUCED + if (!b->quiet) { + printf( + "Constructing Delaunay triangulation by divide-and-conquer method.\n"); + } + hulledges = divconqdelaunay(m, b); +#else /* not REDUCED */ + if (!b->quiet) { + printf("Constructing Delaunay triangulation "); + if (b->incremental) { + printf("by incremental method.\n"); + } else if (b->sweepline) { + printf("by sweepline method.\n"); + } else { + printf("by divide-and-conquer method.\n"); + } + } + if (b->incremental) { + hulledges = incrementaldelaunay(m, b); + } else if (b->sweepline) { + hulledges = sweeplinedelaunay(m, b); + } else { + hulledges = divconqdelaunay(m, b); + } +#endif /* not REDUCED */ + + if (m->triangles.items == 0) { + /* The input vertices were all collinear, so there are no triangles. */ + return 0l; + } else { + return hulledges; + } +} + +/*****************************************************************************/ +/* */ +/* reconstruct() Reconstruct a triangulation from its .ele (and possibly */ +/* .poly) file. Used when the -r switch is used. */ +/* */ +/* Reads an .ele file and reconstructs the original mesh. If the -p switch */ +/* is used, this procedure will also read a .poly file and reconstruct the */ +/* subsegments of the original mesh. If the -a switch is used, this */ +/* procedure will also read an .area file and set a maximum area constraint */ +/* on each triangle. */ +/* */ +/* Vertices that are not corners of triangles, such as nodes on edges of */ +/* subparametric elements, are discarded. */ +/* */ +/* This routine finds the adjacencies between triangles (and subsegments) */ +/* by forming one stack of triangles for each vertex. Each triangle is on */ +/* three different stacks simultaneously. Each triangle's subsegment */ +/* pointers are used to link the items in each stack. This memory-saving */ +/* feature makes the code harder to read. The most important thing to keep */ +/* in mind is that each triangle is removed from a stack precisely when */ +/* the corresponding pointer is adjusted to refer to a subsegment rather */ +/* than the next triangle of the stack. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist, + REAL *triangleattriblist, REAL *trianglearealist, + int elements, int corners, int attribs, + int *segmentlist,int *segmentmarkerlist, int numberofsegments) +#else /* not ANSI_DECLARATORS */ +int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist, + elements, corners, attribs, segmentlist, segmentmarkerlist, + numberofsegments) +struct mesh *m; +struct behavior *b; +int *trianglelist; +REAL *triangleattriblist; +REAL *trianglearealist; +int elements; +int corners; +int attribs; +int *segmentlist; +int *segmentmarkerlist; +int numberofsegments; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +long reconstruct(struct mesh *m, struct behavior *b, char *elefilename, + char *areafilename, char *polyfilename, FILE *polyfile) +#else /* not ANSI_DECLARATORS */ +long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile) +struct mesh *m; +struct behavior *b; +char *elefilename; +char *areafilename; +char *polyfilename; +FILE *polyfile; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + int vertexindex; + int attribindex; +#else /* not TRILIBRARY */ + FILE *elefile; + FILE *areafile; + char inputline[INPUTLINESIZE]; + char *stringptr; + int areaelements; +#endif /* not TRILIBRARY */ + struct otri triangleloop; + struct otri triangleleft; + struct otri checktri; + struct otri checkleft; + struct otri checkneighbor; + struct osub subsegloop; + triangle *vertexarray; + triangle *prevlink; + triangle nexttri; + vertex tdest, tapex; + vertex checkdest, checkapex; + vertex shorg; + vertex killvertex; + vertex segmentorg, segmentdest; + REAL area; + int corner[3]; + int end[2]; + int killvertexindex; + int incorners; + int segmentmarkers; + int boundmarker; + int aroundvertex; + long hullsize; + int notfound; + long elementnumber, segmentnumber; + int i, j; + triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef TRILIBRARY + m->inelements = elements; + incorners = corners; + if (incorners < 3) { + printf("Error: Triangles must have at least 3 vertices.\n"); + triexit(1); + } + m->eextras = attribs; +#else /* not TRILIBRARY */ + /* Read the triangles from an .ele file. */ + if (!b->quiet) { + printf("Opening %s.\n", elefilename); + } + elefile = fopen(elefilename, "r"); + if (elefile == (FILE *) NULL) { + printf(" Error: Cannot access file %s.\n", elefilename); + triexit(1); + } + /* Read number of triangles, number of vertices per triangle, and */ + /* number of triangle attributes from .ele file. */ + stringptr = readline(inputline, elefile, elefilename); + m->inelements = (int) strtol(stringptr, &stringptr, 0); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + incorners = 3; + } else { + incorners = (int) strtol(stringptr, &stringptr, 0); + if (incorners < 3) { + printf("Error: Triangles in %s must have at least 3 vertices.\n", + elefilename); + triexit(1); + } + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + m->eextras = 0; + } else { + m->eextras = (int) strtol(stringptr, &stringptr, 0); + } +#endif /* not TRILIBRARY */ + + initializetrisubpools(m, b); + + /* Create the triangles. */ + for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) { + maketriangle(m, b, &triangleloop); + /* Mark the triangle as living. */ + triangleloop.tri[3] = (triangle) triangleloop.tri; + } + + segmentmarkers = 0; + if (b->poly) { +#ifdef TRILIBRARY + m->insegments = numberofsegments; + segmentmarkers = segmentmarkerlist != (int *) NULL; +#else /* not TRILIBRARY */ + /* Read number of segments and number of segment */ + /* boundary markers from .poly file. */ + stringptr = readline(inputline, polyfile, b->inpolyfilename); + m->insegments = (int) strtol(stringptr, &stringptr, 0); + stringptr = findfield(stringptr); + if (*stringptr != '\0') { + segmentmarkers = (int) strtol(stringptr, &stringptr, 0); + } +#endif /* not TRILIBRARY */ + + /* Create the subsegments. */ + for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) { + makesubseg(m, &subsegloop); + /* Mark the subsegment as living. */ + subsegloop.ss[2] = (subseg) subsegloop.ss; + } + } + +#ifdef TRILIBRARY + vertexindex = 0; + attribindex = 0; +#else /* not TRILIBRARY */ + if (b->vararea) { + /* Open an .area file, check for consistency with the .ele file. */ + if (!b->quiet) { + printf("Opening %s.\n", areafilename); + } + areafile = fopen(areafilename, "r"); + if (areafile == (FILE *) NULL) { + printf(" Error: Cannot access file %s.\n", areafilename); + triexit(1); + } + stringptr = readline(inputline, areafile, areafilename); + areaelements = (int) strtol(stringptr, &stringptr, 0); + if (areaelements != m->inelements) { + printf("Error: %s and %s disagree on number of triangles.\n", + elefilename, areafilename); + triexit(1); + } + } +#endif /* not TRILIBRARY */ + + if (!b->quiet) { + printf("Reconstructing mesh.\n"); + } + /* Allocate a temporary array that maps each vertex to some adjacent */ + /* triangle. I took care to allocate all the permanent memory for */ + /* triangles and subsegments first. */ + vertexarray = (triangle *) trimalloc(m->vertices.items * + (int) sizeof(triangle)); + /* Each vertex is initially unrepresented. */ + for (i = 0; i < m->vertices.items; i++) { + vertexarray[i] = (triangle) m->dummytri; + } + + if (b->verbose) { + printf(" Assembling triangles.\n"); + } + /* Read the triangles from the .ele file, and link */ + /* together those that share an edge. */ + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + elementnumber = b->firstnumber; + while (triangleloop.tri != (triangle *) NULL) { +#ifdef TRILIBRARY + /* Copy the triangle's three corners. */ + for (j = 0; j < 3; j++) { + corner[j] = trianglelist[vertexindex++]; + if ((corner[j] < b->firstnumber) || + (corner[j] >= b->firstnumber + m->invertices)) { + printf("Error: Triangle %ld has an invalid vertex index.\n", + elementnumber); + triexit(1); + } + } +#else /* not TRILIBRARY */ + /* Read triangle number and the triangle's three corners. */ + stringptr = readline(inputline, elefile, elefilename); + for (j = 0; j < 3; j++) { + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Triangle %ld is missing vertex %d in %s.\n", + elementnumber, j + 1, elefilename); + triexit(1); + } else { + corner[j] = (int) strtol(stringptr, &stringptr, 0); + if ((corner[j] < b->firstnumber) || + (corner[j] >= b->firstnumber + m->invertices)) { + printf("Error: Triangle %ld has an invalid vertex index.\n", + elementnumber); + triexit(1); + } + } + } +#endif /* not TRILIBRARY */ + + /* Find out about (and throw away) extra nodes. */ + for (j = 3; j < incorners; j++) { +#ifdef TRILIBRARY + killvertexindex = trianglelist[vertexindex++]; +#else /* not TRILIBRARY */ + stringptr = findfield(stringptr); + if (*stringptr != '\0') { + killvertexindex = (int) strtol(stringptr, &stringptr, 0); +#endif /* not TRILIBRARY */ + if ((killvertexindex >= b->firstnumber) && + (killvertexindex < b->firstnumber + m->invertices)) { + /* Delete the non-corner vertex if it's not already deleted. */ + killvertex = getvertex(m, b, killvertexindex); + if (vertextype(killvertex) != DEADVERTEX) { + vertexdealloc(m, killvertex); + } + } +#ifndef TRILIBRARY + } +#endif /* not TRILIBRARY */ + } + + /* Read the triangle's attributes. */ + for (j = 0; j < m->eextras; j++) { +#ifdef TRILIBRARY + setelemattribute(triangleloop, j, triangleattriblist[attribindex++]); +#else /* not TRILIBRARY */ + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + setelemattribute(triangleloop, j, 0); + } else { + setelemattribute(triangleloop, j, + (REAL) strtod(stringptr, &stringptr)); + } +#endif /* not TRILIBRARY */ + } + + if (b->vararea) { +#ifdef TRILIBRARY + area = trianglearealist[elementnumber - b->firstnumber]; +#else /* not TRILIBRARY */ + /* Read an area constraint from the .area file. */ + stringptr = readline(inputline, areafile, areafilename); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + area = -1.0; /* No constraint on this triangle. */ + } else { + area = (REAL) strtod(stringptr, &stringptr); + } +#endif /* not TRILIBRARY */ + setareabound(triangleloop, area); + } + + /* Set the triangle's vertices. */ + triangleloop.orient = 0; + setorg(triangleloop, getvertex(m, b, corner[0])); + setdest(triangleloop, getvertex(m, b, corner[1])); + setapex(triangleloop, getvertex(m, b, corner[2])); + /* Try linking the triangle to others that share these vertices. */ + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + /* Take the number for the origin of triangleloop. */ + aroundvertex = corner[triangleloop.orient]; + /* Look for other triangles having this vertex. */ + nexttri = vertexarray[aroundvertex - b->firstnumber]; + /* Link the current triangle to the next one in the stack. */ + triangleloop.tri[6 + triangleloop.orient] = nexttri; + /* Push the current triangle onto the stack. */ + vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop); + decode(nexttri, checktri); + if (checktri.tri != m->dummytri) { + dest(triangleloop, tdest); + apex(triangleloop, tapex); + /* Look for other triangles that share an edge. */ + do { + dest(checktri, checkdest); + apex(checktri, checkapex); + if (tapex == checkdest) { + /* The two triangles share an edge; bond them together. */ + lprev(triangleloop, triangleleft); + bond(triangleleft, checktri); + } + if (tdest == checkapex) { + /* The two triangles share an edge; bond them together. */ + lprev(checktri, checkleft); + bond(triangleloop, checkleft); + } + /* Find the next triangle in the stack. */ + nexttri = checktri.tri[6 + checktri.orient]; + decode(nexttri, checktri); + } while (checktri.tri != m->dummytri); + } + } + triangleloop.tri = triangletraverse(m); + elementnumber++; + } + +#ifdef TRILIBRARY + vertexindex = 0; +#else /* not TRILIBRARY */ + fclose(elefile); + if (b->vararea) { + fclose(areafile); + } +#endif /* not TRILIBRARY */ + + hullsize = 0; /* Prepare to count the boundary edges. */ + if (b->poly) { + if (b->verbose) { + printf(" Marking segments in triangulation.\n"); + } + /* Read the segments from the .poly file, and link them */ + /* to their neighboring triangles. */ + boundmarker = 0; + traversalinit(&m->subsegs); + subsegloop.ss = subsegtraverse(m); + segmentnumber = b->firstnumber; + while (subsegloop.ss != (subseg *) NULL) { +#ifdef TRILIBRARY + end[0] = segmentlist[vertexindex++]; + end[1] = segmentlist[vertexindex++]; + if (segmentmarkers) { + boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber]; + } +#else /* not TRILIBRARY */ + /* Read the endpoints of each segment, and possibly a boundary marker. */ + stringptr = readline(inputline, polyfile, b->inpolyfilename); + /* Skip the first (segment number) field. */ + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber, + polyfilename); + triexit(1); + } else { + end[0] = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Segment %ld is missing its second endpoint in %s.\n", + segmentnumber, polyfilename); + triexit(1); + } else { + end[1] = (int) strtol(stringptr, &stringptr, 0); + } + if (segmentmarkers) { + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + boundmarker = 0; + } else { + boundmarker = (int) strtol(stringptr, &stringptr, 0); + } + } +#endif /* not TRILIBRARY */ + for (j = 0; j < 2; j++) { + if ((end[j] < b->firstnumber) || + (end[j] >= b->firstnumber + m->invertices)) { + printf("Error: Segment %ld has an invalid vertex index.\n", + segmentnumber); + triexit(1); + } + } + + /* set the subsegment's vertices. */ + subsegloop.ssorient = 0; + segmentorg = getvertex(m, b, end[0]); + segmentdest = getvertex(m, b, end[1]); + setsorg(subsegloop, segmentorg); + setsdest(subsegloop, segmentdest); + setsegorg(subsegloop, segmentorg); + setsegdest(subsegloop, segmentdest); + setmark(subsegloop, boundmarker); + /* Try linking the subsegment to triangles that share these vertices. */ + for (subsegloop.ssorient = 0; subsegloop.ssorient < 2; + subsegloop.ssorient++) { + /* Take the number for the destination of subsegloop. */ + aroundvertex = end[1 - subsegloop.ssorient]; + /* Look for triangles having this vertex. */ + prevlink = &vertexarray[aroundvertex - b->firstnumber]; + nexttri = vertexarray[aroundvertex - b->firstnumber]; + decode(nexttri, checktri); + sorg(subsegloop, shorg); + notfound = 1; + /* Look for triangles having this edge. Note that I'm only */ + /* comparing each triangle's destination with the subsegment; */ + /* each triangle's apex is handled through a different vertex. */ + /* Because each triangle appears on three vertices' lists, each */ + /* occurrence of a triangle on a list can (and does) represent */ + /* an edge. In this way, most edges are represented twice, and */ + /* every triangle-subsegment bond is represented once. */ + while (notfound && (checktri.tri != m->dummytri)) { + dest(checktri, checkdest); + if (shorg == checkdest) { + /* We have a match. Remove this triangle from the list. */ + *prevlink = checktri.tri[6 + checktri.orient]; + /* Bond the subsegment to the triangle. */ + tsbond(checktri, subsegloop); + /* Check if this is a boundary edge. */ + sym(checktri, checkneighbor); + if (checkneighbor.tri == m->dummytri) { + /* The next line doesn't insert a subsegment (because there's */ + /* already one there), but it sets the boundary markers of */ + /* the existing subsegment and its vertices. */ + insertsubseg(m, b, &checktri, 1); + hullsize++; + } + notfound = 0; + } + /* Find the next triangle in the stack. */ + prevlink = &checktri.tri[6 + checktri.orient]; + nexttri = checktri.tri[6 + checktri.orient]; + decode(nexttri, checktri); + } + } + subsegloop.ss = subsegtraverse(m); + segmentnumber++; + } + } + + /* Mark the remaining edges as not being attached to any subsegment. */ + /* Also, count the (yet uncounted) boundary edges. */ + for (i = 0; i < m->vertices.items; i++) { + /* Search the stack of triangles adjacent to a vertex. */ + nexttri = vertexarray[i]; + decode(nexttri, checktri); + while (checktri.tri != m->dummytri) { + /* Find the next triangle in the stack before this */ + /* information gets overwritten. */ + nexttri = checktri.tri[6 + checktri.orient]; + /* No adjacent subsegment. (This overwrites the stack info.) */ + tsdissolve(checktri); + sym(checktri, checkneighbor); + if (checkneighbor.tri == m->dummytri) { + insertsubseg(m, b, &checktri, 1); + hullsize++; + } + decode(nexttri, checktri); + } + } + + trifree((VOID *) vertexarray); + return hullsize; +} + +#endif /* not CDT_ONLY */ + +/** **/ +/** **/ +/********* General mesh construction routines end here *********/ + +/********* Segment insertion begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* finddirection() Find the first triangle on the path from one point */ +/* to another. */ +/* */ +/* Finds the triangle that intersects a line segment drawn from the */ +/* origin of `searchtri' to the point `searchpoint', and returns the result */ +/* in `searchtri'. The origin of `searchtri' does not change, even though */ +/* the triangle returned may differ from the one passed in. This routine */ +/* is used to find the direction to move in to get from one point to */ +/* another. */ +/* */ +/* The return value notes whether the destination or apex of the found */ +/* triangle is collinear with the two points in question. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, + struct otri *searchtri, + vertex searchpoint) +#else /* not ANSI_DECLARATORS */ +enum finddirectionresult finddirection(m, b, searchtri, searchpoint) +struct mesh *m; +struct behavior *b; +struct otri *searchtri; +vertex searchpoint; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri checktri; + vertex startvertex; + vertex leftvertex, rightvertex; + REAL leftccw, rightccw; + int leftflag, rightflag; + triangle ptr; /* Temporary variable used by onext() and oprev(). */ + + org(*searchtri, startvertex); + dest(*searchtri, rightvertex); + apex(*searchtri, leftvertex); + /* Is `searchpoint' to the left? */ + leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex); + leftflag = leftccw > 0.0; + /* Is `searchpoint' to the right? */ + rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex); + rightflag = rightccw > 0.0; + if (leftflag && rightflag) { + /* `searchtri' faces directly away from `searchpoint'. We could go left */ + /* or right. Ask whether it's a triangle or a boundary on the left. */ + onext(*searchtri, checktri); + if (checktri.tri == m->dummytri) { + leftflag = 0; + } else { + rightflag = 0; + } + } + while (leftflag) { + /* Turn left until satisfied. */ + onextself(*searchtri); + if (searchtri->tri == m->dummytri) { + printf("Internal error in finddirection(): Unable to find a\n"); + printf(" triangle leading from (%.12g, %.12g) to", startvertex[0], + startvertex[1]); + printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]); + internalerror(); + } + apex(*searchtri, leftvertex); + rightccw = leftccw; + leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex); + leftflag = leftccw > 0.0; + } + while (rightflag) { + /* Turn right until satisfied. */ + oprevself(*searchtri); + if (searchtri->tri == m->dummytri) { + printf("Internal error in finddirection(): Unable to find a\n"); + printf(" triangle leading from (%.12g, %.12g) to", startvertex[0], + startvertex[1]); + printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]); + internalerror(); + } + dest(*searchtri, rightvertex); + leftccw = rightccw; + rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex); + rightflag = rightccw > 0.0; + } + if (leftccw == 0.0) { + return LEFTCOLLINEAR; + } else if (rightccw == 0.0) { + return RIGHTCOLLINEAR; + } else { + return WITHIN; + } +} + +/*****************************************************************************/ +/* */ +/* segmentintersection() Find the intersection of an existing segment */ +/* and a segment that is being inserted. Insert */ +/* a vertex at the intersection, splitting an */ +/* existing subsegment. */ +/* */ +/* The segment being inserted connects the apex of splittri to endpoint2. */ +/* splitsubseg is the subsegment being split, and MUST adjoin splittri. */ +/* Hence, endpoints of the subsegment being split are the origin and */ +/* destination of splittri. */ +/* */ +/* On completion, splittri is a handle having the newly inserted */ +/* intersection point as its origin, and endpoint1 as its destination. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void segmentintersection(struct mesh *m, struct behavior *b, + struct otri *splittri, struct osub *splitsubseg, + vertex endpoint2) +#else /* not ANSI_DECLARATORS */ +void segmentintersection(m, b, splittri, splitsubseg, endpoint2) +struct mesh *m; +struct behavior *b; +struct otri *splittri; +struct osub *splitsubseg; +vertex endpoint2; +#endif /* not ANSI_DECLARATORS */ + +{ + struct osub opposubseg; + vertex endpoint1; + vertex torg, tdest; + vertex leftvertex, rightvertex; + vertex newvertex; + enum insertvertexresult success; + enum finddirectionresult collinear; + REAL ex, ey; + REAL tx, ty; + REAL etx, ety; + REAL split, denom; + int i; + triangle ptr; /* Temporary variable used by onext(). */ + subseg sptr; /* Temporary variable used by snext(). */ + + /* Find the other three segment endpoints. */ + apex(*splittri, endpoint1); + org(*splittri, torg); + dest(*splittri, tdest); + /* Segment intersection formulae; see the Antonio reference. */ + tx = tdest[0] - torg[0]; + ty = tdest[1] - torg[1]; + ex = endpoint2[0] - endpoint1[0]; + ey = endpoint2[1] - endpoint1[1]; + etx = torg[0] - endpoint2[0]; + ety = torg[1] - endpoint2[1]; + denom = ty * ex - tx * ey; + if (denom == 0.0) { + printf("Internal error in segmentintersection():"); + printf(" Attempt to find intersection of parallel segments.\n"); + internalerror(); + } + split = (ey * etx - ex * ety) / denom; + /* Create the new vertex. */ + newvertex = (vertex) poolalloc(&m->vertices); + /* Interpolate its coordinate and attributes. */ + for (i = 0; i < 2 + m->nextras; i++) { + newvertex[i] = torg[i] + split * (tdest[i] - torg[i]); + } + setvertexmark(newvertex, mark(*splitsubseg)); + setvertextype(newvertex, INPUTVERTEX); + if (b->verbose > 1) { + printf( + " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", + torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]); + } + /* Insert the intersection vertex. This should always succeed. */ + success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0); + if (success != SUCCESSFULVERTEX) { + printf("Internal error in segmentintersection():\n"); + printf(" Failure to split a segment.\n"); + internalerror(); + } + /* Record a triangle whose origin is the new vertex. */ + setvertex2tri(newvertex, encode(*splittri)); + if (m->steinerleft > 0) { + m->steinerleft--; + } + + /* Divide the segment into two, and correct the segment endpoints. */ + ssymself(*splitsubseg); + spivot(*splitsubseg, opposubseg); + sdissolve(*splitsubseg); + sdissolve(opposubseg); + do { + setsegorg(*splitsubseg, newvertex); + snextself(*splitsubseg); + } while (splitsubseg->ss != m->dummysub); + do { + setsegorg(opposubseg, newvertex); + snextself(opposubseg); + } while (opposubseg.ss != m->dummysub); + + /* Inserting the vertex may have caused edge flips. We wish to rediscover */ + /* the edge connecting endpoint1 to the new intersection vertex. */ + collinear = finddirection(m, b, splittri, endpoint1); + dest(*splittri, rightvertex); + apex(*splittri, leftvertex); + if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) { + onextself(*splittri); + } else if ((rightvertex[0] != endpoint1[0]) || + (rightvertex[1] != endpoint1[1])) { + printf("Internal error in segmentintersection():\n"); + printf(" Topological inconsistency after splitting a segment.\n"); + internalerror(); + } + /* `splittri' should have destination endpoint1. */ +} + +/*****************************************************************************/ +/* */ +/* scoutsegment() Scout the first triangle on the path from one endpoint */ +/* to another, and check for completion (reaching the */ +/* second endpoint), a collinear vertex, or the */ +/* intersection of two segments. */ +/* */ +/* Returns one if the entire segment is successfully inserted, and zero if */ +/* the job must be finished by conformingedge() or constrainededge(). */ +/* */ +/* If the first triangle on the path has the second endpoint as its */ +/* destination or apex, a subsegment is inserted and the job is done. */ +/* */ +/* If the first triangle on the path has a destination or apex that lies on */ +/* the segment, a subsegment is inserted connecting the first endpoint to */ +/* the collinear vertex, and the search is continued from the collinear */ +/* vertex. */ +/* */ +/* If the first triangle on the path has a subsegment opposite its origin, */ +/* then there is a segment that intersects the segment being inserted. */ +/* Their intersection vertex is inserted, splitting the subsegment. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, + vertex endpoint2, int newmark) +#else /* not ANSI_DECLARATORS */ +int scoutsegment(m, b, searchtri, endpoint2, newmark) +struct mesh *m; +struct behavior *b; +struct otri *searchtri; +vertex endpoint2; +int newmark; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri crosstri; + struct osub crosssubseg; + vertex leftvertex, rightvertex; + enum finddirectionresult collinear; + subseg sptr; /* Temporary variable used by tspivot(). */ + + collinear = finddirection(m, b, searchtri, endpoint2); + dest(*searchtri, rightvertex); + apex(*searchtri, leftvertex); + if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) || + ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) { + /* The segment is already an edge in the mesh. */ + if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) { + lprevself(*searchtri); + } + /* Insert a subsegment, if there isn't already one there. */ + insertsubseg(m, b, searchtri, newmark); + return 1; + } else if (collinear == LEFTCOLLINEAR) { + /* We've collided with a vertex between the segment's endpoints. */ + /* Make the collinear vertex be the triangle's origin. */ + lprevself(*searchtri); + insertsubseg(m, b, searchtri, newmark); + /* Insert the remainder of the segment. */ + return scoutsegment(m, b, searchtri, endpoint2, newmark); + } else if (collinear == RIGHTCOLLINEAR) { + /* We've collided with a vertex between the segment's endpoints. */ + insertsubseg(m, b, searchtri, newmark); + /* Make the collinear vertex be the triangle's origin. */ + lnextself(*searchtri); + /* Insert the remainder of the segment. */ + return scoutsegment(m, b, searchtri, endpoint2, newmark); + } else { + lnext(*searchtri, crosstri); + tspivot(crosstri, crosssubseg); + /* Check for a crossing segment. */ + if (crosssubseg.ss == m->dummysub) { + return 0; + } else { + /* Insert a vertex at the intersection. */ + segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2); + otricopy(crosstri, *searchtri); + insertsubseg(m, b, searchtri, newmark); + /* Insert the remainder of the segment. */ + return scoutsegment(m, b, searchtri, endpoint2, newmark); + } + } +} + +/*****************************************************************************/ +/* */ +/* conformingedge() Force a segment into a conforming Delaunay */ +/* triangulation by inserting a vertex at its midpoint, */ +/* and recursively forcing in the two half-segments if */ +/* necessary. */ +/* */ +/* Generates a sequence of subsegments connecting `endpoint1' to */ +/* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */ +/* to each new splitting vertex and subsegment. */ +/* */ +/* Note that conformingedge() does not always maintain the conforming */ +/* Delaunay property. Once inserted, segments are locked into place; */ +/* vertices inserted later (to force other segments in) may render these */ +/* fixed segments non-Delaunay. The conforming Delaunay property will be */ +/* restored by enforcequality() by splitting encroached subsegments. */ +/* */ +/*****************************************************************************/ + +#ifndef REDUCED +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void conformingedge(struct mesh *m, struct behavior *b, + vertex endpoint1, vertex endpoint2, int newmark) +#else /* not ANSI_DECLARATORS */ +void conformingedge(m, b, endpoint1, endpoint2, newmark) +struct mesh *m; +struct behavior *b; +vertex endpoint1; +vertex endpoint2; +int newmark; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri searchtri1, searchtri2; + struct osub brokensubseg; + vertex newvertex; + vertex midvertex1, midvertex2; + enum insertvertexresult success; + int i; + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (b->verbose > 2) { + printf("Forcing segment into triangulation by recursive splitting:\n"); + printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1], + endpoint2[0], endpoint2[1]); + } + /* Create a new vertex to insert in the middle of the segment. */ + newvertex = (vertex) poolalloc(&m->vertices); + /* Interpolate coordinates and attributes. */ + for (i = 0; i < 2 + m->nextras; i++) { + newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]); + } + setvertexmark(newvertex, newmark); + setvertextype(newvertex, SEGMENTVERTEX); + /* No known triangle to search from. */ + searchtri1.tri = m->dummytri; + /* Attempt to insert the new vertex. */ + success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL, + 0, 0); + if (success == DUPLICATEVERTEX) { + if (b->verbose > 2) { + printf(" Segment intersects existing vertex (%.12g, %.12g).\n", + newvertex[0], newvertex[1]); + } + /* Use the vertex that's already there. */ + vertexdealloc(m, newvertex); + org(searchtri1, newvertex); + } else { + if (success == VIOLATINGVERTEX) { + if (b->verbose > 2) { + printf(" Two segments intersect at (%.12g, %.12g).\n", + newvertex[0], newvertex[1]); + } + /* By fluke, we've landed right on another segment. Split it. */ + tspivot(searchtri1, brokensubseg); + success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg, + 0, 0); + if (success != SUCCESSFULVERTEX) { + printf("Internal error in conformingedge():\n"); + printf(" Failure to split a segment.\n"); + internalerror(); + } + } + /* The vertex has been inserted successfully. */ + if (m->steinerleft > 0) { + m->steinerleft--; + } + } + otricopy(searchtri1, searchtri2); + /* `searchtri1' and `searchtri2' are fastened at their origins to */ + /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */ + /* respectively. First, we must get `searchtri2' out of the way so it */ + /* won't be invalidated during the insertion of the first half of the */ + /* segment. */ + finddirection(m, b, &searchtri2, endpoint2); + if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) { + /* The origin of searchtri1 may have changed if a collision with an */ + /* intervening vertex on the segment occurred. */ + org(searchtri1, midvertex1); + conformingedge(m, b, midvertex1, endpoint1, newmark); + } + if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) { + /* The origin of searchtri2 may have changed if a collision with an */ + /* intervening vertex on the segment occurred. */ + org(searchtri2, midvertex2); + conformingedge(m, b, midvertex2, endpoint2, newmark); + } +} + +#endif /* not CDT_ONLY */ +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */ +/* recursively from an existing vertex. Pay special */ +/* attention to stacking inverted triangles. */ +/* */ +/* This is a support routine for inserting segments into a constrained */ +/* Delaunay triangulation. */ +/* */ +/* The origin of fixuptri is treated as if it has just been inserted, and */ +/* the local Delaunay condition needs to be enforced. It is only enforced */ +/* in one sector, however, that being the angular range defined by */ +/* fixuptri. */ +/* */ +/* This routine also needs to make decisions regarding the "stacking" of */ +/* triangles. (Read the description of constrainededge() below before */ +/* reading on here, so you understand the algorithm.) If the position of */ +/* the new vertex (the origin of fixuptri) indicates that the vertex before */ +/* it on the polygon is a reflex vertex, then "stack" the triangle by */ +/* doing nothing. (fixuptri is an inverted triangle, which is how stacked */ +/* triangles are identified.) */ +/* */ +/* Otherwise, check whether the vertex before that was a reflex vertex. */ +/* If so, perform an edge flip, thereby eliminating an inverted triangle */ +/* (popping it off the stack). The edge flip may result in the creation */ +/* of a new inverted triangle, depending on whether or not the new vertex */ +/* is visible to the vertex three edges behind on the polygon. */ +/* */ +/* If neither of the two vertices behind the new vertex are reflex */ +/* vertices, fixuptri and fartri, the triangle opposite it, are not */ +/* inverted; hence, ensure that the edge between them is locally Delaunay. */ +/* */ +/* `leftside' indicates whether or not fixuptri is to the left of the */ +/* segment being inserted. (Imagine that the segment is pointing up from */ +/* endpoint1 to endpoint2.) */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void delaunayfixup(struct mesh *m, struct behavior *b, + struct otri *fixuptri, int leftside) +#else /* not ANSI_DECLARATORS */ +void delaunayfixup(m, b, fixuptri, leftside) +struct mesh *m; +struct behavior *b; +struct otri *fixuptri; +int leftside; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri neartri; + struct otri fartri; + struct osub faredge; + vertex nearvertex, leftvertex, rightvertex, farvertex; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + lnext(*fixuptri, neartri); + sym(neartri, fartri); + /* Check if the edge opposite the origin of fixuptri can be flipped. */ + if (fartri.tri == m->dummytri) { + return; + } + tspivot(neartri, faredge); + if (faredge.ss != m->dummysub) { + return; + } + /* Find all the relevant vertices. */ + apex(neartri, nearvertex); + org(neartri, leftvertex); + dest(neartri, rightvertex); + apex(fartri, farvertex); + /* Check whether the previous polygon vertex is a reflex vertex. */ + if (leftside) { + if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) { + /* leftvertex is a reflex vertex too. Nothing can */ + /* be done until a convex section is found. */ + return; + } + } else { + if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) { + /* rightvertex is a reflex vertex too. Nothing can */ + /* be done until a convex section is found. */ + return; + } + } + if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) { + /* fartri is not an inverted triangle, and farvertex is not a reflex */ + /* vertex. As there are no reflex vertices, fixuptri isn't an */ + /* inverted triangle, either. Hence, test the edge between the */ + /* triangles to ensure it is locally Delaunay. */ + if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <= + 0.0) { + return; + } + /* Not locally Delaunay; go on to an edge flip. */ + } /* else fartri is inverted; remove it from the stack by flipping. */ + flip(m, b, &neartri); + lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */ + /* Recursively process the two triangles that result from the flip. */ + delaunayfixup(m, b, fixuptri, leftside); + delaunayfixup(m, b, &fartri, leftside); +} + +/*****************************************************************************/ +/* */ +/* constrainededge() Force a segment into a constrained Delaunay */ +/* triangulation by deleting the triangles it */ +/* intersects, and triangulating the polygons that */ +/* form on each side of it. */ +/* */ +/* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */ +/* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */ +/* boundary marker of the segment. */ +/* */ +/* To insert a segment, every triangle whose interior intersects the */ +/* segment is deleted. The union of these deleted triangles is a polygon */ +/* (which is not necessarily monotone, but is close enough), which is */ +/* divided into two polygons by the new segment. This routine's task is */ +/* to generate the Delaunay triangulation of these two polygons. */ +/* */ +/* You might think of this routine's behavior as a two-step process. The */ +/* first step is to walk from endpoint1 to endpoint2, flipping each edge */ +/* encountered. This step creates a fan of edges connected to endpoint1, */ +/* including the desired edge to endpoint2. The second step enforces the */ +/* Delaunay condition on each side of the segment in an incremental manner: */ +/* proceeding along the polygon from endpoint1 to endpoint2 (this is done */ +/* independently on each side of the segment), each vertex is "enforced" */ +/* as if it had just been inserted, but affecting only the previous */ +/* vertices. The result is the same as if the vertices had been inserted */ +/* in the order they appear on the polygon, so the result is Delaunay. */ +/* */ +/* In truth, constrainededge() interleaves these two steps. The procedure */ +/* walks from endpoint1 to endpoint2, and each time an edge is encountered */ +/* and flipped, the newly exposed vertex (at the far end of the flipped */ +/* edge) is "enforced" upon the previously flipped edges, usually affecting */ +/* only one side of the polygon (depending upon which side of the segment */ +/* the vertex falls on). */ +/* */ +/* The algorithm is complicated by the need to handle polygons that are not */ +/* convex. Although the polygon is not necessarily monotone, it can be */ +/* triangulated in a manner similar to the stack-based algorithms for */ +/* monotone polygons. For each reflex vertex (local concavity) of the */ +/* polygon, there will be an inverted triangle formed by one of the edge */ +/* flips. (An inverted triangle is one with negative area - that is, its */ +/* vertices are arranged in clockwise order - and is best thought of as a */ +/* wrinkle in the fabric of the mesh.) Each inverted triangle can be */ +/* thought of as a reflex vertex pushed on the stack, waiting to be fixed */ +/* later. */ +/* */ +/* A reflex vertex is popped from the stack when a vertex is inserted that */ +/* is visible to the reflex vertex. (However, if the vertex behind the */ +/* reflex vertex is not visible to the reflex vertex, a new inverted */ +/* triangle will take its place on the stack.) These details are handled */ +/* by the delaunayfixup() routine above. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void constrainededge(struct mesh *m, struct behavior *b, + struct otri *starttri, vertex endpoint2, int newmark) +#else /* not ANSI_DECLARATORS */ +void constrainededge(m, b, starttri, endpoint2, newmark) +struct mesh *m; +struct behavior *b; +struct otri *starttri; +vertex endpoint2; +int newmark; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri fixuptri, fixuptri2; + struct osub crosssubseg; + vertex endpoint1; + vertex farvertex; + REAL area; + int collision; + int done; + triangle ptr; /* Temporary variable used by sym() and oprev(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + org(*starttri, endpoint1); + lnext(*starttri, fixuptri); + flip(m, b, &fixuptri); + /* `collision' indicates whether we have found a vertex directly */ + /* between endpoint1 and endpoint2. */ + collision = 0; + done = 0; + do { + org(fixuptri, farvertex); + /* `farvertex' is the extreme point of the polygon we are "digging" */ + /* to get from endpoint1 to endpoint2. */ + if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) { + oprev(fixuptri, fixuptri2); + /* Enforce the Delaunay condition around endpoint2. */ + delaunayfixup(m, b, &fixuptri, 0); + delaunayfixup(m, b, &fixuptri2, 1); + done = 1; + } else { + /* Check whether farvertex is to the left or right of the segment */ + /* being inserted, to decide which edge of fixuptri to dig */ + /* through next. */ + area = counterclockwise(m, b, endpoint1, endpoint2, farvertex); + if (area == 0.0) { + /* We've collided with a vertex between endpoint1 and endpoint2. */ + collision = 1; + oprev(fixuptri, fixuptri2); + /* Enforce the Delaunay condition around farvertex. */ + delaunayfixup(m, b, &fixuptri, 0); + delaunayfixup(m, b, &fixuptri2, 1); + done = 1; + } else { + if (area > 0.0) { /* farvertex is to the left of the segment. */ + oprev(fixuptri, fixuptri2); + /* Enforce the Delaunay condition around farvertex, on the */ + /* left side of the segment only. */ + delaunayfixup(m, b, &fixuptri2, 1); + /* Flip the edge that crosses the segment. After the edge is */ + /* flipped, one of its endpoints is the fan vertex, and the */ + /* destination of fixuptri is the fan vertex. */ + lprevself(fixuptri); + } else { /* farvertex is to the right of the segment. */ + delaunayfixup(m, b, &fixuptri, 0); + /* Flip the edge that crosses the segment. After the edge is */ + /* flipped, one of its endpoints is the fan vertex, and the */ + /* destination of fixuptri is the fan vertex. */ + oprevself(fixuptri); + } + /* Check for two intersecting segments. */ + tspivot(fixuptri, crosssubseg); + if (crosssubseg.ss == m->dummysub) { + flip(m, b, &fixuptri); /* May create inverted triangle at left. */ + } else { + /* We've collided with a segment between endpoint1 and endpoint2. */ + collision = 1; + /* Insert a vertex at the intersection. */ + segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2); + done = 1; + } + } + } + } while (!done); + /* Insert a subsegment to make the segment permanent. */ + insertsubseg(m, b, &fixuptri, newmark); + /* If there was a collision with an interceding vertex, install another */ + /* segment connecting that vertex with endpoint2. */ + if (collision) { + /* Insert the remainder of the segment. */ + if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) { + constrainededge(m, b, &fixuptri, endpoint2, newmark); + } + } +} + +/*****************************************************************************/ +/* */ +/* insertsegment() Insert a PSLG segment into a triangulation. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void insertsegment(struct mesh *m, struct behavior *b, + vertex endpoint1, vertex endpoint2, int newmark) +#else /* not ANSI_DECLARATORS */ +void insertsegment(m, b, endpoint1, endpoint2, newmark) +struct mesh *m; +struct behavior *b; +vertex endpoint1; +vertex endpoint2; +int newmark; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri searchtri1, searchtri2; + triangle encodedtri; + vertex checkvertex; + triangle ptr; /* Temporary variable used by sym(). */ + + if (b->verbose > 1) { + printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n", + endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]); + } + + /* Find a triangle whose origin is the segment's first endpoint. */ + checkvertex = (vertex) NULL; + encodedtri = vertex2tri(endpoint1); + if (encodedtri != (triangle) NULL) { + decode(encodedtri, searchtri1); + org(searchtri1, checkvertex); + } + if (checkvertex != endpoint1) { + /* Find a boundary triangle to search from. */ + searchtri1.tri = m->dummytri; + searchtri1.orient = 0; + symself(searchtri1); + /* Search for the segment's first endpoint by point location. */ + if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) { + printf( + "Internal error in insertsegment(): Unable to locate PSLG vertex\n"); + printf(" (%.12g, %.12g) in triangulation.\n", + endpoint1[0], endpoint1[1]); + internalerror(); + } + } + /* Remember this triangle to improve subsequent point location. */ + otricopy(searchtri1, m->recenttri); + /* Scout the beginnings of a path from the first endpoint */ + /* toward the second. */ + if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) { + /* The segment was easily inserted. */ + return; + } + /* The first endpoint may have changed if a collision with an intervening */ + /* vertex on the segment occurred. */ + org(searchtri1, endpoint1); + + /* Find a triangle whose origin is the segment's second endpoint. */ + checkvertex = (vertex) NULL; + encodedtri = vertex2tri(endpoint2); + if (encodedtri != (triangle) NULL) { + decode(encodedtri, searchtri2); + org(searchtri2, checkvertex); + } + if (checkvertex != endpoint2) { + /* Find a boundary triangle to search from. */ + searchtri2.tri = m->dummytri; + searchtri2.orient = 0; + symself(searchtri2); + /* Search for the segment's second endpoint by point location. */ + if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) { + printf( + "Internal error in insertsegment(): Unable to locate PSLG vertex\n"); + printf(" (%.12g, %.12g) in triangulation.\n", + endpoint2[0], endpoint2[1]); + internalerror(); + } + } + /* Remember this triangle to improve subsequent point location. */ + otricopy(searchtri2, m->recenttri); + /* Scout the beginnings of a path from the second endpoint */ + /* toward the first. */ + if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) { + /* The segment was easily inserted. */ + return; + } + /* The second endpoint may have changed if a collision with an intervening */ + /* vertex on the segment occurred. */ + org(searchtri2, endpoint2); + +#ifndef REDUCED +#ifndef CDT_ONLY + if (b->splitseg) { + /* Insert vertices to force the segment into the triangulation. */ + conformingedge(m, b, endpoint1, endpoint2, newmark); + } else { +#endif /* not CDT_ONLY */ +#endif /* not REDUCED */ + /* Insert the segment directly into the triangulation. */ + constrainededge(m, b, &searchtri1, endpoint2, newmark); +#ifndef REDUCED +#ifndef CDT_ONLY + } +#endif /* not CDT_ONLY */ +#endif /* not REDUCED */ +} + +/*****************************************************************************/ +/* */ +/* markhull() Cover the convex hull of a triangulation with subsegments. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void markhull(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void markhull(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri hulltri; + struct otri nexttri; + struct otri starttri; + triangle ptr; /* Temporary variable used by sym() and oprev(). */ + + /* Find a triangle handle on the hull. */ + hulltri.tri = m->dummytri; + hulltri.orient = 0; + symself(hulltri); + /* Remember where we started so we know when to stop. */ + otricopy(hulltri, starttri); + /* Go once counterclockwise around the convex hull. */ + do { + /* Create a subsegment if there isn't already one here. */ + insertsubseg(m, b, &hulltri, 1); + /* To find the next hull edge, go clockwise around the next vertex. */ + lnextself(hulltri); + oprev(hulltri, nexttri); + while (nexttri.tri != m->dummytri) { + otricopy(nexttri, hulltri); + oprev(hulltri, nexttri); + } + } while (!otriequal(hulltri, starttri)); +} + +/*****************************************************************************/ +/* */ +/* formskeleton() Create the segments of a triangulation, including PSLG */ +/* segments and edges on the convex hull. */ +/* */ +/* The PSLG segments are read from a .poly file. The return value is the */ +/* number of segments in the file. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, + int *segmentmarkerlist, int numberofsegments) +#else /* not ANSI_DECLARATORS */ +void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments) +struct mesh *m; +struct behavior *b; +int *segmentlist; +int *segmentmarkerlist; +int numberofsegments; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void formskeleton(struct mesh *m, struct behavior *b, + FILE *polyfile, char *polyfilename) +#else /* not ANSI_DECLARATORS */ +void formskeleton(m, b, polyfile, polyfilename) +struct mesh *m; +struct behavior *b; +FILE *polyfile; +char *polyfilename; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + char polyfilename[6]; + int index; +#else /* not TRILIBRARY */ + char inputline[INPUTLINESIZE]; + char *stringptr; +#endif /* not TRILIBRARY */ + vertex endpoint1, endpoint2; + int segmentmarkers; + int end1, end2; + int boundmarker; + int i; + + if (b->poly) { + if (!b->quiet) { + printf("Recovering segments in Delaunay triangulation.\n"); + } +#ifdef TRILIBRARY + strcpy(polyfilename, "input"); + m->insegments = numberofsegments; + segmentmarkers = segmentmarkerlist != (int *) NULL; + index = 0; +#else /* not TRILIBRARY */ + /* Read the segments from a .poly file. */ + /* Read number of segments and number of boundary markers. */ + stringptr = readline(inputline, polyfile, polyfilename); + m->insegments = (int) strtol(stringptr, &stringptr, 0); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + segmentmarkers = 0; + } else { + segmentmarkers = (int) strtol(stringptr, &stringptr, 0); + } +#endif /* not TRILIBRARY */ + /* If the input vertices are collinear, there is no triangulation, */ + /* so don't try to insert segments. */ + if (m->triangles.items == 0) { + return; + } + + /* If segments are to be inserted, compute a mapping */ + /* from vertices to triangles. */ + if (m->insegments > 0) { + makevertexmap(m, b); + if (b->verbose) { + printf(" Recovering PSLG segments.\n"); + } + } + + boundmarker = 0; + /* Read and insert the segments. */ + for (i = 0; i < m->insegments; i++) { +#ifdef TRILIBRARY + end1 = segmentlist[index++]; + end2 = segmentlist[index++]; + if (segmentmarkers) { + boundmarker = segmentmarkerlist[i]; + } +#else /* not TRILIBRARY */ + stringptr = readline(inputline, polyfile, b->inpolyfilename); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Segment %d has no endpoints in %s.\n", + b->firstnumber + i, polyfilename); + triexit(1); + } else { + end1 = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Segment %d is missing its second endpoint in %s.\n", + b->firstnumber + i, polyfilename); + triexit(1); + } else { + end2 = (int) strtol(stringptr, &stringptr, 0); + } + if (segmentmarkers) { + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + boundmarker = 0; + } else { + boundmarker = (int) strtol(stringptr, &stringptr, 0); + } + } +#endif /* not TRILIBRARY */ + if ((end1 < b->firstnumber) || + (end1 >= b->firstnumber + m->invertices)) { + if (!b->quiet) { + printf("Warning: Invalid first endpoint of segment %d in %s.\n", + b->firstnumber + i, polyfilename); + } + } else if ((end2 < b->firstnumber) || + (end2 >= b->firstnumber + m->invertices)) { + if (!b->quiet) { + printf("Warning: Invalid second endpoint of segment %d in %s.\n", + b->firstnumber + i, polyfilename); + } + } else { + /* Find the vertices numbered `end1' and `end2'. */ + endpoint1 = getvertex(m, b, end1); + endpoint2 = getvertex(m, b, end2); + if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) { + if (!b->quiet) { + printf("Warning: Endpoints of segment %d are coincident in %s.\n", + b->firstnumber + i, polyfilename); + } + } else { + insertsegment(m, b, endpoint1, endpoint2, boundmarker); + } + } + } + } else { + m->insegments = 0; + } + if (b->convex || !b->poly) { + /* Enclose the convex hull with subsegments. */ + if (b->verbose) { + printf(" Enclosing convex hull with segments.\n"); + } + markhull(m, b); + } +} + +/** **/ +/** **/ +/********* Segment insertion ends here *********/ + +/********* Carving out holes and concavities begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* infecthull() Virally infect all of the triangles of the convex hull */ +/* that are not protected by subsegments. Where there are */ +/* subsegments, set boundary markers as appropriate. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void infecthull(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void infecthull(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri hulltri; + struct otri nexttri; + struct otri starttri; + struct osub hullsubseg; + triangle **deadtriangle; + vertex horg, hdest; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (b->verbose) { + printf(" Marking concavities (external triangles) for elimination.\n"); + } + /* Find a triangle handle on the hull. */ + hulltri.tri = m->dummytri; + hulltri.orient = 0; + symself(hulltri); + /* Remember where we started so we know when to stop. */ + otricopy(hulltri, starttri); + /* Go once counterclockwise around the convex hull. */ + do { + /* Ignore triangles that are already infected. */ + if (!infected(hulltri)) { + /* Is the triangle protected by a subsegment? */ + tspivot(hulltri, hullsubseg); + if (hullsubseg.ss == m->dummysub) { + /* The triangle is not protected; infect it. */ + if (!infected(hulltri)) { + infect(hulltri); + deadtriangle = (triangle **) poolalloc(&m->viri); + *deadtriangle = hulltri.tri; + } + } else { + /* The triangle is protected; set boundary markers if appropriate. */ + if (mark(hullsubseg) == 0) { + setmark(hullsubseg, 1); + org(hulltri, horg); + dest(hulltri, hdest); + if (vertexmark(horg) == 0) { + setvertexmark(horg, 1); + } + if (vertexmark(hdest) == 0) { + setvertexmark(hdest, 1); + } + } + } + } + /* To find the next hull edge, go clockwise around the next vertex. */ + lnextself(hulltri); + oprev(hulltri, nexttri); + while (nexttri.tri != m->dummytri) { + otricopy(nexttri, hulltri); + oprev(hulltri, nexttri); + } + } while (!otriequal(hulltri, starttri)); +} + +/*****************************************************************************/ +/* */ +/* plague() Spread the virus from all infected triangles to any neighbors */ +/* not protected by subsegments. Delete all infected triangles. */ +/* */ +/* This is the procedure that actually creates holes and concavities. */ +/* */ +/* This procedure operates in two phases. The first phase identifies all */ +/* the triangles that will die, and marks them as infected. They are */ +/* marked to ensure that each triangle is added to the virus pool only */ +/* once, so the procedure will terminate. */ +/* */ +/* The second phase actually eliminates the infected triangles. It also */ +/* eliminates orphaned vertices. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void plague(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void plague(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri testtri; + struct otri neighbor; + triangle **virusloop; + triangle **deadtriangle; + struct osub neighborsubseg; + vertex testvertex; + vertex norg, ndest; + vertex deadorg, deaddest, deadapex; + int killorg; + triangle ptr; /* Temporary variable used by sym() and onext(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (b->verbose) { + printf(" Marking neighbors of marked triangles.\n"); + } + /* Loop through all the infected triangles, spreading the virus to */ + /* their neighbors, then to their neighbors' neighbors. */ + traversalinit(&m->viri); + virusloop = (triangle **) traverse(&m->viri); + while (virusloop != (triangle **) NULL) { + testtri.tri = *virusloop; + /* A triangle is marked as infected by messing with one of its pointers */ + /* to subsegments, setting it to an illegal value. Hence, we have to */ + /* temporarily uninfect this triangle so that we can examine its */ + /* adjacent subsegments. */ + uninfect(testtri); + if (b->verbose > 2) { + /* Assign the triangle an orientation for convenience in */ + /* checking its vertices. */ + testtri.orient = 0; + org(testtri, deadorg); + dest(testtri, deaddest); + apex(testtri, deadapex); + printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + deadorg[0], deadorg[1], deaddest[0], deaddest[1], + deadapex[0], deadapex[1]); + } + /* Check each of the triangle's three neighbors. */ + for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { + /* Find the neighbor. */ + sym(testtri, neighbor); + /* Check for a subsegment between the triangle and its neighbor. */ + tspivot(testtri, neighborsubseg); + /* Check if the neighbor is nonexistent or already infected. */ + if ((neighbor.tri == m->dummytri) || infected(neighbor)) { + if (neighborsubseg.ss != m->dummysub) { + /* There is a subsegment separating the triangle from its */ + /* neighbor, but both triangles are dying, so the subsegment */ + /* dies too. */ + subsegdealloc(m, neighborsubseg.ss); + if (neighbor.tri != m->dummytri) { + /* Make sure the subsegment doesn't get deallocated again */ + /* later when the infected neighbor is visited. */ + uninfect(neighbor); + tsdissolve(neighbor); + infect(neighbor); + } + } + } else { /* The neighbor exists and is not infected. */ + if (neighborsubseg.ss == m->dummysub) { + /* There is no subsegment protecting the neighbor, so */ + /* the neighbor becomes infected. */ + if (b->verbose > 2) { + org(neighbor, deadorg); + dest(neighbor, deaddest); + apex(neighbor, deadapex); + printf( + " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + deadorg[0], deadorg[1], deaddest[0], deaddest[1], + deadapex[0], deadapex[1]); + } + infect(neighbor); + /* Ensure that the neighbor's neighbors will be infected. */ + deadtriangle = (triangle **) poolalloc(&m->viri); + *deadtriangle = neighbor.tri; + } else { /* The neighbor is protected by a subsegment. */ + /* Remove this triangle from the subsegment. */ + stdissolve(neighborsubseg); + /* The subsegment becomes a boundary. Set markers accordingly. */ + if (mark(neighborsubseg) == 0) { + setmark(neighborsubseg, 1); + } + org(neighbor, norg); + dest(neighbor, ndest); + if (vertexmark(norg) == 0) { + setvertexmark(norg, 1); + } + if (vertexmark(ndest) == 0) { + setvertexmark(ndest, 1); + } + } + } + } + /* Remark the triangle as infected, so it doesn't get added to the */ + /* virus pool again. */ + infect(testtri); + virusloop = (triangle **) traverse(&m->viri); + } + + if (b->verbose) { + printf(" Deleting marked triangles.\n"); + } + + traversalinit(&m->viri); + virusloop = (triangle **) traverse(&m->viri); + while (virusloop != (triangle **) NULL) { + testtri.tri = *virusloop; + + /* Check each of the three corners of the triangle for elimination. */ + /* This is done by walking around each vertex, checking if it is */ + /* still connected to at least one live triangle. */ + for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { + org(testtri, testvertex); + /* Check if the vertex has already been tested. */ + if (testvertex != (vertex) NULL) { + killorg = 1; + /* Mark the corner of the triangle as having been tested. */ + setorg(testtri, NULL); + /* Walk counterclockwise about the vertex. */ + onext(testtri, neighbor); + /* Stop upon reaching a boundary or the starting triangle. */ + while ((neighbor.tri != m->dummytri) && + (!otriequal(neighbor, testtri))) { + if (infected(neighbor)) { + /* Mark the corner of this triangle as having been tested. */ + setorg(neighbor, NULL); + } else { + /* A live triangle. The vertex survives. */ + killorg = 0; + } + /* Walk counterclockwise about the vertex. */ + onextself(neighbor); + } + /* If we reached a boundary, we must walk clockwise as well. */ + if (neighbor.tri == m->dummytri) { + /* Walk clockwise about the vertex. */ + oprev(testtri, neighbor); + /* Stop upon reaching a boundary. */ + while (neighbor.tri != m->dummytri) { + if (infected(neighbor)) { + /* Mark the corner of this triangle as having been tested. */ + setorg(neighbor, NULL); + } else { + /* A live triangle. The vertex survives. */ + killorg = 0; + } + /* Walk clockwise about the vertex. */ + oprevself(neighbor); + } + } + if (killorg) { + if (b->verbose > 1) { + printf(" Deleting vertex (%.12g, %.12g)\n", + testvertex[0], testvertex[1]); + } + setvertextype(testvertex, UNDEADVERTEX); + m->undeads++; + } + } + } + + /* Record changes in the number of boundary edges, and disconnect */ + /* dead triangles from their neighbors. */ + for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { + sym(testtri, neighbor); + if (neighbor.tri == m->dummytri) { + /* There is no neighboring triangle on this edge, so this edge */ + /* is a boundary edge. This triangle is being deleted, so this */ + /* boundary edge is deleted. */ + m->hullsize--; + } else { + /* Disconnect the triangle from its neighbor. */ + dissolve(neighbor); + /* There is a neighboring triangle on this edge, so this edge */ + /* becomes a boundary edge when this triangle is deleted. */ + m->hullsize++; + } + } + /* Return the dead triangle to the pool of triangles. */ + triangledealloc(m, testtri.tri); + virusloop = (triangle **) traverse(&m->viri); + } + /* Empty the virus pool. */ + poolrestart(&m->viri); +} + +/*****************************************************************************/ +/* */ +/* regionplague() Spread regional attributes and/or area constraints */ +/* (from a .poly file) throughout the mesh. */ +/* */ +/* This procedure operates in two phases. The first phase spreads an */ +/* attribute and/or an area constraint through a (segment-bounded) region. */ +/* The triangles are marked to ensure that each triangle is added to the */ +/* virus pool only once, so the procedure will terminate. */ +/* */ +/* The second phase uninfects all infected triangles, returning them to */ +/* normal. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void regionplague(struct mesh *m, struct behavior *b, + REAL attribute, REAL area) +#else /* not ANSI_DECLARATORS */ +void regionplague(m, b, attribute, area) +struct mesh *m; +struct behavior *b; +REAL attribute; +REAL area; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri testtri; + struct otri neighbor; + triangle **virusloop; + triangle **regiontri; + struct osub neighborsubseg; + vertex regionorg, regiondest, regionapex; + triangle ptr; /* Temporary variable used by sym() and onext(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (b->verbose > 1) { + printf(" Marking neighbors of marked triangles.\n"); + } + /* Loop through all the infected triangles, spreading the attribute */ + /* and/or area constraint to their neighbors, then to their neighbors' */ + /* neighbors. */ + traversalinit(&m->viri); + virusloop = (triangle **) traverse(&m->viri); + while (virusloop != (triangle **) NULL) { + testtri.tri = *virusloop; + /* A triangle is marked as infected by messing with one of its pointers */ + /* to subsegments, setting it to an illegal value. Hence, we have to */ + /* temporarily uninfect this triangle so that we can examine its */ + /* adjacent subsegments. */ + uninfect(testtri); + if (b->regionattrib) { + /* Set an attribute. */ + setelemattribute(testtri, m->eextras, attribute); + } + if (b->vararea) { + /* Set an area constraint. */ + setareabound(testtri, area); + } + if (b->verbose > 2) { + /* Assign the triangle an orientation for convenience in */ + /* checking its vertices. */ + testtri.orient = 0; + org(testtri, regionorg); + dest(testtri, regiondest); + apex(testtri, regionapex); + printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + regionorg[0], regionorg[1], regiondest[0], regiondest[1], + regionapex[0], regionapex[1]); + } + /* Check each of the triangle's three neighbors. */ + for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { + /* Find the neighbor. */ + sym(testtri, neighbor); + /* Check for a subsegment between the triangle and its neighbor. */ + tspivot(testtri, neighborsubseg); + /* Make sure the neighbor exists, is not already infected, and */ + /* isn't protected by a subsegment. */ + if ((neighbor.tri != m->dummytri) && !infected(neighbor) + && (neighborsubseg.ss == m->dummysub)) { + if (b->verbose > 2) { + org(neighbor, regionorg); + dest(neighbor, regiondest); + apex(neighbor, regionapex); + printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + regionorg[0], regionorg[1], regiondest[0], regiondest[1], + regionapex[0], regionapex[1]); + } + /* Infect the neighbor. */ + infect(neighbor); + /* Ensure that the neighbor's neighbors will be infected. */ + regiontri = (triangle **) poolalloc(&m->viri); + *regiontri = neighbor.tri; + } + } + /* Remark the triangle as infected, so it doesn't get added to the */ + /* virus pool again. */ + infect(testtri); + virusloop = (triangle **) traverse(&m->viri); + } + + /* Uninfect all triangles. */ + if (b->verbose > 1) { + printf(" Unmarking marked triangles.\n"); + } + traversalinit(&m->viri); + virusloop = (triangle **) traverse(&m->viri); + while (virusloop != (triangle **) NULL) { + testtri.tri = *virusloop; + uninfect(testtri); + virusloop = (triangle **) traverse(&m->viri); + } + /* Empty the virus pool. */ + poolrestart(&m->viri); +} + +/*****************************************************************************/ +/* */ +/* carveholes() Find the holes and infect them. Find the area */ +/* constraints and infect them. Infect the convex hull. */ +/* Spread the infection and kill triangles. Spread the */ +/* area constraints. */ +/* */ +/* This routine mainly calls other routines to carry out all these */ +/* functions. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, + REAL *regionlist, int regions) +#else /* not ANSI_DECLARATORS */ +void carveholes(m, b, holelist, holes, regionlist, regions) +struct mesh *m; +struct behavior *b; +REAL *holelist; +int holes; +REAL *regionlist; +int regions; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri searchtri; + struct otri triangleloop; + struct otri *regiontris; + triangle **holetri; + triangle **regiontri; + vertex searchorg, searchdest; + enum locateresult intersect; + int i; + triangle ptr; /* Temporary variable used by sym(). */ + + if (!(b->quiet || (b->noholes && b->convex))) { + printf("Removing unwanted triangles.\n"); + if (b->verbose && (holes > 0)) { + printf(" Marking holes for elimination.\n"); + } + } + + if (regions > 0) { + /* Allocate storage for the triangles in which region points fall. */ + regiontris = (struct otri *) trimalloc(regions * + (int) sizeof(struct otri)); + } else { + regiontris = (struct otri *) NULL; + } + + if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) { + /* Initialize a pool of viri to be used for holes, concavities, */ + /* regional attributes, and/or regional area constraints. */ + poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0); + } + + if (!b->convex) { + /* Mark as infected any unprotected triangles on the boundary. */ + /* This is one way by which concavities are created. */ + infecthull(m, b); + } + + if ((holes > 0) && !b->noholes) { + /* Infect each triangle in which a hole lies. */ + for (i = 0; i < 2 * holes; i += 2) { + /* Ignore holes that aren't within the bounds of the mesh. */ + if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax) + && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) { + /* Start searching from some triangle on the outer boundary. */ + searchtri.tri = m->dummytri; + searchtri.orient = 0; + symself(searchtri); + /* Ensure that the hole is to the left of this boundary edge; */ + /* otherwise, locate() will falsely report that the hole */ + /* falls within the starting triangle. */ + org(searchtri, searchorg); + dest(searchtri, searchdest); + if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) > + 0.0) { + /* Find a triangle that contains the hole. */ + intersect = locate(m, b, &holelist[i], &searchtri); + if ((intersect != OUTSIDE) && (!infected(searchtri))) { + /* Infect the triangle. This is done by marking the triangle */ + /* as infected and including the triangle in the virus pool. */ + infect(searchtri); + holetri = (triangle **) poolalloc(&m->viri); + *holetri = searchtri.tri; + } + } + } + } + } + + /* Now, we have to find all the regions BEFORE we carve the holes, because */ + /* locate() won't work when the triangulation is no longer convex. */ + /* (Incidentally, this is the reason why regional attributes and area */ + /* constraints can't be used when refining a preexisting mesh, which */ + /* might not be convex; they can only be used with a freshly */ + /* triangulated PSLG.) */ + if (regions > 0) { + /* Find the starting triangle for each region. */ + for (i = 0; i < regions; i++) { + regiontris[i].tri = m->dummytri; + /* Ignore region points that aren't within the bounds of the mesh. */ + if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) && + (regionlist[4 * i + 1] >= m->ymin) && + (regionlist[4 * i + 1] <= m->ymax)) { + /* Start searching from some triangle on the outer boundary. */ + searchtri.tri = m->dummytri; + searchtri.orient = 0; + symself(searchtri); + /* Ensure that the region point is to the left of this boundary */ + /* edge; otherwise, locate() will falsely report that the */ + /* region point falls within the starting triangle. */ + org(searchtri, searchorg); + dest(searchtri, searchdest); + if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) > + 0.0) { + /* Find a triangle that contains the region point. */ + intersect = locate(m, b, ®ionlist[4 * i], &searchtri); + if ((intersect != OUTSIDE) && (!infected(searchtri))) { + /* Record the triangle for processing after the */ + /* holes have been carved. */ + otricopy(searchtri, regiontris[i]); + } + } + } + } + } + + if (m->viri.items > 0) { + /* Carve the holes and concavities. */ + plague(m, b); + } + /* The virus pool should be empty now. */ + + if (regions > 0) { + if (!b->quiet) { + if (b->regionattrib) { + if (b->vararea) { + printf("Spreading regional attributes and area constraints.\n"); + } else { + printf("Spreading regional attributes.\n"); + } + } else { + printf("Spreading regional area constraints.\n"); + } + } + if (b->regionattrib && !b->refine) { + /* Assign every triangle a regional attribute of zero. */ + traversalinit(&m->triangles); + triangleloop.orient = 0; + triangleloop.tri = triangletraverse(m); + while (triangleloop.tri != (triangle *) NULL) { + setelemattribute(triangleloop, m->eextras, 0.0); + triangleloop.tri = triangletraverse(m); + } + } + for (i = 0; i < regions; i++) { + if (regiontris[i].tri != m->dummytri) { + /* Make sure the triangle under consideration still exists. */ + /* It may have been eaten by the virus. */ + if (!deadtri(regiontris[i].tri)) { + /* Put one triangle in the virus pool. */ + infect(regiontris[i]); + regiontri = (triangle **) poolalloc(&m->viri); + *regiontri = regiontris[i].tri; + /* Apply one region's attribute and/or area constraint. */ + regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]); + /* The virus pool should be empty now. */ + } + } + } + if (b->regionattrib && !b->refine) { + /* Note the fact that each triangle has an additional attribute. */ + m->eextras++; + } + } + + /* Free up memory. */ + if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) { + pooldeinit(&m->viri); + } + if (regions > 0) { + trifree((VOID *) regiontris); + } +} + +/** **/ +/** **/ +/********* Carving out holes and concavities ends here *********/ + +/********* Mesh quality maintenance begins here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* tallyencs() Traverse the entire list of subsegments, and check each */ +/* to see if it is encroached. If so, add it to the list. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void tallyencs(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void tallyencs(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct osub subsegloop; + int dummy; + + traversalinit(&m->subsegs); + subsegloop.ssorient = 0; + subsegloop.ss = subsegtraverse(m); + while (subsegloop.ss != (subseg *) NULL) { + /* If the segment is encroached, add it to the list. */ + dummy = checkseg4encroach(m, b, &subsegloop); + subsegloop.ss = subsegtraverse(m); + } +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* precisionerror() Print an error message for precision problems. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +void precisionerror() +{ + printf("Try increasing the area criterion and/or reducing the minimum\n"); + printf(" allowable angle so that tiny triangles are not created.\n"); +#ifdef SINGLE + printf("Alternatively, try recompiling me with double precision\n"); + printf(" arithmetic (by removing \"#define SINGLE\" from the\n"); + printf(" source file or \"-DSINGLE\" from the makefile).\n"); +#endif /* SINGLE */ +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* splitencsegs() Split all the encroached subsegments. */ +/* */ +/* Each encroached subsegment is repaired by splitting it - inserting a */ +/* vertex at or near its midpoint. Newly inserted vertices may encroach */ +/* upon other subsegments; these are also repaired. */ +/* */ +/* `triflaws' is a flag that specifies whether one should take note of new */ +/* bad triangles that result from inserting vertices to repair encroached */ +/* subsegments. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void splitencsegs(struct mesh *m, struct behavior *b, int triflaws) +#else /* not ANSI_DECLARATORS */ +void splitencsegs(m, b, triflaws) +struct mesh *m; +struct behavior *b; +int triflaws; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri enctri; + struct otri testtri; + struct osub testsh; + struct osub currentenc; + struct badsubseg *encloop; + vertex eorg, edest, eapex; + vertex newvertex; + enum insertvertexresult success; + REAL segmentlength, nearestpoweroftwo; + REAL split; + REAL multiplier, divisor; + int acuteorg, acuteorg2, acutedest, acutedest2; + int dummy; + int i; + triangle ptr; /* Temporary variable used by stpivot(). */ + subseg sptr; /* Temporary variable used by snext(). */ + + /* Note that steinerleft == -1 if an unlimited number */ + /* of Steiner points is allowed. */ + while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) { + traversalinit(&m->badsubsegs); + encloop = badsubsegtraverse(m); + while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) { + sdecode(encloop->encsubseg, currentenc); + sorg(currentenc, eorg); + sdest(currentenc, edest); + /* Make sure that this segment is still the same segment it was */ + /* when it was determined to be encroached. If the segment was */ + /* enqueued multiple times (because several newly inserted */ + /* vertices encroached it), it may have already been split. */ + if (!deadsubseg(currentenc.ss) && + (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) { + /* To decide where to split a segment, we need to know if the */ + /* segment shares an endpoint with an adjacent segment. */ + /* The concern is that, if we simply split every encroached */ + /* segment in its center, two adjacent segments with a small */ + /* angle between them might lead to an infinite loop; each */ + /* vertex added to split one segment will encroach upon the */ + /* other segment, which must then be split with a vertex that */ + /* will encroach upon the first segment, and so on forever. */ + /* To avoid this, imagine a set of concentric circles, whose */ + /* radii are powers of two, about each segment endpoint. */ + /* These concentric circles determine where the segment is */ + /* split. (If both endpoints are shared with adjacent */ + /* segments, split the segment in the middle, and apply the */ + /* concentric circles for later splittings.) */ + + /* Is the origin shared with another segment? */ + stpivot(currentenc, enctri); + lnext(enctri, testtri); + tspivot(testtri, testsh); + acuteorg = testsh.ss != m->dummysub; + /* Is the destination shared with another segment? */ + lnextself(testtri); + tspivot(testtri, testsh); + acutedest = testsh.ss != m->dummysub; + + /* If we're using Chew's algorithm (rather than Ruppert's) */ + /* to define encroachment, delete free vertices from the */ + /* subsegment's diametral circle. */ + if (!b->conformdel && !acuteorg && !acutedest) { + apex(enctri, eapex); + while ((vertextype(eapex) == FREEVERTEX) && + ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) { + deletevertex(m, b, &testtri); + stpivot(currentenc, enctri); + apex(enctri, eapex); + lprev(enctri, testtri); + } + } + + /* Now, check the other side of the segment, if there's a triangle */ + /* there. */ + sym(enctri, testtri); + if (testtri.tri != m->dummytri) { + /* Is the destination shared with another segment? */ + lnextself(testtri); + tspivot(testtri, testsh); + acutedest2 = testsh.ss != m->dummysub; + acutedest = acutedest || acutedest2; + /* Is the origin shared with another segment? */ + lnextself(testtri); + tspivot(testtri, testsh); + acuteorg2 = testsh.ss != m->dummysub; + acuteorg = acuteorg || acuteorg2; + + /* Delete free vertices from the subsegment's diametral circle. */ + if (!b->conformdel && !acuteorg2 && !acutedest2) { + org(testtri, eapex); + while ((vertextype(eapex) == FREEVERTEX) && + ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + + (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) { + deletevertex(m, b, &testtri); + sym(enctri, testtri); + apex(testtri, eapex); + lprevself(testtri); + } + } + } + + /* Use the concentric circles if exactly one endpoint is shared */ + /* with another adjacent segment. */ + if (acuteorg || acutedest) { + segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) + + (edest[1] - eorg[1]) * (edest[1] - eorg[1])); + /* Find the power of two that most evenly splits the segment. */ + /* The worst case is a 2:1 ratio between subsegment lengths. */ + nearestpoweroftwo = 1.0; + while (segmentlength > 3.0 * nearestpoweroftwo) { + nearestpoweroftwo *= 2.0; + } + while (segmentlength < 1.5 * nearestpoweroftwo) { + nearestpoweroftwo *= 0.5; + } + /* Where do we split the segment? */ + split = nearestpoweroftwo / segmentlength; + if (acutedest) { + split = 1.0 - split; + } + } else { + /* If we're not worried about adjacent segments, split */ + /* this segment in the middle. */ + split = 0.5; + } + + /* Create the new vertex. */ + newvertex = (vertex) poolalloc(&m->vertices); + /* Interpolate its coordinate and attributes. */ + for (i = 0; i < 2 + m->nextras; i++) { + newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]); + } + + if (!b->noexact) { + /* Roundoff in the above calculation may yield a `newvertex' */ + /* that is not precisely collinear with `eorg' and `edest'. */ + /* Improve collinearity by one step of iterative refinement. */ + multiplier = counterclockwise(m, b, eorg, edest, newvertex); + divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) + + (eorg[1] - edest[1]) * (eorg[1] - edest[1])); + if ((multiplier != 0.0) && (divisor != 0.0)) { + multiplier = multiplier / divisor; + /* Watch out for NANs. */ + if (multiplier == multiplier) { + newvertex[0] += multiplier * (edest[1] - eorg[1]); + newvertex[1] += multiplier * (eorg[0] - edest[0]); + } + } + } + + setvertexmark(newvertex, mark(currentenc)); + setvertextype(newvertex, SEGMENTVERTEX); + if (b->verbose > 1) { + printf( + " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", + eorg[0], eorg[1], edest[0], edest[1], + newvertex[0], newvertex[1]); + } + /* Check whether the new vertex lies on an endpoint. */ + if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) || + ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) { + printf("Error: Ran out of precision at (%.12g, %.12g).\n", + newvertex[0], newvertex[1]); + printf("I attempted to split a segment to a smaller size than\n"); + printf(" can be accommodated by the finite precision of\n"); + printf(" floating point arithmetic.\n"); + precisionerror(); + triexit(1); + } + /* Insert the splitting vertex. This should always succeed. */ + success = insertvertex(m, b, newvertex, &enctri, ¤tenc, + 1, triflaws); + if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) { + printf("Internal error in splitencsegs():\n"); + printf(" Failure to split a segment.\n"); + internalerror(); + } + if (m->steinerleft > 0) { + m->steinerleft--; + } + /* Check the two new subsegments to see if they're encroached. */ + dummy = checkseg4encroach(m, b, ¤tenc); + snextself(currentenc); + dummy = checkseg4encroach(m, b, ¤tenc); + } + + badsubsegdealloc(m, encloop); + encloop = badsubsegtraverse(m); + } + } +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* tallyfaces() Test every triangle in the mesh for quality measures. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void tallyfaces(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void tallyfaces(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop; + + if (b->verbose) { + printf(" Making a list of bad triangles.\n"); + } + traversalinit(&m->triangles); + triangleloop.orient = 0; + triangleloop.tri = triangletraverse(m); + while (triangleloop.tri != (triangle *) NULL) { + /* If the triangle is bad, enqueue it. */ + testtriangle(m, b, &triangleloop); + triangleloop.tri = triangletraverse(m); + } +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* splittriangle() Inserts a vertex at the circumcenter of a triangle. */ +/* Deletes the newly inserted vertex if it encroaches */ +/* upon a segment. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void splittriangle(struct mesh *m, struct behavior *b, + struct badtriang *badtri) +#else /* not ANSI_DECLARATORS */ +void splittriangle(m, b, badtri) +struct mesh *m; +struct behavior *b; +struct badtriang *badtri; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri badotri; + vertex borg, bdest, bapex; + vertex newvertex; + REAL xi, eta; + enum insertvertexresult success; + int errorflag; + int i; + + decode(badtri->poortri, badotri); + org(badotri, borg); + dest(badotri, bdest); + apex(badotri, bapex); + /* Make sure that this triangle is still the same triangle it was */ + /* when it was tested and determined to be of bad quality. */ + /* Subsequent transformations may have made it a different triangle. */ + if (!deadtri(badotri.tri) && (borg == badtri->triangorg) && + (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) { + if (b->verbose > 1) { + printf(" Splitting this triangle at its circumcenter:\n"); + printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0], + borg[1], bdest[0], bdest[1], bapex[0], bapex[1]); + } + + errorflag = 0; + /* Create a new vertex at the triangle's circumcenter. */ + newvertex = (vertex) poolalloc(&m->vertices); + findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1); + + /* Check whether the new vertex lies on a triangle vertex. */ + if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) || + ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) || + ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) { + if (!b->quiet) { + printf( + "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n", + newvertex[0], newvertex[1]); + errorflag = 1; + } + vertexdealloc(m, newvertex); + } else { + for (i = 2; i < 2 + m->nextras; i++) { + /* Interpolate the vertex attributes at the circumcenter. */ + newvertex[i] = borg[i] + xi * (bdest[i] - borg[i]) + + eta * (bapex[i] - borg[i]); + } + /* The new vertex must be in the interior, and therefore is a */ + /* free vertex with a marker of zero. */ + setvertexmark(newvertex, 0); + setvertextype(newvertex, FREEVERTEX); + + /* Ensure that the handle `badotri' does not represent the longest */ + /* edge of the triangle. This ensures that the circumcenter must */ + /* fall to the left of this edge, so point location will work. */ + /* (If the angle org-apex-dest exceeds 90 degrees, then the */ + /* circumcenter lies outside the org-dest edge, and eta is */ + /* negative. Roundoff error might prevent eta from being */ + /* negative when it should be, so I test eta against xi.) */ + if (eta < xi) { + lprevself(badotri); + } + + /* Insert the circumcenter, searching from the edge of the triangle, */ + /* and maintain the Delaunay property of the triangulation. */ + success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL, + 1, 1); + if (success == SUCCESSFULVERTEX) { + if (m->steinerleft > 0) { + m->steinerleft--; + } + } else if (success == ENCROACHINGVERTEX) { + /* If the newly inserted vertex encroaches upon a subsegment, */ + /* delete the new vertex. */ + undovertex(m, b); + if (b->verbose > 1) { + printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]); + } + vertexdealloc(m, newvertex); + } else if (success == VIOLATINGVERTEX) { + /* Failed to insert the new vertex, but some subsegment was */ + /* marked as being encroached. */ + vertexdealloc(m, newvertex); + } else { /* success == DUPLICATEVERTEX */ + /* Couldn't insert the new vertex because a vertex is already there. */ + if (!b->quiet) { + printf( + "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n", + newvertex[0], newvertex[1]); + errorflag = 1; + } + vertexdealloc(m, newvertex); + } + } + if (errorflag) { + if (b->verbose) { + printf(" The new vertex is at the circumcenter of triangle\n"); + printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", + borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]); + } + printf("This probably means that I am trying to refine triangles\n"); + printf(" to a smaller size than can be accommodated by the finite\n"); + printf(" precision of floating point arithmetic. (You can be\n"); + printf(" sure of this if I fail to terminate.)\n"); + precisionerror(); + } + } +} + +#endif /* not CDT_ONLY */ + +/*****************************************************************************/ +/* */ +/* enforcequality() Remove all the encroached subsegments and bad */ +/* triangles from the triangulation. */ +/* */ +/*****************************************************************************/ + +#ifndef CDT_ONLY + +#ifdef ANSI_DECLARATORS +void enforcequality(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void enforcequality(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct badtriang *badtri; + int i; + + if (!b->quiet) { + printf("Adding Steiner points to enforce quality.\n"); + } + /* Initialize the pool of encroached subsegments. */ + poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK, + BADSUBSEGPERBLOCK, 0); + if (b->verbose) { + printf(" Looking for encroached subsegments.\n"); + } + /* Test all segments to see if they're encroached. */ + tallyencs(m, b); + if (b->verbose && (m->badsubsegs.items > 0)) { + printf(" Splitting encroached subsegments.\n"); + } + /* Fix encroached subsegments without noting bad triangles. */ + splitencsegs(m, b, 0); + /* At this point, if we haven't run out of Steiner points, the */ + /* triangulation should be (conforming) Delaunay. */ + + /* Next, we worry about enforcing triangle quality. */ + if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) { + /* Initialize the pool of bad triangles. */ + poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK, + BADTRIPERBLOCK, 0); + /* Initialize the queues of bad triangles. */ + for (i = 0; i < 4096; i++) { + m->queuefront[i] = (struct badtriang *) NULL; + } + m->firstnonemptyq = -1; + /* Test all triangles to see if they're bad. */ + tallyfaces(m, b); + /* Initialize the pool of recently flipped triangles. */ + poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK, + FLIPSTACKERPERBLOCK, 0); + m->checkquality = 1; + if (b->verbose) { + printf(" Splitting bad triangles.\n"); + } + while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) { + /* Fix one bad triangle by inserting a vertex at its circumcenter. */ + badtri = dequeuebadtriang(m); + splittriangle(m, b, badtri); + if (m->badsubsegs.items > 0) { + /* Put bad triangle back in queue for another try later. */ + enqueuebadtriang(m, b, badtri); + /* Fix any encroached subsegments that resulted. */ + /* Record any new bad triangles that result. */ + splitencsegs(m, b, 1); + } else { + /* Return the bad triangle to the pool. */ + pooldealloc(&m->badtriangles, (VOID *) badtri); + } + } + } + /* At this point, if the "-D" switch was selected and we haven't run out */ + /* of Steiner points, the triangulation should be (conforming) Delaunay */ + /* and have no low-quality triangles. */ + + /* Might we have run out of Steiner points too soon? */ + if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) && + (m->steinerleft == 0)) { + printf("\nWarning: I ran out of Steiner points, but the mesh has\n"); + if (m->badsubsegs.items == 1) { + printf(" one encroached subsegment, and therefore might not be truly\n" + ); + } else { + printf(" %ld encroached subsegments, and therefore might not be truly\n" + , m->badsubsegs.items); + } + printf(" Delaunay. If the Delaunay property is important to you,\n"); + printf(" try increasing the number of Steiner points (controlled by\n"); + printf(" the -S switch) slightly and try again.\n\n"); + } +} + +#endif /* not CDT_ONLY */ + +/** **/ +/** **/ +/********* Mesh quality maintenance ends here *********/ + +/*****************************************************************************/ +/* */ +/* highorder() Create extra nodes for quadratic subparametric elements. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void highorder(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void highorder(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop, trisym; + struct osub checkmark; + vertex newvertex; + vertex torg, tdest; + int i; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + + if (!b->quiet) { + printf("Adding vertices for second-order triangles.\n"); + } + /* The following line ensures that dead items in the pool of nodes */ + /* cannot be allocated for the extra nodes associated with high */ + /* order elements. This ensures that the primary nodes (at the */ + /* corners of elements) will occur earlier in the output files, and */ + /* have lower indices, than the extra nodes. */ + m->vertices.deaditemstack = (VOID *) NULL; + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + /* To loop over the set of edges, loop over all triangles, and look at */ + /* the three edges of each triangle. If there isn't another triangle */ + /* adjacent to the edge, operate on the edge. If there is another */ + /* adjacent triangle, operate on the edge only if the current triangle */ + /* has a smaller pointer than its neighbor. This way, each edge is */ + /* considered only once. */ + while (triangleloop.tri != (triangle *) NULL) { + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + sym(triangleloop, trisym); + if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { + org(triangleloop, torg); + dest(triangleloop, tdest); + /* Create a new node in the middle of the edge. Interpolate */ + /* its attributes. */ + newvertex = (vertex) poolalloc(&m->vertices); + for (i = 0; i < 2 + m->nextras; i++) { + newvertex[i] = 0.5 * (torg[i] + tdest[i]); + } + /* Set the new node's marker to zero or one, depending on */ + /* whether it lies on a boundary. */ + setvertexmark(newvertex, trisym.tri == m->dummytri); + setvertextype(newvertex, + trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX); + if (b->usesegments) { + tspivot(triangleloop, checkmark); + /* If this edge is a segment, transfer the marker to the new node. */ + if (checkmark.ss != m->dummysub) { + setvertexmark(newvertex, mark(checkmark)); + setvertextype(newvertex, SEGMENTVERTEX); + } + } + if (b->verbose > 1) { + printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]); + } + /* Record the new node in the (one or two) adjacent elements. */ + triangleloop.tri[m->highorderindex + triangleloop.orient] = + (triangle) newvertex; + if (trisym.tri != m->dummytri) { + trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex; + } + } + } + triangleloop.tri = triangletraverse(m); + } +} + +/********* File I/O routines begin here *********/ +/** **/ +/** **/ + +/*****************************************************************************/ +/* */ +/* readline() Read a nonempty line from a file. */ +/* */ +/* A line is considered "nonempty" if it contains something that looks like */ +/* a number. Comments (prefaced by `#') are ignored. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +char *readline(char *string, FILE *infile, char *infilename) +#else /* not ANSI_DECLARATORS */ +char *readline(string, infile, infilename) +char *string; +FILE *infile; +char *infilename; +#endif /* not ANSI_DECLARATORS */ + +{ + char *result; + + /* Search for something that looks like a number. */ + do { + result = fgets(string, INPUTLINESIZE, infile); + if (result == (char *) NULL) { + printf(" Error: Unexpected end of file in %s.\n", infilename); + triexit(1); + } + /* Skip anything that doesn't look like a number, a comment, */ + /* or the end of a line. */ + while ((*result != '\0') && (*result != '#') + && (*result != '.') && (*result != '+') && (*result != '-') + && ((*result < '0') || (*result > '9'))) { + result++; + } + /* If it's a comment or end of line, read another line and try again. */ + } while ((*result == '#') || (*result == '\0')); + return result; +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* findfield() Find the next field of a string. */ +/* */ +/* Jumps past the current field by searching for whitespace, then jumps */ +/* past the whitespace to find the next field. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +char *findfield(char *string) +#else /* not ANSI_DECLARATORS */ +char *findfield(string) +char *string; +#endif /* not ANSI_DECLARATORS */ + +{ + char *result; + + result = string; + /* Skip the current field. Stop upon reaching whitespace. */ + while ((*result != '\0') && (*result != '#') + && (*result != ' ') && (*result != '\t')) { + result++; + } + /* Now skip the whitespace and anything else that doesn't look like a */ + /* number, a comment, or the end of a line. */ + while ((*result != '\0') && (*result != '#') + && (*result != '.') && (*result != '+') && (*result != '-') + && ((*result < '0') || (*result > '9'))) { + result++; + } + /* Check for a comment (prefixed with `#'). */ + if (*result == '#') { + *result = '\0'; + } + return result; +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* readnodes() Read the vertices from a file, which may be a .node or */ +/* .poly file. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void readnodes(struct mesh *m, struct behavior *b, char *nodefilename, + char *polyfilename, FILE **polyfile) +#else /* not ANSI_DECLARATORS */ +void readnodes(m, b, nodefilename, polyfilename, polyfile) +struct mesh *m; +struct behavior *b; +char *nodefilename; +char *polyfilename; +FILE **polyfile; +#endif /* not ANSI_DECLARATORS */ + +{ + FILE *infile; + vertex vertexloop; + char inputline[INPUTLINESIZE]; + char *stringptr; + char *infilename; + REAL x, y; + int firstnode; + int nodemarkers; + int currentmarker; + int i, j; + + if (b->poly) { + /* Read the vertices from a .poly file. */ + if (!b->quiet) { + printf("Opening %s.\n", polyfilename); + } + *polyfile = fopen(polyfilename, "r"); + if (*polyfile == (FILE *) NULL) { + printf(" Error: Cannot access file %s.\n", polyfilename); + triexit(1); + } + /* Read number of vertices, number of dimensions, number of vertex */ + /* attributes, and number of boundary markers. */ + stringptr = readline(inputline, *polyfile, polyfilename); + m->invertices = (int) strtol(stringptr, &stringptr, 0); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + m->mesh_dim = 2; + } else { + m->mesh_dim = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + m->nextras = 0; + } else { + m->nextras = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + nodemarkers = 0; + } else { + nodemarkers = (int) strtol(stringptr, &stringptr, 0); + } + if (m->invertices > 0) { + infile = *polyfile; + infilename = polyfilename; + m->readnodefile = 0; + } else { + /* If the .poly file claims there are zero vertices, that means that */ + /* the vertices should be read from a separate .node file. */ + m->readnodefile = 1; + infilename = nodefilename; + } + } else { + m->readnodefile = 1; + infilename = nodefilename; + *polyfile = (FILE *) NULL; + } + + if (m->readnodefile) { + /* Read the vertices from a .node file. */ + if (!b->quiet) { + printf("Opening %s.\n", nodefilename); + } + infile = fopen(nodefilename, "r"); + if (infile == (FILE *) NULL) { + printf(" Error: Cannot access file %s.\n", nodefilename); + triexit(1); + } + /* Read number of vertices, number of dimensions, number of vertex */ + /* attributes, and number of boundary markers. */ + stringptr = readline(inputline, infile, nodefilename); + m->invertices = (int) strtol(stringptr, &stringptr, 0); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + m->mesh_dim = 2; + } else { + m->mesh_dim = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + m->nextras = 0; + } else { + m->nextras = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + nodemarkers = 0; + } else { + nodemarkers = (int) strtol(stringptr, &stringptr, 0); + } + } + + if (m->invertices < 3) { + printf("Error: Input must have at least three input vertices.\n"); + triexit(1); + } + if (m->mesh_dim != 2) { + printf("Error: Triangle only works with two-dimensional meshes.\n"); + triexit(1); + } + if (m->nextras == 0) { + b->weighted = 0; + } + + initializevertexpool(m, b); + + /* Read the vertices. */ + for (i = 0; i < m->invertices; i++) { + vertexloop = (vertex) poolalloc(&m->vertices); + stringptr = readline(inputline, infile, infilename); + if (i == 0) { + firstnode = (int) strtol(stringptr, &stringptr, 0); + if ((firstnode == 0) || (firstnode == 1)) { + b->firstnumber = firstnode; + } + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i); + triexit(1); + } + x = (REAL) strtod(stringptr, &stringptr); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i); + triexit(1); + } + y = (REAL) strtod(stringptr, &stringptr); + vertexloop[0] = x; + vertexloop[1] = y; + /* Read the vertex attributes. */ + for (j = 2; j < 2 + m->nextras; j++) { + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + vertexloop[j] = 0.0; + } else { + vertexloop[j] = (REAL) strtod(stringptr, &stringptr); + } + } + if (nodemarkers) { + /* Read a vertex marker. */ + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + setvertexmark(vertexloop, 0); + } else { + currentmarker = (int) strtol(stringptr, &stringptr, 0); + setvertexmark(vertexloop, currentmarker); + } + } else { + /* If no markers are specified in the file, they default to zero. */ + setvertexmark(vertexloop, 0); + } + setvertextype(vertexloop, INPUTVERTEX); + /* Determine the smallest and largest x and y coordinates. */ + if (i == 0) { + m->xmin = m->xmax = x; + m->ymin = m->ymax = y; + } else { + m->xmin = (x < m->xmin) ? x : m->xmin; + m->xmax = (x > m->xmax) ? x : m->xmax; + m->ymin = (y < m->ymin) ? y : m->ymin; + m->ymax = (y > m->ymax) ? y : m->ymax; + } + } + if (m->readnodefile) { + fclose(infile); + } + + /* Nonexistent x value used as a flag to mark circle events in sweepline */ + /* Delaunay algorithm. */ + m->xminextreme = 10 * m->xmin - 9 * m->xmax; +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* transfernodes() Read the vertices from memory. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, + REAL *pointattriblist, int *pointmarkerlist, + int numberofpoints, int numberofpointattribs) +#else /* not ANSI_DECLARATORS */ +void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist, + numberofpoints, numberofpointattribs) +struct mesh *m; +struct behavior *b; +REAL *pointlist; +REAL *pointattriblist; +int *pointmarkerlist; +int numberofpoints; +int numberofpointattribs; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex vertexloop; + REAL x, y; + int i, j; + int coordindex; + int attribindex; + + m->invertices = numberofpoints; + m->mesh_dim = 2; + m->nextras = numberofpointattribs; + m->readnodefile = 0; + if (m->invertices < 3) { + printf("Error: Input must have at least three input vertices.\n"); + triexit(1); + } + if (m->nextras == 0) { + b->weighted = 0; + } + + initializevertexpool(m, b); + + /* Read the vertices. */ + coordindex = 0; + attribindex = 0; + for (i = 0; i < m->invertices; i++) { + vertexloop = (vertex) poolalloc(&m->vertices); + /* Read the vertex coordinates. */ + x = vertexloop[0] = pointlist[coordindex++]; + y = vertexloop[1] = pointlist[coordindex++]; + /* Read the vertex attributes. */ + for (j = 0; j < numberofpointattribs; j++) { + vertexloop[2 + j] = pointattriblist[attribindex++]; + } + if (pointmarkerlist != (int *) NULL) { + /* Read a vertex marker. */ + setvertexmark(vertexloop, pointmarkerlist[i]); + } else { + /* If no markers are specified, they default to zero. */ + setvertexmark(vertexloop, 0); + } + setvertextype(vertexloop, INPUTVERTEX); + /* Determine the smallest and largest x and y coordinates. */ + if (i == 0) { + m->xmin = m->xmax = x; + m->ymin = m->ymax = y; + } else { + m->xmin = (x < m->xmin) ? x : m->xmin; + m->xmax = (x > m->xmax) ? x : m->xmax; + m->ymin = (y < m->ymin) ? y : m->ymin; + m->ymax = (y > m->ymax) ? y : m->ymax; + } + } + + /* Nonexistent x value used as a flag to mark circle events in sweepline */ + /* Delaunay algorithm. */ + m->xminextreme = 10 * m->xmin - 9 * m->xmax; +} + +#endif /* TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* readholes() Read the holes, and possibly regional attributes and area */ +/* constraints, from a .poly file. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void readholes(struct mesh *m, struct behavior *b, + FILE *polyfile, char *polyfilename, REAL **hlist, int *holes, + REAL **rlist, int *regions) +#else /* not ANSI_DECLARATORS */ +void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions) +struct mesh *m; +struct behavior *b; +FILE *polyfile; +char *polyfilename; +REAL **hlist; +int *holes; +REAL **rlist; +int *regions; +#endif /* not ANSI_DECLARATORS */ + +{ + REAL *holelist; + REAL *regionlist; + char inputline[INPUTLINESIZE]; + char *stringptr; + int index; + int i; + + /* Read the holes. */ + stringptr = readline(inputline, polyfile, polyfilename); + *holes = (int) strtol(stringptr, &stringptr, 0); + if (*holes > 0) { + holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL)); + *hlist = holelist; + for (i = 0; i < 2 * *holes; i += 2) { + stringptr = readline(inputline, polyfile, polyfilename); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d has no x coordinate.\n", + b->firstnumber + (i >> 1)); + triexit(1); + } else { + holelist[i] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d has no y coordinate.\n", + b->firstnumber + (i >> 1)); + triexit(1); + } else { + holelist[i + 1] = (REAL) strtod(stringptr, &stringptr); + } + } + } else { + *hlist = (REAL *) NULL; + } + +#ifndef CDT_ONLY + if ((b->regionattrib || b->vararea) && !b->refine) { + /* Read the area constraints. */ + stringptr = readline(inputline, polyfile, polyfilename); + *regions = (int) strtol(stringptr, &stringptr, 0); + if (*regions > 0) { + regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL)); + *rlist = regionlist; + index = 0; + for (i = 0; i < *regions; i++) { + stringptr = readline(inputline, polyfile, polyfilename); + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no x coordinate.\n", + b->firstnumber + i); + triexit(1); + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no y coordinate.\n", + b->firstnumber + i); + triexit(1); + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + printf( + "Error: Region %d has no region attribute or area constraint.\n", + b->firstnumber + i); + triexit(1); + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findfield(stringptr); + if (*stringptr == '\0') { + regionlist[index] = regionlist[index - 1]; + } else { + regionlist[index] = (REAL) strtod(stringptr, &stringptr); + } + index++; + } + } + } else { + /* Set `*regions' to zero to avoid an accidental free() later. */ + *regions = 0; + *rlist = (REAL *) NULL; + } +#endif /* not CDT_ONLY */ + + fclose(polyfile); +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* finishfile() Write the command line to the output file so the user */ +/* can remember how the file was generated. Close the file. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void finishfile(FILE *outfile, int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void finishfile(outfile, argc, argv) +FILE *outfile; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +{ + int i; + + fprintf(outfile, "# Generated by"); + for (i = 0; i < argc; i++) { + fprintf(outfile, " "); + fputs(argv[i], outfile); + } + fprintf(outfile, "\n"); + fclose(outfile); +} + +#endif /* not TRILIBRARY */ + +/*****************************************************************************/ +/* */ +/* writenodes() Number the vertices and write them to a .node file. */ +/* */ +/* To save memory, the vertex numbers are written over the boundary markers */ +/* after the vertices are written to a file. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, + REAL **pointattriblist, int **pointmarkerlist) +#else /* not ANSI_DECLARATORS */ +void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist) +struct mesh *m; +struct behavior *b; +REAL **pointlist; +REAL **pointattriblist; +int **pointmarkerlist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writenodes(struct mesh *m, struct behavior *b, char *nodefilename, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writenodes(m, b, nodefilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *nodefilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + REAL *plist; + REAL *palist; + int *pmlist; + int coordindex; + int attribindex; +#else /* not TRILIBRARY */ + FILE *outfile; +#endif /* not TRILIBRARY */ + vertex vertexloop; + long outvertices; + int vertexnumber; + int i; + + if (b->jettison) { + outvertices = m->vertices.items - m->undeads; + } else { + outvertices = m->vertices.items; + } + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing vertices.\n"); + } + /* Allocate memory for output vertices if necessary. */ + if (*pointlist == (REAL *) NULL) { + *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL))); + } + /* Allocate memory for output vertex attributes if necessary. */ + if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) { + *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras * + sizeof(REAL))); + } + /* Allocate memory for output vertex markers if necessary. */ + if (!b->nobound && (*pointmarkerlist == (int *) NULL)) { + *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int))); + } + plist = *pointlist; + palist = *pointattriblist; + pmlist = *pointmarkerlist; + coordindex = 0; + attribindex = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", nodefilename); + } + outfile = fopen(nodefilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", nodefilename); + triexit(1); + } + /* Number of vertices, number of dimensions, number of vertex attributes, */ + /* and number of boundary markers (zero or one). */ + fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim, + m->nextras, 1 - b->nobound); +#endif /* not TRILIBRARY */ + + traversalinit(&m->vertices); + vertexnumber = b->firstnumber; + vertexloop = vertextraverse(m); + while (vertexloop != (vertex) NULL) { + if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { +#ifdef TRILIBRARY + /* X and y coordinates. */ + plist[coordindex++] = vertexloop[0]; + plist[coordindex++] = vertexloop[1]; + /* Vertex attributes. */ + for (i = 0; i < m->nextras; i++) { + palist[attribindex++] = vertexloop[2 + i]; + } + if (!b->nobound) { + /* Copy the boundary marker. */ + pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop); + } +#else /* not TRILIBRARY */ + /* Vertex number, x and y coordinates. */ + fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0], + vertexloop[1]); + for (i = 0; i < m->nextras; i++) { + /* Write an attribute. */ + fprintf(outfile, " %.17g", vertexloop[i + 2]); + } + if (b->nobound) { + fprintf(outfile, "\n"); + } else { + /* Write the boundary marker. */ + fprintf(outfile, " %d\n", vertexmark(vertexloop)); + } +#endif /* not TRILIBRARY */ + + setvertexmark(vertexloop, vertexnumber); + vertexnumber++; + } + vertexloop = vertextraverse(m); + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +/*****************************************************************************/ +/* */ +/* numbernodes() Number the vertices. */ +/* */ +/* Each vertex is assigned a marker equal to its number. */ +/* */ +/* Used when writenodes() is not called because no .node file is written. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void numbernodes(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void numbernodes(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + vertex vertexloop; + int vertexnumber; + + traversalinit(&m->vertices); + vertexnumber = b->firstnumber; + vertexloop = vertextraverse(m); + while (vertexloop != (vertex) NULL) { + setvertexmark(vertexloop, vertexnumber); + if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { + vertexnumber++; + } + vertexloop = vertextraverse(m); + } +} + +/*****************************************************************************/ +/* */ +/* writeelements() Write the triangles to an .ele file. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writeelements(struct mesh *m, struct behavior *b, + int **trianglelist, REAL **triangleattriblist) +#else /* not ANSI_DECLARATORS */ +void writeelements(m, b, trianglelist, triangleattriblist) +struct mesh *m; +struct behavior *b; +int **trianglelist; +REAL **triangleattriblist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writeelements(struct mesh *m, struct behavior *b, char *elefilename, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writeelements(m, b, elefilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *elefilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + int *tlist; + REAL *talist; + int vertexindex; + int attribindex; +#else /* not TRILIBRARY */ + FILE *outfile; +#endif /* not TRILIBRARY */ + struct otri triangleloop; + vertex p1, p2, p3; + vertex mid1, mid2, mid3; + long elementnumber; + int i; + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing triangles.\n"); + } + /* Allocate memory for output triangles if necessary. */ + if (*trianglelist == (int *) NULL) { + *trianglelist = (int *) trimalloc((int) (m->triangles.items * + ((b->order + 1) * (b->order + 2) / + 2) * sizeof(int))); + } + /* Allocate memory for output triangle attributes if necessary. */ + if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) { + *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items * + m->eextras * + sizeof(REAL))); + } + tlist = *trianglelist; + talist = *triangleattriblist; + vertexindex = 0; + attribindex = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", elefilename); + } + outfile = fopen(elefilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", elefilename); + triexit(1); + } + /* Number of triangles, vertices per triangle, attributes per triangle. */ + fprintf(outfile, "%ld %d %d\n", m->triangles.items, + (b->order + 1) * (b->order + 2) / 2, m->eextras); +#endif /* not TRILIBRARY */ + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + triangleloop.orient = 0; + elementnumber = b->firstnumber; + while (triangleloop.tri != (triangle *) NULL) { + org(triangleloop, p1); + dest(triangleloop, p2); + apex(triangleloop, p3); + if (b->order == 1) { +#ifdef TRILIBRARY + tlist[vertexindex++] = vertexmark(p1); + tlist[vertexindex++] = vertexmark(p2); + tlist[vertexindex++] = vertexmark(p3); +#else /* not TRILIBRARY */ + /* Triangle number, indices for three vertices. */ + fprintf(outfile, "%4ld %4d %4d %4d", elementnumber, + vertexmark(p1), vertexmark(p2), vertexmark(p3)); +#endif /* not TRILIBRARY */ + } else { + mid1 = (vertex) triangleloop.tri[m->highorderindex + 1]; + mid2 = (vertex) triangleloop.tri[m->highorderindex + 2]; + mid3 = (vertex) triangleloop.tri[m->highorderindex]; +#ifdef TRILIBRARY + tlist[vertexindex++] = vertexmark(p1); + tlist[vertexindex++] = vertexmark(p2); + tlist[vertexindex++] = vertexmark(p3); + tlist[vertexindex++] = vertexmark(mid1); + tlist[vertexindex++] = vertexmark(mid2); + tlist[vertexindex++] = vertexmark(mid3); +#else /* not TRILIBRARY */ + /* Triangle number, indices for six vertices. */ + fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber, + vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1), + vertexmark(mid2), vertexmark(mid3)); +#endif /* not TRILIBRARY */ + } + +#ifdef TRILIBRARY + for (i = 0; i < m->eextras; i++) { + talist[attribindex++] = elemattribute(triangleloop, i); + } +#else /* not TRILIBRARY */ + for (i = 0; i < m->eextras; i++) { + fprintf(outfile, " %.17g", elemattribute(triangleloop, i)); + } + fprintf(outfile, "\n"); +#endif /* not TRILIBRARY */ + + triangleloop.tri = triangletraverse(m); + elementnumber++; + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +/*****************************************************************************/ +/* */ +/* writepoly() Write the segments and holes to a .poly file. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writepoly(struct mesh *m, struct behavior *b, + int **segmentlist, int **segmentmarkerlist) +#else /* not ANSI_DECLARATORS */ +void writepoly(m, b, segmentlist, segmentmarkerlist) +struct mesh *m; +struct behavior *b; +int **segmentlist; +int **segmentmarkerlist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writepoly(struct mesh *m, struct behavior *b, char *polyfilename, + REAL *holelist, int holes, REAL *regionlist, int regions, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions, + argc, argv) +struct mesh *m; +struct behavior *b; +char *polyfilename; +REAL *holelist; +int holes; +REAL *regionlist; +int regions; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + int *slist; + int *smlist; + int index; +#else /* not TRILIBRARY */ + FILE *outfile; + long holenumber, regionnumber; +#endif /* not TRILIBRARY */ + struct osub subsegloop; + vertex endpoint1, endpoint2; + long subsegnumber; + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing segments.\n"); + } + /* Allocate memory for output segments if necessary. */ + if (*segmentlist == (int *) NULL) { + *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 * + sizeof(int))); + } + /* Allocate memory for output segment markers if necessary. */ + if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) { + *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items * + sizeof(int))); + } + slist = *segmentlist; + smlist = *segmentmarkerlist; + index = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", polyfilename); + } + outfile = fopen(polyfilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", polyfilename); + triexit(1); + } + /* The zero indicates that the vertices are in a separate .node file. */ + /* Followed by number of dimensions, number of vertex attributes, */ + /* and number of boundary markers (zero or one). */ + fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras, + 1 - b->nobound); + /* Number of segments, number of boundary markers (zero or one). */ + fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound); +#endif /* not TRILIBRARY */ + + traversalinit(&m->subsegs); + subsegloop.ss = subsegtraverse(m); + subsegloop.ssorient = 0; + subsegnumber = b->firstnumber; + while (subsegloop.ss != (subseg *) NULL) { + sorg(subsegloop, endpoint1); + sdest(subsegloop, endpoint2); +#ifdef TRILIBRARY + /* Copy indices of the segment's two endpoints. */ + slist[index++] = vertexmark(endpoint1); + slist[index++] = vertexmark(endpoint2); + if (!b->nobound) { + /* Copy the boundary marker. */ + smlist[subsegnumber - b->firstnumber] = mark(subsegloop); + } +#else /* not TRILIBRARY */ + /* Segment number, indices of its two endpoints, and possibly a marker. */ + if (b->nobound) { + fprintf(outfile, "%4ld %4d %4d\n", subsegnumber, + vertexmark(endpoint1), vertexmark(endpoint2)); + } else { + fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber, + vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop)); + } +#endif /* not TRILIBRARY */ + + subsegloop.ss = subsegtraverse(m); + subsegnumber++; + } + +#ifndef TRILIBRARY +#ifndef CDT_ONLY + fprintf(outfile, "%d\n", holes); + if (holes > 0) { + for (holenumber = 0; holenumber < holes; holenumber++) { + /* Hole number, x and y coordinates. */ + fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber, + holelist[2 * holenumber], holelist[2 * holenumber + 1]); + } + } + if (regions > 0) { + fprintf(outfile, "%d\n", regions); + for (regionnumber = 0; regionnumber < regions; regionnumber++) { + /* Region number, x and y coordinates, attribute, maximum area. */ + fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n", + b->firstnumber + regionnumber, + regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1], + regionlist[4 * regionnumber + 2], + regionlist[4 * regionnumber + 3]); + } + } +#endif /* not CDT_ONLY */ + + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +/*****************************************************************************/ +/* */ +/* writeedges() Write the edges to an .edge file. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writeedges(struct mesh *m, struct behavior *b, + int **edgelist, int **edgemarkerlist) +#else /* not ANSI_DECLARATORS */ +void writeedges(m, b, edgelist, edgemarkerlist) +struct mesh *m; +struct behavior *b; +int **edgelist; +int **edgemarkerlist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writeedges(struct mesh *m, struct behavior *b, char *edgefilename, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writeedges(m, b, edgefilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *edgefilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + int *elist; + int *emlist; + int index; +#else /* not TRILIBRARY */ + FILE *outfile; +#endif /* not TRILIBRARY */ + struct otri triangleloop, trisym; + struct osub checkmark; + vertex p1, p2; + long edgenumber; + triangle ptr; /* Temporary variable used by sym(). */ + subseg sptr; /* Temporary variable used by tspivot(). */ + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing edges.\n"); + } + /* Allocate memory for edges if necessary. */ + if (*edgelist == (int *) NULL) { + *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int))); + } + /* Allocate memory for edge markers if necessary. */ + if (!b->nobound && (*edgemarkerlist == (int *) NULL)) { + *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int))); + } + elist = *edgelist; + emlist = *edgemarkerlist; + index = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", edgefilename); + } + outfile = fopen(edgefilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", edgefilename); + triexit(1); + } + /* Number of edges, number of boundary markers (zero or one). */ + fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound); +#endif /* not TRILIBRARY */ + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + edgenumber = b->firstnumber; + /* To loop over the set of edges, loop over all triangles, and look at */ + /* the three edges of each triangle. If there isn't another triangle */ + /* adjacent to the edge, operate on the edge. If there is another */ + /* adjacent triangle, operate on the edge only if the current triangle */ + /* has a smaller pointer than its neighbor. This way, each edge is */ + /* considered only once. */ + while (triangleloop.tri != (triangle *) NULL) { + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + sym(triangleloop, trisym); + if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { + org(triangleloop, p1); + dest(triangleloop, p2); +#ifdef TRILIBRARY + elist[index++] = vertexmark(p1); + elist[index++] = vertexmark(p2); +#endif /* TRILIBRARY */ + if (b->nobound) { +#ifndef TRILIBRARY + /* Edge number, indices of two endpoints. */ + fprintf(outfile, "%4ld %d %d\n", edgenumber, + vertexmark(p1), vertexmark(p2)); +#endif /* not TRILIBRARY */ + } else { + /* Edge number, indices of two endpoints, and a boundary marker. */ + /* If there's no subsegment, the boundary marker is zero. */ + if (b->usesegments) { + tspivot(triangleloop, checkmark); + if (checkmark.ss == m->dummysub) { +#ifdef TRILIBRARY + emlist[edgenumber - b->firstnumber] = 0; +#else /* not TRILIBRARY */ + fprintf(outfile, "%4ld %d %d %d\n", edgenumber, + vertexmark(p1), vertexmark(p2), 0); +#endif /* not TRILIBRARY */ + } else { +#ifdef TRILIBRARY + emlist[edgenumber - b->firstnumber] = mark(checkmark); +#else /* not TRILIBRARY */ + fprintf(outfile, "%4ld %d %d %d\n", edgenumber, + vertexmark(p1), vertexmark(p2), mark(checkmark)); +#endif /* not TRILIBRARY */ + } + } else { +#ifdef TRILIBRARY + emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri; +#else /* not TRILIBRARY */ + fprintf(outfile, "%4ld %d %d %d\n", edgenumber, + vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri); +#endif /* not TRILIBRARY */ + } + } + edgenumber++; + } + } + triangleloop.tri = triangletraverse(m); + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +/*****************************************************************************/ +/* */ +/* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */ +/* file. */ +/* */ +/* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */ +/* Hence, the Voronoi vertices are listed by traversing the Delaunay */ +/* triangles, and the Voronoi edges are listed by traversing the Delaunay */ +/* edges. */ +/* */ +/* WARNING: In order to assign numbers to the Voronoi vertices, this */ +/* procedure messes up the subsegments or the extra nodes of every */ +/* element. Hence, you should call this procedure last. */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, + REAL **vpointattriblist, int **vpointmarkerlist, + int **vedgelist, int **vedgemarkerlist, REAL **vnormlist) +#else /* not ANSI_DECLARATORS */ +void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist, + vedgelist, vedgemarkerlist, vnormlist) +struct mesh *m; +struct behavior *b; +REAL **vpointlist; +REAL **vpointattriblist; +int **vpointmarkerlist; +int **vedgelist; +int **vedgemarkerlist; +REAL **vnormlist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename, + char *vedgefilename, int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *vnodefilename; +char *vedgefilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + REAL *plist; + REAL *palist; + int *elist; + REAL *normlist; + int coordindex; + int attribindex; +#else /* not TRILIBRARY */ + FILE *outfile; +#endif /* not TRILIBRARY */ + struct otri triangleloop, trisym; + vertex torg, tdest, tapex; + REAL circumcenter[2]; + REAL xi, eta; + long vnodenumber, vedgenumber; + int p1, p2; + int i; + triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing Voronoi vertices.\n"); + } + /* Allocate memory for Voronoi vertices if necessary. */ + if (*vpointlist == (REAL *) NULL) { + *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 * + sizeof(REAL))); + } + /* Allocate memory for Voronoi vertex attributes if necessary. */ + if (*vpointattriblist == (REAL *) NULL) { + *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items * + m->nextras * sizeof(REAL))); + } + *vpointmarkerlist = (int *) NULL; + plist = *vpointlist; + palist = *vpointattriblist; + coordindex = 0; + attribindex = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", vnodefilename); + } + outfile = fopen(vnodefilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", vnodefilename); + triexit(1); + } + /* Number of triangles, two dimensions, number of vertex attributes, */ + /* no markers. */ + fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0); +#endif /* not TRILIBRARY */ + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + triangleloop.orient = 0; + vnodenumber = b->firstnumber; + while (triangleloop.tri != (triangle *) NULL) { + org(triangleloop, torg); + dest(triangleloop, tdest); + apex(triangleloop, tapex); + findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0); +#ifdef TRILIBRARY + /* X and y coordinates. */ + plist[coordindex++] = circumcenter[0]; + plist[coordindex++] = circumcenter[1]; + for (i = 2; i < 2 + m->nextras; i++) { + /* Interpolate the vertex attributes at the circumcenter. */ + palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i]) + + eta * (tapex[i] - torg[i]); + } +#else /* not TRILIBRARY */ + /* Voronoi vertex number, x and y coordinates. */ + fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0], + circumcenter[1]); + for (i = 2; i < 2 + m->nextras; i++) { + /* Interpolate the vertex attributes at the circumcenter. */ + fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i]) + + eta * (tapex[i] - torg[i])); + } + fprintf(outfile, "\n"); +#endif /* not TRILIBRARY */ + + * (int *) (triangleloop.tri + 6) = (int) vnodenumber; + triangleloop.tri = triangletraverse(m); + vnodenumber++; + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing Voronoi edges.\n"); + } + /* Allocate memory for output Voronoi edges if necessary. */ + if (*vedgelist == (int *) NULL) { + *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int))); + } + *vedgemarkerlist = (int *) NULL; + /* Allocate memory for output Voronoi norms if necessary. */ + if (*vnormlist == (REAL *) NULL) { + *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL))); + } + elist = *vedgelist; + normlist = *vnormlist; + coordindex = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", vedgefilename); + } + outfile = fopen(vedgefilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", vedgefilename); + triexit(1); + } + /* Number of edges, zero boundary markers. */ + fprintf(outfile, "%ld %d\n", m->edges, 0); +#endif /* not TRILIBRARY */ + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + vedgenumber = b->firstnumber; + /* To loop over the set of edges, loop over all triangles, and look at */ + /* the three edges of each triangle. If there isn't another triangle */ + /* adjacent to the edge, operate on the edge. If there is another */ + /* adjacent triangle, operate on the edge only if the current triangle */ + /* has a smaller pointer than its neighbor. This way, each edge is */ + /* considered only once. */ + while (triangleloop.tri != (triangle *) NULL) { + for (triangleloop.orient = 0; triangleloop.orient < 3; + triangleloop.orient++) { + sym(triangleloop, trisym); + if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { + /* Find the number of this triangle (and Voronoi vertex). */ + p1 = * (int *) (triangleloop.tri + 6); + if (trisym.tri == m->dummytri) { + org(triangleloop, torg); + dest(triangleloop, tdest); +#ifdef TRILIBRARY + /* Copy an infinite ray. Index of one endpoint, and -1. */ + elist[coordindex] = p1; + normlist[coordindex++] = tdest[1] - torg[1]; + elist[coordindex] = -1; + normlist[coordindex++] = torg[0] - tdest[0]; +#else /* not TRILIBRARY */ + /* Write an infinite ray. Edge number, index of one endpoint, -1, */ + /* and x and y coordinates of a vector representing the */ + /* direction of the ray. */ + fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber, + p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]); +#endif /* not TRILIBRARY */ + } else { + /* Find the number of the adjacent triangle (and Voronoi vertex). */ + p2 = * (int *) (trisym.tri + 6); + /* Finite edge. Write indices of two endpoints. */ +#ifdef TRILIBRARY + elist[coordindex] = p1; + normlist[coordindex++] = 0.0; + elist[coordindex] = p2; + normlist[coordindex++] = 0.0; +#else /* not TRILIBRARY */ + fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2); +#endif /* not TRILIBRARY */ + } + vedgenumber++; + } + } + triangleloop.tri = triangletraverse(m); + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist) +#else /* not ANSI_DECLARATORS */ +void writeneighbors(m, b, neighborlist) +struct mesh *m; +struct behavior *b; +int **neighborlist; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writeneighbors(m, b, neighborfilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *neighborfilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ +#ifdef TRILIBRARY + int *nlist; + int index; +#else /* not TRILIBRARY */ + FILE *outfile; +#endif /* not TRILIBRARY */ + struct otri triangleloop, trisym; + long elementnumber; + int neighbor1, neighbor2, neighbor3; + triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef TRILIBRARY + if (!b->quiet) { + printf("Writing neighbors.\n"); + } + /* Allocate memory for neighbors if necessary. */ + if (*neighborlist == (int *) NULL) { + *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 * + sizeof(int))); + } + nlist = *neighborlist; + index = 0; +#else /* not TRILIBRARY */ + if (!b->quiet) { + printf("Writing %s.\n", neighborfilename); + } + outfile = fopen(neighborfilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", neighborfilename); + triexit(1); + } + /* Number of triangles, three neighbors per triangle. */ + fprintf(outfile, "%ld %d\n", m->triangles.items, 3); +#endif /* not TRILIBRARY */ + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + triangleloop.orient = 0; + elementnumber = b->firstnumber; + while (triangleloop.tri != (triangle *) NULL) { + * (int *) (triangleloop.tri + 6) = (int) elementnumber; + triangleloop.tri = triangletraverse(m); + elementnumber++; + } + * (int *) (m->dummytri + 6) = -1; + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + elementnumber = b->firstnumber; + while (triangleloop.tri != (triangle *) NULL) { + triangleloop.orient = 1; + sym(triangleloop, trisym); + neighbor1 = * (int *) (trisym.tri + 6); + triangleloop.orient = 2; + sym(triangleloop, trisym); + neighbor2 = * (int *) (trisym.tri + 6); + triangleloop.orient = 0; + sym(triangleloop, trisym); + neighbor3 = * (int *) (trisym.tri + 6); +#ifdef TRILIBRARY + nlist[index++] = neighbor1; + nlist[index++] = neighbor2; + nlist[index++] = neighbor3; +#else /* not TRILIBRARY */ + /* Triangle number, neighboring triangle numbers. */ + fprintf(outfile, "%4ld %d %d %d\n", elementnumber, + neighbor1, neighbor2, neighbor3); +#endif /* not TRILIBRARY */ + + triangleloop.tri = triangletraverse(m); + elementnumber++; + } + +#ifndef TRILIBRARY + finishfile(outfile, argc, argv); +#endif /* not TRILIBRARY */ +} + +/*****************************************************************************/ +/* */ +/* writeoff() Write the triangulation to an .off file. */ +/* */ +/* OFF stands for the Object File Format, a format used by the Geometry */ +/* Center's Geomview package. */ +/* */ +/*****************************************************************************/ + +#ifndef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void writeoff(struct mesh *m, struct behavior *b, char *offfilename, + int argc, char **argv) +#else /* not ANSI_DECLARATORS */ +void writeoff(m, b, offfilename, argc, argv) +struct mesh *m; +struct behavior *b; +char *offfilename; +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +{ + FILE *outfile; + struct otri triangleloop; + vertex vertexloop; + vertex p1, p2, p3; + long outvertices; + + if (!b->quiet) { + printf("Writing %s.\n", offfilename); + } + + if (b->jettison) { + outvertices = m->vertices.items - m->undeads; + } else { + outvertices = m->vertices.items; + } + + outfile = fopen(offfilename, "w"); + if (outfile == (FILE *) NULL) { + printf(" Error: Cannot create file %s.\n", offfilename); + triexit(1); + } + /* Number of vertices, triangles, and edges. */ + fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items, + m->edges); + + /* Write the vertices. */ + traversalinit(&m->vertices); + vertexloop = vertextraverse(m); + while (vertexloop != (vertex) NULL) { + if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { + /* The "0.0" is here because the OFF format uses 3D coordinates. */ + fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1], + 0.0); + } + vertexloop = vertextraverse(m); + } + + /* Write the triangles. */ + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + triangleloop.orient = 0; + while (triangleloop.tri != (triangle *) NULL) { + org(triangleloop, p1); + dest(triangleloop, p2); + apex(triangleloop, p3); + /* The "3" means a three-vertex polygon. */ + fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber, + vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber); + triangleloop.tri = triangletraverse(m); + } + finishfile(outfile, argc, argv); +} + +#endif /* not TRILIBRARY */ + +/** **/ +/** **/ +/********* File I/O routines end here *********/ + +/*****************************************************************************/ +/* */ +/* quality_statistics() Print statistics about the quality of the mesh. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void quality_statistics(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void quality_statistics(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + struct otri triangleloop; + vertex p[3]; + REAL cossquaretable[8]; + REAL ratiotable[16]; + REAL dx[3], dy[3]; + REAL edgelength[3]; + REAL dotproduct; + REAL cossquare; + REAL triarea; + REAL shortest, longest; + REAL trilongest2; + REAL smallestarea, biggestarea; + REAL triminaltitude2; + REAL minaltitude; + REAL triaspect2; + REAL worstaspect; + REAL smallestangle, biggestangle; + REAL radconst, degconst; + int angletable[18]; + int aspecttable[16]; + int aspectindex; + int tendegree; + int acutebiggest; + int i, ii, j, k; + + printf("Mesh quality statistics:\n\n"); + radconst = PI / 18.0; + degconst = 180.0 / PI; + for (i = 0; i < 8; i++) { + cossquaretable[i] = cos(radconst * (REAL) (i + 1)); + cossquaretable[i] = cossquaretable[i] * cossquaretable[i]; + } + for (i = 0; i < 18; i++) { + angletable[i] = 0; + } + + ratiotable[0] = 1.5; ratiotable[1] = 2.0; + ratiotable[2] = 2.5; ratiotable[3] = 3.0; + ratiotable[4] = 4.0; ratiotable[5] = 6.0; + ratiotable[6] = 10.0; ratiotable[7] = 15.0; + ratiotable[8] = 25.0; ratiotable[9] = 50.0; + ratiotable[10] = 100.0; ratiotable[11] = 300.0; + ratiotable[12] = 1000.0; ratiotable[13] = 10000.0; + ratiotable[14] = 100000.0; ratiotable[15] = 0.0; + for (i = 0; i < 16; i++) { + aspecttable[i] = 0; + } + + worstaspect = 0.0; + minaltitude = m->xmax - m->xmin + m->ymax - m->ymin; + minaltitude = minaltitude * minaltitude; + shortest = minaltitude; + longest = 0.0; + smallestarea = minaltitude; + biggestarea = 0.0; + worstaspect = 0.0; + smallestangle = 0.0; + biggestangle = 2.0; + acutebiggest = 1; + + traversalinit(&m->triangles); + triangleloop.tri = triangletraverse(m); + triangleloop.orient = 0; + while (triangleloop.tri != (triangle *) NULL) { + org(triangleloop, p[0]); + dest(triangleloop, p[1]); + apex(triangleloop, p[2]); + trilongest2 = 0.0; + + for (i = 0; i < 3; i++) { + j = plus1mod3[i]; + k = minus1mod3[i]; + dx[i] = p[j][0] - p[k][0]; + dy[i] = p[j][1] - p[k][1]; + edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i]; + if (edgelength[i] > trilongest2) { + trilongest2 = edgelength[i]; + } + if (edgelength[i] > longest) { + longest = edgelength[i]; + } + if (edgelength[i] < shortest) { + shortest = edgelength[i]; + } + } + + triarea = counterclockwise(m, b, p[0], p[1], p[2]); + if (triarea < smallestarea) { + smallestarea = triarea; + } + if (triarea > biggestarea) { + biggestarea = triarea; + } + triminaltitude2 = triarea * triarea / trilongest2; + if (triminaltitude2 < minaltitude) { + minaltitude = triminaltitude2; + } + triaspect2 = trilongest2 / triminaltitude2; + if (triaspect2 > worstaspect) { + worstaspect = triaspect2; + } + aspectindex = 0; + while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex]) + && (aspectindex < 15)) { + aspectindex++; + } + aspecttable[aspectindex]++; + + for (i = 0; i < 3; i++) { + j = plus1mod3[i]; + k = minus1mod3[i]; + dotproduct = dx[j] * dx[k] + dy[j] * dy[k]; + cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]); + tendegree = 8; + for (ii = 7; ii >= 0; ii--) { + if (cossquare > cossquaretable[ii]) { + tendegree = ii; + } + } + if (dotproduct <= 0.0) { + angletable[tendegree]++; + if (cossquare > smallestangle) { + smallestangle = cossquare; + } + if (acutebiggest && (cossquare < biggestangle)) { + biggestangle = cossquare; + } + } else { + angletable[17 - tendegree]++; + if (acutebiggest || (cossquare > biggestangle)) { + biggestangle = cossquare; + acutebiggest = 0; + } + } + } + triangleloop.tri = triangletraverse(m); + } + + shortest = sqrt(shortest); + longest = sqrt(longest); + minaltitude = sqrt(minaltitude); + worstaspect = sqrt(worstaspect); + smallestarea *= 0.5; + biggestarea *= 0.5; + if (smallestangle >= 1.0) { + smallestangle = 0.0; + } else { + smallestangle = degconst * acos(sqrt(smallestangle)); + } + if (biggestangle >= 1.0) { + biggestangle = 180.0; + } else { + if (acutebiggest) { + biggestangle = degconst * acos(sqrt(biggestangle)); + } else { + biggestangle = 180.0 - degconst * acos(sqrt(biggestangle)); + } + } + + printf(" Smallest area: %16.5g | Largest area: %16.5g\n", + smallestarea, biggestarea); + printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n", + shortest, longest); + printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n", + minaltitude, worstaspect); + + printf(" Triangle aspect ratio histogram:\n"); + printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", + ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8], + aspecttable[8]); + for (i = 1; i < 7; i++) { + printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", + ratiotable[i - 1], ratiotable[i], aspecttable[i], + ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]); + } + printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n", + ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14], + aspecttable[15]); + printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n"); + + printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n", + smallestangle, biggestangle); + + printf(" Angle histogram:\n"); + for (i = 0; i < 9; i++) { + printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n", + i * 10, i * 10 + 10, angletable[i], + i * 10 + 90, i * 10 + 100, angletable[i + 9]); + } + printf("\n"); +} + +/*****************************************************************************/ +/* */ +/* statistics() Print all sorts of cool facts. */ +/* */ +/*****************************************************************************/ + +#ifdef ANSI_DECLARATORS +void statistics(struct mesh *m, struct behavior *b) +#else /* not ANSI_DECLARATORS */ +void statistics(m, b) +struct mesh *m; +struct behavior *b; +#endif /* not ANSI_DECLARATORS */ + +{ + printf("\nStatistics:\n\n"); + printf(" Input vertices: %d\n", m->invertices); + if (b->refine) { + printf(" Input triangles: %d\n", m->inelements); + } + if (b->poly) { + printf(" Input segments: %d\n", m->insegments); + if (!b->refine) { + printf(" Input holes: %d\n", m->holes); + } + } + + printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads); + printf(" Mesh triangles: %ld\n", m->triangles.items); + printf(" Mesh edges: %ld\n", m->edges); + printf(" Mesh exterior boundary edges: %ld\n", m->hullsize); + if (b->poly || b->refine) { + printf(" Mesh interior boundary edges: %ld\n", + m->subsegs.items - m->hullsize); + printf(" Mesh subsegments (constrained edges): %ld\n", + m->subsegs.items); + } + printf("\n"); + + if (b->verbose) { + quality_statistics(m, b); + printf("Memory allocation statistics:\n\n"); + printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems); + printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems); + if (m->subsegs.maxitems > 0) { + printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems); + } + if (m->viri.maxitems > 0) { + printf(" Maximum number of viri: %ld\n", m->viri.maxitems); + } + if (m->badsubsegs.maxitems > 0) { + printf(" Maximum number of encroached subsegments: %ld\n", + m->badsubsegs.maxitems); + } + if (m->badtriangles.maxitems > 0) { + printf(" Maximum number of bad triangles: %ld\n", + m->badtriangles.maxitems); + } + if (m->flipstackers.maxitems > 0) { + printf(" Maximum number of stacked triangle flips: %ld\n", + m->flipstackers.maxitems); + } + if (m->splaynodes.maxitems > 0) { + printf(" Maximum number of splay tree nodes: %ld\n", + m->splaynodes.maxitems); + } + printf(" Approximate heap memory use (bytes): %ld\n\n", + m->vertices.maxitems * m->vertices.itembytes + + m->triangles.maxitems * m->triangles.itembytes + + m->subsegs.maxitems * m->subsegs.itembytes + + m->viri.maxitems * m->viri.itembytes + + m->badsubsegs.maxitems * m->badsubsegs.itembytes + + m->badtriangles.maxitems * m->badtriangles.itembytes + + m->flipstackers.maxitems * m->flipstackers.itembytes + + m->splaynodes.maxitems * m->splaynodes.itembytes); + + printf("Algorithmic statistics:\n\n"); + if (!b->weighted) { + printf(" Number of incircle tests: %ld\n", m->incirclecount); + } else { + printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount); + } + printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount); + if (m->hyperbolacount > 0) { + printf(" Number of right-of-hyperbola tests: %ld\n", + m->hyperbolacount); + } + if (m->circletopcount > 0) { + printf(" Number of circle top computations: %ld\n", + m->circletopcount); + } + if (m->circumcentercount > 0) { + printf(" Number of triangle circumcenter computations: %ld\n", + m->circumcentercount); + } + printf("\n"); + } +} + +/*****************************************************************************/ +/* */ +/* main() or triangulate() Gosh, do everything. */ +/* */ +/* The sequence is roughly as follows. Many of these steps can be skipped, */ +/* depending on the command line switches. */ +/* */ +/* - Initialize constants and parse the command line. */ +/* - Read the vertices from a file and either */ +/* - triangulate them (no -r), or */ +/* - read an old mesh from files and reconstruct it (-r). */ +/* - Insert the PSLG segments (-p), and possibly segments on the convex */ +/* hull (-c). */ +/* - Read the holes (-p), regional attributes (-pA), and regional area */ +/* constraints (-pa). Carve the holes and concavities, and spread the */ +/* regional attributes and area constraints. */ +/* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */ +/* Also enforce the conforming Delaunay property (-q and -a). */ +/* - Compute the number of edges in the resulting mesh. */ +/* - Promote the mesh's linear triangles to higher order elements (-o). */ +/* - Write the output files and print the statistics. */ +/* - Check the consistency and Delaunay property of the mesh (-C). */ +/* */ +/*****************************************************************************/ + +#ifdef TRILIBRARY + +#ifdef ANSI_DECLARATORS +void triangulate(char *triswitches, struct triangulateio *in, + struct triangulateio *out, struct triangulateio *vorout) +#else /* not ANSI_DECLARATORS */ +void triangulate(triswitches, in, out, vorout) +char *triswitches; +struct triangulateio *in; +struct triangulateio *out; +struct triangulateio *vorout; +#endif /* not ANSI_DECLARATORS */ + +#else /* not TRILIBRARY */ + +#ifdef ANSI_DECLARATORS +int main(int argc, char **argv) +//int main() +#else /* not ANSI_DECLARATORS */ +int main(argc, argv) +int argc; +char **argv; +#endif /* not ANSI_DECLARATORS */ + +#endif /* not TRILIBRARY */ + +{ + struct mesh m; + struct behavior b; + REAL *holearray; /* Array of holes. */ + REAL *regionarray; /* Array of regional attributes and area constraints. */ +#ifndef TRILIBRARY + FILE *polyfile; +#endif /* not TRILIBRARY */ +#ifndef NO_TIMER + /* Variables for timing the performance of Triangle. The types are */ + /* defined in sys/time.h. */ + struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6; + struct timezone tz; +#endif /* not NO_TIMER */ + +#ifndef NO_TIMER + gettimeofday(&tv0, &tz); +#endif /* not NO_TIMER */ + + triangleinit(&m); +#ifdef TRILIBRARY + parsecommandline(1, &triswitches, &b); +#else /* not TRILIBRARY */ + parsecommandline(argc, argv, &b); +#endif /* not TRILIBRARY */ + m.steinerleft = b.steiner; + +#ifdef TRILIBRARY + transfernodes(&m, &b, in->pointlist, in->pointattributelist, + in->pointmarkerlist, in->numberofpoints, + in->numberofpointattributes); +#else /* not TRILIBRARY */ + readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile); +#endif /* not TRILIBRARY */ + +#ifndef NO_TIMER + if (!b.quiet) { + gettimeofday(&tv1, &tz); + } +#endif /* not NO_TIMER */ + +#ifdef CDT_ONLY + m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */ +#else /* not CDT_ONLY */ + if (b.refine) { + /* Read and reconstruct a mesh. */ +#ifdef TRILIBRARY + m.hullsize = reconstruct(&m, &b, in->trianglelist, + in->triangleattributelist, in->trianglearealist, + in->numberoftriangles, in->numberofcorners, + in->numberoftriangleattributes, + in->segmentlist, in->segmentmarkerlist, + in->numberofsegments); +#else /* not TRILIBRARY */ + m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename, + b.inpolyfilename, polyfile); +#endif /* not TRILIBRARY */ + } else { + m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */ + } +#endif /* not CDT_ONLY */ + +#ifndef NO_TIMER + if (!b.quiet) { + gettimeofday(&tv2, &tz); + if (b.refine) { + printf("Mesh reconstruction"); + } else { + printf("Delaunay"); + } + printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) + + (tv2.tv_usec - tv1.tv_usec) / 1000l); + } +#endif /* not NO_TIMER */ + + /* Ensure that no vertex can be mistaken for a triangular bounding */ + /* box vertex in insertvertex(). */ + m.infvertex1 = (vertex) NULL; + m.infvertex2 = (vertex) NULL; + m.infvertex3 = (vertex) NULL; + + if (b.usesegments) { + m.checksegments = 1; /* Segments will be introduced next. */ + if (!b.refine) { + /* Insert PSLG segments and/or convex hull segments. */ +#ifdef TRILIBRARY + formskeleton(&m, &b, in->segmentlist, + in->segmentmarkerlist, in->numberofsegments); +#else /* not TRILIBRARY */ + formskeleton(&m, &b, polyfile, b.inpolyfilename); +#endif /* not TRILIBRARY */ + } + } + +#ifndef NO_TIMER + if (!b.quiet) { + gettimeofday(&tv3, &tz); + if (b.usesegments && !b.refine) { + printf("Segment milliseconds: %ld\n", + 1000l * (tv3.tv_sec - tv2.tv_sec) + + (tv3.tv_usec - tv2.tv_usec) / 1000l); + } + } +#endif /* not NO_TIMER */ + + if (b.poly && (m.triangles.items > 0)) { +#ifdef TRILIBRARY + holearray = in->holelist; + m.holes = in->numberofholes; + regionarray = in->regionlist; + m.regions = in->numberofregions; +#else /* not TRILIBRARY */ + readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes, + ®ionarray, &m.regions); +#endif /* not TRILIBRARY */ + if (!b.refine) { + /* Carve out holes and concavities. */ + carveholes(&m, &b, holearray, m.holes, regionarray, m.regions); + } + } else { + /* Without a PSLG, there can be no holes or regional attributes */ + /* or area constraints. The following are set to zero to avoid */ + /* an accidental free() later. */ + m.holes = 0; + m.regions = 0; + } + +#ifndef NO_TIMER + if (!b.quiet) { + gettimeofday(&tv4, &tz); + if (b.poly && !b.refine) { + printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) + + (tv4.tv_usec - tv3.tv_usec) / 1000l); + } + } +#endif /* not NO_TIMER */ + +#ifndef CDT_ONLY + if (b.quality && (m.triangles.items > 0)) { + enforcequality(&m, &b); /* Enforce angle and area constraints. */ + } +#endif /* not CDT_ONLY */ + +#ifndef NO_TIMER + if (!b.quiet) { + gettimeofday(&tv5, &tz); +#ifndef CDT_ONLY + if (b.quality) { + printf("Quality milliseconds: %ld\n", + 1000l * (tv5.tv_sec - tv4.tv_sec) + + (tv5.tv_usec - tv4.tv_usec) / 1000l); + } +#endif /* not CDT_ONLY */ + } +#endif /* not NO_TIMER */ + + /* Calculate the number of edges. */ + m.edges = (3l * m.triangles.items + m.hullsize) / 2l; + + if (b.order > 1) { + highorder(&m, &b); /* Promote elements to higher polynomial order. */ + } + if (!b.quiet) { + printf("\n"); + } + +#ifdef TRILIBRARY + if (b.jettison) { + out->numberofpoints = m.vertices.items - m.undeads; + } else { + out->numberofpoints = m.vertices.items; + } + out->numberofpointattributes = m.nextras; + out->numberoftriangles = m.triangles.items; + out->numberofcorners = (b.order + 1) * (b.order + 2) / 2; + out->numberoftriangleattributes = m.eextras; + out->numberofedges = m.edges; + if (b.usesegments) { + out->numberofsegments = m.subsegs.items; + } else { + out->numberofsegments = m.hullsize; + } + if (vorout != (struct triangulateio *) NULL) { + vorout->numberofpoints = m.triangles.items; + vorout->numberofpointattributes = m.nextras; + vorout->numberofedges = m.edges; + } +#endif /* TRILIBRARY */ + /* If not using iteration numbers, don't write a .node file if one was */ + /* read, because the original one would be overwritten! */ + if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) { + if (!b.quiet) { +#ifdef TRILIBRARY + printf("NOT writing vertices.\n"); +#else /* not TRILIBRARY */ + printf("NOT writing a .node file.\n"); +#endif /* not TRILIBRARY */ + } + numbernodes(&m, &b); /* We must remember to number the vertices. */ + } else { + /* writenodes() numbers the vertices too. */ +#ifdef TRILIBRARY + writenodes(&m, &b, &out->pointlist, &out->pointattributelist, + &out->pointmarkerlist); +#else /* not TRILIBRARY */ + writenodes(&m, &b, b.outnodefilename, argc, argv); +#endif /* TRILIBRARY */ + } + if (b.noelewritten) { + if (!b.quiet) { +#ifdef TRILIBRARY + printf("NOT writing triangles.\n"); +#else /* not TRILIBRARY */ + printf("NOT writing an .ele file.\n"); +#endif /* not TRILIBRARY */ + } + } else { +#ifdef TRILIBRARY + writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist); +#else /* not TRILIBRARY */ + writeelements(&m, &b, b.outelefilename, argc, argv); +#endif /* not TRILIBRARY */ + } + /* The -c switch (convex switch) causes a PSLG to be written */ + /* even if none was read. */ + if (b.poly || b.convex) { + /* If not using iteration numbers, don't overwrite the .poly file. */ + if (b.nopolywritten || b.noiterationnum) { + if (!b.quiet) { +#ifdef TRILIBRARY + printf("NOT writing segments.\n"); +#else /* not TRILIBRARY */ + printf("NOT writing a .poly file.\n"); +#endif /* not TRILIBRARY */ + } + } else { +#ifdef TRILIBRARY + writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist); + out->numberofholes = m.holes; + out->numberofregions = m.regions; + if (b.poly) { + out->holelist = in->holelist; + out->regionlist = in->regionlist; + } else { + out->holelist = (REAL *) NULL; + out->regionlist = (REAL *) NULL; + } +#else /* not TRILIBRARY */ + writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray, + m.regions, argc, argv); +#endif /* not TRILIBRARY */ + } + } +#ifndef TRILIBRARY +#ifndef CDT_ONLY + if (m.regions > 0) { + trifree((VOID *) regionarray); + } +#endif /* not CDT_ONLY */ + if (m.holes > 0) { + trifree((VOID *) holearray); + } + if (b.geomview) { + writeoff(&m, &b, b.offfilename, argc, argv); + } +#endif /* not TRILIBRARY */ + if (b.edgesout) { +#ifdef TRILIBRARY + writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist); +#else /* not TRILIBRARY */ + writeedges(&m, &b, b.edgefilename, argc, argv); +#endif /* not TRILIBRARY */ + } + if (b.voronoi) { +#ifdef TRILIBRARY + writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist, + &vorout->pointmarkerlist, &vorout->edgelist, + &vorout->edgemarkerlist, &vorout->normlist); +#else /* not TRILIBRARY */ + writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv); +#endif /* not TRILIBRARY */ + } + if (b.neighbors) { +#ifdef TRILIBRARY + writeneighbors(&m, &b, &out->neighborlist); +#else /* not TRILIBRARY */ + writeneighbors(&m, &b, b.neighborfilename, argc, argv); +#endif /* not TRILIBRARY */ + } + + if (!b.quiet) { +#ifndef NO_TIMER + gettimeofday(&tv6, &tz); + printf("\nOutput milliseconds: %ld\n", + 1000l * (tv6.tv_sec - tv5.tv_sec) + + (tv6.tv_usec - tv5.tv_usec) / 1000l); + printf("Total running milliseconds: %ld\n", + 1000l * (tv6.tv_sec - tv0.tv_sec) + + (tv6.tv_usec - tv0.tv_usec) / 1000l); +#endif /* not NO_TIMER */ + + statistics(&m, &b); + } + +#ifndef REDUCED + if (b.docheck) { + checkmesh(&m, &b); + checkdelaunay(&m, &b); + } +#endif /* not REDUCED */ + + triangledeinit(&m, &b); +#ifndef TRILIBRARY + return 0; +#endif /* not TRILIBRARY */ +} diff --git a/triangle/triangle.h b/triangle/triangle.h new file mode 100644 index 0000000..9df1f39 --- /dev/null +++ b/triangle/triangle.h @@ -0,0 +1,289 @@ +/*****************************************************************************/ +/* */ +/* (triangle.h) */ +/* */ +/* Include file for programs that call Triangle. */ +/* */ +/* Accompanies Triangle Version 1.6 */ +/* July 28, 2005 */ +/* */ +/* Copyright 1996, 2005 */ +/* Jonathan Richard Shewchuk */ +/* 2360 Woolsey #H */ +/* Berkeley, California 94705-1927 */ +/* jrs@cs.berkeley.edu */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* How to call Triangle from another program */ +/* */ +/* */ +/* If you haven't read Triangle's instructions (run "triangle -h" to read */ +/* them), you won't understand what follows. */ +/* */ +/* Triangle must be compiled into an object file (triangle.o) with the */ +/* TRILIBRARY symbol defined (generally by using the -DTRILIBRARY compiler */ +/* switch). The makefile included with Triangle will do this for you if */ +/* you run "make trilibrary". The resulting object file can be called via */ +/* the procedure triangulate(). */ +/* */ +/* If the size of the object file is important to you, you may wish to */ +/* generate a reduced version of triangle.o. The REDUCED symbol gets rid */ +/* of all features that are primarily of research interest. Specifically, */ +/* the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches. */ +/* The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond */ +/* constrained Delaunay triangulation. Specifically, the -DCDT_ONLY switch */ +/* eliminates Triangle's -r, -q, -a, -u, -D, -Y, -S, and -s switches. */ +/* */ +/* IMPORTANT: These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be */ +/* made in the makefile or in triangle.c itself. Putting these definitions */ +/* in this file (triangle.h) will not create the desired effect. */ +/* */ +/* */ +/* The calling convention for triangulate() follows. */ +/* */ +/* void triangulate(triswitches, in, out, vorout) */ +/* char *triswitches; */ +/* struct triangulateio *in; */ +/* struct triangulateio *out; */ +/* struct triangulateio *vorout; */ +/* */ +/* `triswitches' is a string containing the command line switches you wish */ +/* to invoke. No initial dash is required. Some suggestions: */ +/* */ +/* - You'll probably find it convenient to use the `z' switch so that */ +/* points (and other items) are numbered from zero. This simplifies */ +/* indexing, because the first item of any type always starts at index */ +/* [0] of the corresponding array, whether that item's number is zero or */ +/* one. */ +/* - You'll probably want to use the `Q' (quiet) switch in your final code, */ +/* but you can take advantage of Triangle's printed output (including the */ +/* `V' switch) while debugging. */ +/* - If you are not using the `q', `a', `u', `D', `j', or `s' switches, */ +/* then the output points will be identical to the input points, except */ +/* possibly for the boundary markers. If you don't need the boundary */ +/* markers, you should use the `N' (no nodes output) switch to save */ +/* memory. (If you do need boundary markers, but need to save memory, a */ +/* good nasty trick is to set out->pointlist equal to in->pointlist */ +/* before calling triangulate(), so that Triangle overwrites the input */ +/* points with identical copies.) */ +/* - The `I' (no iteration numbers) and `g' (.off file output) switches */ +/* have no effect when Triangle is compiled with TRILIBRARY defined. */ +/* */ +/* `in', `out', and `vorout' are descriptions of the input, the output, */ +/* and the Voronoi output. If the `v' (Voronoi output) switch is not used, */ +/* `vorout' may be NULL. `in' and `out' may never be NULL. */ +/* */ +/* Certain fields of the input and output structures must be initialized, */ +/* as described below. */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* The `triangulateio' structure. */ +/* */ +/* Used to pass data into and out of the triangulate() procedure. */ +/* */ +/* */ +/* Arrays are used to store points, triangles, markers, and so forth. In */ +/* all cases, the first item in any array is stored starting at index [0]. */ +/* However, that item is item number `1' unless the `z' switch is used, in */ +/* which case it is item number `0'. Hence, you may find it easier to */ +/* index points (and triangles in the neighbor list) if you use the `z' */ +/* switch. Unless, of course, you're calling Triangle from a Fortran */ +/* program. */ +/* */ +/* Description of fields (except the `numberof' fields, which are obvious): */ +/* */ +/* `pointlist': An array of point coordinates. The first point's x */ +/* coordinate is at index [0] and its y coordinate at index [1], followed */ +/* by the coordinates of the remaining points. Each point occupies two */ +/* REALs. */ +/* `pointattributelist': An array of point attributes. Each point's */ +/* attributes occupy `numberofpointattributes' REALs. */ +/* `pointmarkerlist': An array of point markers; one int per point. */ +/* */ +/* `trianglelist': An array of triangle corners. The first triangle's */ +/* first corner is at index [0], followed by its other two corners in */ +/* counterclockwise order, followed by any other nodes if the triangle */ +/* represents a nonlinear element. Each triangle occupies */ +/* `numberofcorners' ints. */ +/* `triangleattributelist': An array of triangle attributes. Each */ +/* triangle's attributes occupy `numberoftriangleattributes' REALs. */ +/* `trianglearealist': An array of triangle area constraints; one REAL per */ +/* triangle. Input only. */ +/* `neighborlist': An array of triangle neighbors; three ints per */ +/* triangle. Output only. */ +/* */ +/* `segmentlist': An array of segment endpoints. The first segment's */ +/* endpoints are at indices [0] and [1], followed by the remaining */ +/* segments. Two ints per segment. */ +/* `segmentmarkerlist': An array of segment markers; one int per segment. */ +/* */ +/* `holelist': An array of holes. The first hole's x and y coordinates */ +/* are at indices [0] and [1], followed by the remaining holes. Two */ +/* REALs per hole. Input only, although the pointer is copied to the */ +/* output structure for your convenience. */ +/* */ +/* `regionlist': An array of regional attributes and area constraints. */ +/* The first constraint's x and y coordinates are at indices [0] and [1], */ +/* followed by the regional attribute at index [2], followed by the */ +/* maximum area at index [3], followed by the remaining area constraints. */ +/* Four REALs per area constraint. Note that each regional attribute is */ +/* used only if you select the `A' switch, and each area constraint is */ +/* used only if you select the `a' switch (with no number following), but */ +/* omitting one of these switches does not change the memory layout. */ +/* Input only, although the pointer is copied to the output structure for */ +/* your convenience. */ +/* */ +/* `edgelist': An array of edge endpoints. The first edge's endpoints are */ +/* at indices [0] and [1], followed by the remaining edges. Two ints per */ +/* edge. Output only. */ +/* `edgemarkerlist': An array of edge markers; one int per edge. Output */ +/* only. */ +/* `normlist': An array of normal vectors, used for infinite rays in */ +/* Voronoi diagrams. The first normal vector's x and y magnitudes are */ +/* at indices [0] and [1], followed by the remaining vectors. For each */ +/* finite edge in a Voronoi diagram, the normal vector written is the */ +/* zero vector. Two REALs per edge. Output only. */ +/* */ +/* */ +/* Any input fields that Triangle will examine must be initialized. */ +/* Furthermore, for each output array that Triangle will write to, you */ +/* must either provide space by setting the appropriate pointer to point */ +/* to the space you want the data written to, or you must initialize the */ +/* pointer to NULL, which tells Triangle to allocate space for the results. */ +/* The latter option is preferable, because Triangle always knows exactly */ +/* how much space to allocate. The former option is provided mainly for */ +/* people who need to call Triangle from Fortran code, though it also makes */ +/* possible some nasty space-saving tricks, like writing the output to the */ +/* same arrays as the input. */ +/* */ +/* Triangle will not free() any input or output arrays, including those it */ +/* allocates itself; that's up to you. You should free arrays allocated by */ +/* Triangle by calling the trifree() procedure defined below. (By default, */ +/* trifree() just calls the standard free() library procedure, but */ +/* applications that call triangulate() may replace trimalloc() and */ +/* trifree() in triangle.c to use specialized memory allocators.) */ +/* */ +/* Here's a guide to help you decide which fields you must initialize */ +/* before you call triangulate(). */ +/* */ +/* `in': */ +/* */ +/* - `pointlist' must always point to a list of points; `numberofpoints' */ +/* and `numberofpointattributes' must be properly set. */ +/* `pointmarkerlist' must either be set to NULL (in which case all */ +/* markers default to zero), or must point to a list of markers. If */ +/* `numberofpointattributes' is not zero, `pointattributelist' must */ +/* point to a list of point attributes. */ +/* - If the `r' switch is used, `trianglelist' must point to a list of */ +/* triangles, and `numberoftriangles', `numberofcorners', and */ +/* `numberoftriangleattributes' must be properly set. If */ +/* `numberoftriangleattributes' is not zero, `triangleattributelist' */ +/* must point to a list of triangle attributes. If the `a' switch is */ +/* used (with no number following), `trianglearealist' must point to a */ +/* list of triangle area constraints. `neighborlist' may be ignored. */ +/* - If the `p' switch is used, `segmentlist' must point to a list of */ +/* segments, `numberofsegments' must be properly set, and */ +/* `segmentmarkerlist' must either be set to NULL (in which case all */ +/* markers default to zero), or must point to a list of markers. */ +/* - If the `p' switch is used without the `r' switch, then */ +/* `numberofholes' and `numberofregions' must be properly set. If */ +/* `numberofholes' is not zero, `holelist' must point to a list of */ +/* holes. If `numberofregions' is not zero, `regionlist' must point to */ +/* a list of region constraints. */ +/* - If the `p' switch is used, `holelist', `numberofholes', */ +/* `regionlist', and `numberofregions' is copied to `out'. (You can */ +/* nonetheless get away with not initializing them if the `r' switch is */ +/* used.) */ +/* - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */ +/* ignored. */ +/* */ +/* `out': */ +/* */ +/* - `pointlist' must be initialized (NULL or pointing to memory) unless */ +/* the `N' switch is used. `pointmarkerlist' must be initialized */ +/* unless the `N' or `B' switch is used. If `N' is not used and */ +/* `in->numberofpointattributes' is not zero, `pointattributelist' must */ +/* be initialized. */ +/* - `trianglelist' must be initialized unless the `E' switch is used. */ +/* `neighborlist' must be initialized if the `n' switch is used. If */ +/* the `E' switch is not used and (`in->numberofelementattributes' is */ +/* not zero or the `A' switch is used), `elementattributelist' must be */ +/* initialized. `trianglearealist' may be ignored. */ +/* - `segmentlist' must be initialized if the `p' or `c' switch is used, */ +/* and the `P' switch is not used. `segmentmarkerlist' must also be */ +/* initialized under these circumstances unless the `B' switch is used. */ +/* - `edgelist' must be initialized if the `e' switch is used. */ +/* `edgemarkerlist' must be initialized if the `e' switch is used and */ +/* the `B' switch is not. */ +/* - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/ +/* */ +/* `vorout' (only needed if `v' switch is used): */ +/* */ +/* - `pointlist' must be initialized. If `in->numberofpointattributes' */ +/* is not zero, `pointattributelist' must be initialized. */ +/* `pointmarkerlist' may be ignored. */ +/* - `edgelist' and `normlist' must both be initialized. */ +/* `edgemarkerlist' may be ignored. */ +/* - Everything else may be ignored. */ +/* */ +/* After a call to triangulate(), the valid fields of `out' and `vorout' */ +/* will depend, in an obvious way, on the choice of switches used. Note */ +/* that when the `p' switch is used, the pointers `holelist' and */ +/* `regionlist' are copied from `in' to `out', but no new space is */ +/* allocated; be careful that you don't free() the same array twice. On */ +/* the other hand, Triangle will never copy the `pointlist' pointer (or any */ +/* others); new space is allocated for `out->pointlist', or if the `N' */ +/* switch is used, `out->pointlist' remains uninitialized. */ +/* */ +/* All of the meaningful `numberof' fields will be properly set; for */ +/* instance, `numberofedges' will represent the number of edges in the */ +/* triangulation whether or not the edges were written. If segments are */ +/* not used, `numberofsegments' will indicate the number of boundary edges. */ +/* */ +/*****************************************************************************/ + +struct triangulateio { + REAL *pointlist; /* In / out */ + REAL *pointattributelist; /* In / out */ + int *pointmarkerlist; /* In / out */ + int numberofpoints; /* In / out */ + int numberofpointattributes; /* In / out */ + + int *trianglelist; /* In / out */ + REAL *triangleattributelist; /* In / out */ + REAL *trianglearealist; /* In only */ + int *neighborlist; /* Out only */ + int numberoftriangles; /* In / out */ + int numberofcorners; /* In / out */ + int numberoftriangleattributes; /* In / out */ + + int *segmentlist; /* In / out */ + int *segmentmarkerlist; /* In / out */ + int numberofsegments; /* In / out */ + + REAL *holelist; /* In / pointer to array copied out */ + int numberofholes; /* In / copied out */ + + REAL *regionlist; /* In / pointer to array copied out */ + int numberofregions; /* In / copied out */ + + int *edgelist; /* Out only */ + int *edgemarkerlist; /* Not used with Voronoi diagram; out only */ + REAL *normlist; /* Used only with Voronoi diagram; out only */ + int numberofedges; /* Out only */ +}; + +#ifdef ANSI_DECLARATORS +void triangulate(char *, struct triangulateio *, struct triangulateio *, + struct triangulateio *); +void trifree(VOID *memptr); +#else /* not ANSI_DECLARATORS */ +void triangulate(); +void trifree(); +#endif /* not ANSI_DECLARATORS */