// BemRawDoc.cpp : implementation of the CBemRawDoc class
//

#include "stdafx.h"
#include "math.h"
#include "BemRaw.h"

#include "geom.h"
#include "BemRawDoc.h"
#include "InpParts.h"
#include "InpTime.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBemRawDoc

IMPLEMENT_DYNCREATE(CBemRawDoc, CDocument)

BEGIN_MESSAGE_MAP(CBemRawDoc, CDocument)
	//{{AFX_MSG_MAP(CBemRawDoc)
	ON_COMMAND(ID_PART_SAVE, OnPartSave)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBemRawDoc construction/destruction

CBemRawDoc::CBemRawDoc()
{
	// TODO: add one-time construction code here

}

CBemRawDoc::~CBemRawDoc()
{
}

BOOL CBemRawDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	memset (&lfnt,0,sizeof(LOGFONT));
	lfnt.lfHeight=-12;
	strcpy (lfnt.lfFaceName,"Courier New");
	bounl=bounr=bount=bounb=720;
	m_size.cx=1000;m_size.cy=800;
	efpo=0.1f;

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CBemRawDoc serialization

void CBemRawDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << name << kx << ky << thick;
		ar.Write (&lfnt,sizeof(LOGFONT));
	}
	else
	{
		ar >> name >> kx >> ky >> thick;
		ar.Read (&lfnt,sizeof(LOGFONT));
	}
	Nodes.Serialize(ar);
	Elems.Serialize(ar);
	Wells.Serialize(ar);
	IntNods.Serialize(ar);
	TriElems.Serialize(ar);
}

/////////////////////////////////////////////////////////////////////////////
// CBemRawDoc diagnostics

#ifdef _DEBUG
void CBemRawDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CBemRawDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CBemRawDoc commands

void CBemRawDoc::DeleteContents() 
{
	int i=0;
	while (i<Nodes.GetSize())
	{
		delete Nodes.GetAt(i++);
	}	                     
	Nodes.RemoveAll();
	i=0;
	while (i<Elems.GetSize())
	{
		delete Elems.GetAt(i++);
	}	                     
	Elems.RemoveAll();
	i=0;
	while (i<Wells.GetSize())
	{
		delete Wells.GetAt(i++);
	}	                     
	Wells.RemoveAll();
	i=0;
	while (i<IntNods.GetSize())
	{
		delete IntNods.GetAt(i++);
	}	                     
	IntNods.RemoveAll();
	i=0;
	while (i<TriElems.GetSize())
	{
		delete TriElems.GetAt(i++);
	}	                     
	TriElems.RemoveAll();
	i=0;
	while (i<Area.GetSize())
	{
		delete Area.GetAt(i++);
	}	                     
	Area.RemoveAll();
	i=0;
	while (i<TimInts.GetSize())
	{
		delete TimInts.GetAt(i++);
	}	                     
	TimInts.RemoveAll();
	
	CDocument::DeleteContents();
}

BOOL CBemRawDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
	
    tx=kx*thick;ty=ky*thick;
	rprec=precip/(tx*3.1536e10);
	tt=sqrt(ty/tx);
	tp=1.0/(6.2831852*tt);
   	txy=sqrt(tx/ty);
	nel=Elems.GetSize();
	nwl=Wells.GetSize();
	efpo=at=0.1f;
	al=1.0f;tim=0.0f;
	
	return TRUE;
}

CNode* CBemRawDoc::GetNode(int i)
{
	return (CNode*)Nodes.GetAt(i);
}

CElement* CBemRawDoc::GetElement(int i)
{
	return (CElement*)Elems.GetAt(i);
}

CIntPoint* CBemRawDoc::GetIntPt(int i)
{
	return (CIntPoint*)IntNods.GetAt(i);
}

CIntElem* CBemRawDoc::GetIntElm(int i)
{
	return (CIntElem*)TriElems.GetAt(i);
}

CWell* CBemRawDoc::GetWell(int i)
{
	return (CWell*)Wells.GetAt(i);
}

CTimeInt* CBemRawDoc::GetTime(int i)
{
	return (CTimeInt*)TimInts.GetAt(i);
}

CNode* CBemRawDoc::GetArNode(int i)
{
	return (CNode*)Area.GetAt(i);
}

CNode* CBemRawDoc::AddCorner(float x, float y)
{
	CNode* nd=new CNode(x,y);
	Area.Add(nd);
	return nd;
}

CNode* CBemRawDoc::AddCorner(CPoint pt)
{
	CNode* nd=new CNode(pt,gcb);
	Area.Add(nd);
	return nd;
}

CTimeInt* CBemRawDoc::AddTime(float tim)
{
	CTimeInt* tm=new CTimeInt(tim);
	TimInts.Add(tm);
	return tm;
}

void CBemRawDoc::PlotElem(CDC *pDC, BOOL IsNum)
{
	int i;
	CPoint p[2];
	CPen *ppr;
	CFont hf,*hfp;
	hf.CreateFontIndirect(&lfnt);
	hfp=pDC->SelectObject(&hf);
	ppr=(CPen*)pDC->SelectStockObject(BLACK_PEN);
	for (i=0;i<Elems.GetSize();i++)
	{
		CElement* el=GetElement(i);
		CNode* n1=GetNode(el->nod1);CNode* n2=GetNode(el->nod2);
		n1->TranCoord(gcb);n2->TranCoord(gcb);
		p[0]=n1->Coord();p[1]=n2->Coord();
		pDC->Polygon(p,2);
		if (IsNum)
		{
			int ix,iy;
			ix=(p[0].x+p[1].x)/2;iy=(p[0].y+p[1].y)/2;
			CString msg;
			msg.Format("E%d",i+1);
			UINT tap=pDC->SetTextAlign(TA_CENTER | TA_BOTTOM);
			pDC->TextOut (ix,iy,msg);
			pDC->SetTextAlign(tap);
		}
		pDC->SelectStockObject(BLACK_PEN);
	}
	pDC->SelectObject(hfp);
	pDC->SelectObject(ppr);
	hf.DeleteObject();
}

void CBemRawDoc::PlotWells(CDC *pDC, int sz)
{
	int i;
	CFont hf,*hfp;
	hf.CreateFontIndirect(&lfnt);
	hfp=pDC->SelectObject(&hf);
	for (i=0;i<Wells.GetSize();i++)
	{
		CWell* nd=GetWell(i);
		nd->Plot (pDC,gcb,sz);
	}
	pDC->SelectObject(hfp);
	hf.DeleteObject();
}

void CBemRawDoc::PlotNod (CDC* pDC,int sz,BOOL IsNum)
{
	int i,n;
	CFont hf,*hfp;
	hf.CreateFontIndirect(&lfnt);
	hfp=pDC->SelectObject(&hf);
	for (i=0;i<Nodes.GetSize();i++)
	{
		CNode* nd=GetNode(i);
		if (IsNum) n=i+1;
		else n=-1;
		nd->PlotNode (pDC,n,sz,gcb);
	}
	pDC->SelectObject(hfp);
	hf.DeleteObject();
}

void CBemRawDoc::PlotIntPt (CDC* pDC,int sz,BOOL IsNum)
{
	int i,n;
	CFont hf,*hfp;
	hf.CreateFontIndirect(&lfnt);
	hfp=pDC->SelectObject(&hf);
	for (i=0;i<IntNods.GetSize();i++)
	{
		CIntPoint* nd=GetIntPt(i);
		if (IsNum) n=i+1;
		else n=-1;
		nd->PlotPt (pDC,n,sz,gcb);
	}
	pDC->SelectObject(hfp);
	hf.DeleteObject();
}

CSize CBemRawDoc::GetDocSize()
{
	return m_size;
}

void CBemRawDoc::ScaleNodes(CRect rc)
{
	int i;
	float xmin,xmax,ymin,ymax,dx,dxi,dy,dyi,dp1,dp2;
	if (Nodes.GetSize()==0) return;
	CNode* nd=GetNode(0);
	xmin=xmax=nd->xb;ymin=ymax=nd->yb;
	for (i=0;i<Nodes.GetSize();i++)
	{
		nd=GetNode(i);
		if (nd->xb>xmax) xmax=nd->xb;
		if (nd->xb<xmin) xmin=nd->xb;
		if (nd->yb>ymax) ymax=nd->yb;
		if (nd->yb<ymin) ymin=nd->yb;
	}
	dxi=rc.Width()-100;dyi=rc.Height()-100;
	dx=xmax-xmin;dy=ymax-ymin;
	gcb[0]=rc.left+50;gcb[3]=rc.top+50;
	gcb[2]=xmin;gcb[5]=ymax;
	if (fabs(dx)<1e-5 || fabs(dy)<1e-5)
	{
		gcb[1]=100.0f;gcb[4]=-100.0f;
	}
	else
	{
		dp1=fabs(dxi/dx);dp2=fabs(dyi/dy);
		if (dp1<dp2) {gcb[1]=dp1;gcb[4]=-dp1;}
		else {gcb[1]=dp2;gcb[4]=-dp2;}
	}
	m_size.cx=rc.right;m_size.cy=rc.bottom;
}

void CBemRawDoc::PlotArea(CDC &dc)
{
	int i,nac;
	CPoint* ptar;
	nac=Area.GetSize();
	ptar=new CPoint[nac];
	for (i=0;i<nac;i++)
	{
		CNode* nd=GetArNode(i);
		nd->PlotNode(&dc,-1,3,gcb);
		ptar[i]=nd->Coord();
	}
	dc.Polygon(ptar,nac);
	delete ptar;
}

int CBemRawDoc::FindCorner(CPoint pt)
{
	int i,ij;
	ij=-1;
	for (i=0;i<Area.GetSize();i++)
	{
		CNode* nd=GetArNode(i);
		if (nd->IsEqu(pt,gcb)) {ij=i;break;}
	}
	return ij;
}

void CBemRawDoc::DelCorner(int i)
{
	if (i<0) return;
	CNode* nd=GetArNode(i);
	Area.RemoveAt(i);
	delete nd;
}

void CBemRawDoc::GenParts(CDC &dc)
{
	int i,nac,np;
	float xmin,xmax,ymin,ymax,x,y,dx,dy,ar;
	nac=Area.GetSize();
	if (nac<=0) return;
	CPoint* ptar;
	CInpParts pin;
	ptar=new CPoint[nac];
	for (i=0;i<nac;i++)
	{
		CNode* nd=GetArNode(i);
		if (i==0) {xmin=xmax=nd->xb;ymin=ymax=nd->yb;}
		else
		{
			if (nd->xb>xmax) xmax=nd->xb;
			if (nd->xb<xmin) xmin=nd->xb;
			if (nd->yb>ymax) ymax=nd->yb;
			if (nd->yb<ymin) ymin=nd->yb;
		}
		nd->TranCoord(gcb);
		ptar[i]=nd->Coord();
	}
	CRgn rg;
	rg.CreatePolygonRgn (ptar,nac,ALTERNATE);
	pin.m_nx=pin.m_ny=50;pin.m_efpo=efpo;pin.m_con=1.0f;
	pin.m_al=al;pin.m_at=at;
	if (pin.DoModal()==IDOK)
	{
		efpo=pin.m_efpo;
		if (efpo<=0.0f)
		{
			AfxMessageBox ("Error! Eff.porosity must be positive!");
		}
		else
		{
			i=0;
			while (i<TimInts.GetSize())
			{
				delete TimInts.GetAt(i++);
			}	                     
			TimInts.RemoveAll();
			CTimeInt* tm=AddTime(0.0f);tim=0.0f;
			dx=(xmax-xmin)/(float)pin.m_nx;dy=(ymax-ymin)/(float)pin.m_ny;
			for (x=xmin+dx*0.5f;x<xmax;x+=dx)
			{
				for (y=ymin+dy*0.5f;y<ymax;y+=dy)
				{
					CPoint pt=TranCoord(x,y);
					if (rg.PtInRegion(pt))
					{
						CPartic* par=tm->AddParts(x,y);
						par->Plot(dc,gcb,RGB(255,0,0));
					}
				}
			}
			retd=efpo+pin.m_rho*pin.m_kd;
			ar=PolArea();
			np=tm->Parts.GetSize();
			matter=ar*thick*efpo*pin.m_con/(float)np;
			al=pin.m_al;at=pin.m_at;
			CString msg;
			msg.Format ("Area: %.3f\r\nNo.of particles: %d\r\nRetardation: %.3f\n\rMatter: %.5f",ar,np,retd,matter);
			AfxMessageBox(msg);
		}
	}
	delete ptar;
}

CPoint CBemRawDoc::TranCoord(float x, float y)
{
	CPoint pt;
 	pt.x=gcb[0]+gcb[1]*(x-gcb[2])+0.5;
 	pt.y=gcb[3]+gcb[4]*(y-gcb[5])+0.5;
	return pt;
}

float CBemRawDoc::PolArea()
{
	float ar;
	int i,nc;
	nc=Area.GetSize();
	ar=0.0f;
	for (i=0;i<nc-1;i++)
	{
		CNode* nd1=GetArNode(i);
		CNode* nd2=GetArNode(i+1);
		ar+=(nd2->xb-nd1->xb)*(nd2->yb+nd1->yb);
	}
	CNode* nd1=GetArNode(nc-1);
	CNode* nd2=GetArNode(0);
	ar+=(nd2->xb-nd1->xb)*(nd2->yb+nd1->yb);
	ar*=0.5f;
	return fabs(ar);
}

void CBemRawDoc::PositionParts(CDC &td)
{
	int i,it,ired,igren,ibl,ipa,nn,npar;
	double vx,vy,vxx,vyy,v,dxx,dyy,dxy,dyx,dvx,dv,dvy;
	float xx,yy,dx,dy,sigl,sigt,r1,r2,xb,yb;
	ired=ibl=0;igren=255;
	CPoint* ptar,pt;
	nn=Nodes.GetSize();
	ptar=new CPoint[nn];
	for (i=0;i<nn;i++)
	{
		CNode* nd=GetNode(i);
		nd->TranCoord(gcb);
		ptar[i]=nd->Coord();
	}
	CRgn rg;
	rg.CreatePolygonRgn (ptar,nn,ALTERNATE);
	for (it=0;it<ntim;it++)           //--------- time loop ---------
	{
		CTimeInt* tm1=GetTime(it);
		tim+=delt;
		CTimeInt* tm2=AddTime(tim);
		npar=tm1->Parts.GetSize();
		CString nadt;
		nadt.Format ("Time: %.3f",tim/86400.0f);
		UINT txa=td.SetTextAlign(TA_RIGHT | TA_TOP);
//		td.TextOut (r.right-5,r.top+5,nadt);
		td.SetTextAlign(txa);
		ired+=5*it;if (ired>255) ired=0;
		ibl+=10*it;if (ibl>255) ibl=0;
		igren-=10*it;if (igren<0) igren=255;
		for (ipa=0;ipa<npar;ipa++)       //-------- particles loop -------
		{
			CPartic* par=tm1->GetPartic(ipa);
			xb=par->xb;yb=par->yb;
			Veloc (vx,vy,xb,yb);
			vx/=retd;vy/=retd;
			dx=vx*delt;dy=vy*delt;
			xb+=dx;yb+=dy;
			pt=TranCoord(xb,yb);
			if (rg.PtInRegion(pt))
			{
				Veloc (vxx,vyy,xb,yb);
				vxx/=retd;vyy/=retd;
				v=sqrt(vx*vx+vy*vy);
				dvx=vxx-vx;dvy=vyy-vy;dv=sqrt(vxx*vxx+vyy*vyy)-v;
				dxx=(al*(2.0*vx*dvx*v-vx*vx*dv)+at*(2.0*vy*dvy*v-vy*vy*dv))/(v*v*dx);
				dyy=(al*(2.0*vy*dvy*v-vy*vy*dv)+at*(2.0*vx*dvx*v-vx*vx*dv))/(v*v*dy);
				dxy=(al-at)*((dvx*vy+dvy*vx)*v-vx*vy*dv)/(v*v*dx);
				dyx=(al-at)*((dvx*vy+dvy*vx)*v-vx*vy*dv)/(v*v*dy);
				vx=(vxx+vx)*0.5+dxx+dxy;vy=(vyy+vy)*0.5+dyy+dyx;
				v=sqrt(vx*vx+vy*vy);r1=r2=0.0F;
				if (al>0.0F)
				{
					sigl=sqrt(2*al*v*delt)/v;r1=gran();
				}
				if (at>0.0F)
				{
					sigt=sqrt(2*at*v*delt)/v;r2=gran();
				}
				dx=vx*(delt+r1*sigl)+vy*r2*sigt;
				dy=vy*(delt+r1*sigl)+vx*r2*sigt;

				xx=par->xb+dx;yy=par->yb+dy;
				CPartic* prn=tm2->AddParts(xx,yy);
				prn->Plot(td,gcb,RGB(ired,igren,ibl));
			}  
		}				//------ end of particles loop
	}					//------ end of time loop
}

void CBemRawDoc::TimeInter(CDC &dc)
{
	CInpTime tm;
	tm.m_nt=ntim;tm.m_dt=delt;
	if (tm.DoModal()==IDOK)
	{
		ntim=tm.m_nt;delt=tm.m_dt;
		PositionParts(dc);
	}
}

float CBemRawDoc::gran()
{
	float x,y;int i;
	x=-6;
	for (i=0;i<12;i++)
	{
		y=rand();
		x=x+y/32767.0;
	}
	return(x);
}

void CBemRawDoc::PlotTime(CDC &dc, int its,int ite)
{
	int i,j;
	if (its<0 || ite<0) return;
	if (ite>ntim) ite=ntim;
	for (i=its;i<ite;i++)
	{
		CTimeInt* tm=GetTime(i);
		for (j=0;j<tm->Parts.GetSize();j++)
		{
			CPartic* pr=tm->GetPartic(j);
			pr->Plot(dc,gcb,RGB(255,0,0));
		}
	}
}

void CBemRawDoc::OpenCorner()
{
	char szFile[256];
	UINT  i, cbString;
	char  chReplace;    /* string separator for szFilter */
	char  szFilter[256],msg[80],*pom,*pf;
	float x,y;
	CString menf;
	CFileDialog fd(TRUE);    
	CStdioFile hf;

    strcpy(szFilter,"Text files (*.TXT)|*.txt|Mapview files(*.BNA)|*.bna|All files (*.*)|*.*|");
    cbString=strlen(szFilter);
	chReplace = szFilter[cbString - 1]; /* retrieve wildcard */
    szFile[0]=0;
    
    for (i = 0; szFilter[i] != '\0'; i++) 
	{
    	if (szFilter[i] == chReplace) szFilter[i] = '\0';
	}

/* Set all structure members to zero. */

	fd.m_ofn.lpstrFilter = szFilter;
	fd.m_ofn.nFilterIndex = 1;
	fd.m_ofn.lpstrFile= szFile;
	fd.m_ofn.nMaxFile = sizeof(szFile);
	fd.m_ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK | OFN_EXPLORER;


	if (fd.DoModal()==IDOK) 
	{
		menf=fd.GetPathName();
		hf.Open(menf,CFile::typeText | CFile::modeRead);
		if (fd.m_ofn.nFilterIndex==1)
		{
     		for (;;)
     		{
     			pf=hf.ReadString (msg,80);
     			if (pf==NULL) break;
     			pom=strtok(msg,", ");x=atof(pom);
     			pom=strtok (NULL,", ");y=atof(pom);
				AddCorner (x,y);
			}
		}
		if (fd.m_ofn.nFilterIndex==2)
		{
     		for (;;)
     		{
     			pf=hf.ReadString (msg,80);
     			if (pf==NULL) break;
     			if (msg[0]=='"') continue;
     			pom=strtok(msg,", ");x=atof(pom);
     			pom=strtok (NULL,", ");y=atof(pom);
				AddCorner (x,y);
			}
		}	
		hf.Close();
	}
}

void CBemRawDoc::SaveCorner()
{
	char szFile[256];
	UINT  cbString;
	int i;
	char  chReplace;    /* string separator for szFilter */
	char  szFilter[256];
	CString menf,msx;
	CFileDialog fd(FALSE);    
	CStdioFile hf;

    strcpy(szFilter,"Corners (*.TXT)|*.txt|Mapview (*.BNA)|*.bna|všetky (*.*)|*.*|");
    cbString=strlen(szFilter);
	chReplace = szFilter[cbString - 1]; /* retrieve wildcard */
    szFile[0]=0;
    
    for (i = 0; szFilter[i] != '\0'; i++) 
	{
    	if (szFilter[i] == chReplace) szFilter[i] = '\0';
	}

/* Set all structure members to zero. */

	fd.m_ofn.lpstrFilter = szFilter;
	fd.m_ofn.nFilterIndex = 1;
	fd.m_ofn.lpstrFile= szFile;
	fd.m_ofn.nMaxFile = sizeof(szFile);
	fd.m_ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_EXPLORER;


	if (fd.DoModal()==IDOK) 
	{
		menf=fd.GetPathName();
		msx=fd.GetFileExt();
		if (fd.m_ofn.nFilterIndex==1)
		{
			if (msx.IsEmpty()) menf+=".txt";
			hf.Open(menf,CFile::typeText | CFile::modeWrite | CFile::modeCreate);
			for (i=0;i<Area.GetSize();i++)
			{
				CNode* bd=GetArNode(i);
				CString str;
				str.Format ("%8.3f %8.3f\n",bd->xb,bd->yb);
				hf.WriteString(str);
			}
		}
		if (fd.m_ofn.nFilterIndex==2)
		{
			if (msx.IsEmpty()) menf+=".bna";
			hf.Open(menf,CFile::typeText | CFile::modeWrite | CFile::modeCreate);
			for (i=0;i<Area.GetSize();i++)
			{
				CNode* bd=GetArNode(i);
				CString str;
				str.Format ("\"%d\"\n",i+1);
				hf.WriteString(str);
				str.Format ("%8.3f %8.3f\n",bd->xb,bd->yb);
				hf.WriteString(str);
			}
		}
		hf.Close();
	}
}

void CBemRawDoc::OpenParts()
{
	char szFile[256];
	UINT  i, cbString;
	char  chReplace;    /* string separator for szFilter */
	char  szFilter[256];
	CString menf;
	CFileDialog fd(TRUE);    
	CFile hf;

    strcpy(szFilter,"Particles (*.PAR)|*.par|All files (*.*)|*.*|");
    cbString=strlen(szFilter);
	chReplace = szFilter[cbString - 1]; /* retrieve wildcard */
    szFile[0]=0;
    
    for (i = 0; szFilter[i] != '\0'; i++) 
	{
    	if (szFilter[i] == chReplace) szFilter[i] = '\0';
	}

/* Set all structure members to zero. */

	fd.m_ofn.lpstrFilter = szFilter;
	fd.m_ofn.nFilterIndex = 1;
	fd.m_ofn.lpstrFile= szFile;
	fd.m_ofn.nMaxFile = sizeof(szFile);
	fd.m_ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK | OFN_EXPLORER;


	if (fd.DoModal()==IDOK) 
	{
		menf=fd.GetPathName();
		hf.Open(menf,CFile::typeBinary | CFile::modeRead);
		CArchive ar(&hf,CArchive::load);
		TimInts.Serialize(ar);
		ntim=TimInts.GetSize();
		ar.Close();
		hf.Close();
	}
	else ntim=0;
}

void CBemRawDoc::OnPartSave() 
{
	char szFile[256];
	UINT  cbString;
	int i;
	char  chReplace;    /* string separator for szFilter */
	char  szFilter[256];
	CString menf,msx;
	CFileDialog fd(FALSE);    
	CFile hf;

    strcpy(szFilter,"Particles (*.PAR)|*.par|všetky (*.*)|*.*|");
    cbString=strlen(szFilter);
	chReplace = szFilter[cbString - 1]; /* retrieve wildcard */
    szFile[0]=0;
    
    for (i = 0; szFilter[i] != '\0'; i++) 
	{
    	if (szFilter[i] == chReplace) szFilter[i] = '\0';
	}

/* Set all structure members to zero. */

	fd.m_ofn.lpstrFilter = szFilter;
	fd.m_ofn.nFilterIndex = 1;
	fd.m_ofn.lpstrFile= szFile;
	fd.m_ofn.nMaxFile = sizeof(szFile);
	fd.m_ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_EXPLORER;


	if (fd.DoModal()==IDOK) 
	{
		menf=fd.GetPathName();
		msx=fd.GetFileExt();
		if (msx.IsEmpty()) menf+=".par";
		hf.Open(menf,CFile::typeBinary | CFile::modeWrite | CFile::modeCreate);
		CArchive ar(&hf,CArchive::store);
		TimInts.Serialize(ar);
		ar.Close();
		hf.Close();
	}	
}
