// BemStreamDoc.cpp : implementation of the CBemStreamDoc class
//

#include "stdafx.h"
#include "math.h"
#include "BemStream.h"

#include "geom.h"
#include "BemStreamDoc.h"
#include "liststamp.h"
#include "stamplist.h"

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

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc

IMPLEMENT_DYNCREATE(CBemStreamDoc, CDocument)

BEGIN_MESSAGE_MAP(CBemStreamDoc, CDocument)
	//{{AFX_MSG_MAP(CBemStreamDoc)
	ON_COMMAND(ID_SAVE_STREAM, OnSaveStream)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc construction/destruction

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

}

CBemStreamDoc::~CBemStreamDoc()
{
}

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

	m_size.cx=1000;m_size.cy=800;
	efpo=0.1f;
	return TRUE;
}

BOOL CBemStreamDoc::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=0.1f;
	
	return TRUE;
}

void CBemStreamDoc::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<Stamps.GetSize())
	{
		delete Stamps.GetAt(i++);
	}	                     
	Stamps.RemoveAll();
	i=0;
	while (i<Streams.GetSize())
	{
		delete Streams.GetAt(i++);
	}	                     
	Streams.RemoveAll();
	
	CDocument::DeleteContents();
}

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc serialization

void CBemStreamDoc::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);
}

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc diagnostics

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

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

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc commands
void CBemStreamDoc::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 CBemStreamDoc::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 CBemStreamDoc::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 CBemStreamDoc::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();
}

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

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

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

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

CIntElem* CBemStreamDoc::GetIntElem(int i)
{
	return (CIntElem*)TriElems.GetAt(i);
}

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

CStream* CBemStreamDoc::AddStream(float x, float y, int iw)
{
	int i;
	CStream* st=new CStream(x,y,iw);
	for (i=0;i<Stamps.GetSize();i++)
	{
		CStamp* stm=GetStamp(i);
		st->AddStamp(stm);
	}
	Streams.Add(st);
	return st;
}

CStream* CBemStreamDoc::AddStream(CPoint p, int iw)
{
	int i;
	CStream* st=new CStream(p,gcb,iw);
	for (i=0;i<Stamps.GetSize();i++)
	{
		CStamp* stm=GetStamp(i);
		st->AddStamp(stm);
	}
	Streams.Add(st);
	return st;
}

CStream* CBemStreamDoc::GetStream(int i)
{
	return (CStream*)Streams.GetAt(i);
}

CStamp* CBemStreamDoc::AddStamp(float x, float y, float tm)
{
	CStamp* st=new CStamp(x,y,tm);
	Stamps.Add(st);
	return st;
}

CStamp* CBemStreamDoc::AddStamp(CStamp* stp)
{
	CStamp* st=new CStamp(stp);
	Stamps.Add(st);
	return st;
}

CStamp* CBemStreamDoc::GetStamp(int i)
{
	return (CStamp*)Stamps.GetAt(i);
}

void CBemStreamDoc::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;
	delt=0.002*sqrt(dx*dx+dy*dy);
	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 CBemStreamDoc::AddStreamWell(CDC &dc, CPoint pt, int nstr)
{
	if (nwl==0) return;
	int i,iw;
	float xs,ys,dang,pi2=6.283185f;
	iw=-1;
	for (i=0;i<nwl;i++)
	{
		CWell* wl=GetWell(i);
		if (wl->IsEqu(pt,gcb)) {iw=i;break;}
	}
	if (iw<0)
	{
		AfxMessageBox("Well is not found!");
		return;
	}
	CWell* wl=GetWell(iw);
	dang=pi2/(float)nstr;
	for (i=0;i<nstr;i++)
	{
		xs=wl->xz+wl->diam*cos(i*dang);
		ys=wl->yz+wl->diam*sin(i*dang);
		CStream* str=AddStream(xs,ys,iw);
		Stream (dc,str,-1.0f);
	}
}

void CBemStreamDoc::PlotStream(CDC *pDC,int iscz,int iscc,int sz)
{
	int i;
	CFont hf,*hfp;
	hf.CreateFontIndirect(&lfnt);
	hfp=pDC->SelectObject(&hf);
	for (i=0;i<Streams.GetSize();i++)
	{
		CStream* str=GetStream(i);
		str->Plot(*pDC,gcb,iscz,iscc,sz,efpo);
	}
	pDC->SelectObject(hfp);
	hf.DeleteObject();
}

void CBemStreamDoc::InpStamp()
{
	CStampList stl;
	int i,j;
	for (i=0;i<Stamps.GetSize();i++)
	{
		CStamp* st=GetStamp(i);
		stl.AddStamp(st);
	}
	stl.m_efpo=efpo;
	if (stl.DoModal()==IDOK)
	{
		efpo=stl.m_efpo;
		i=0;
		while (i<Stamps.GetSize())
		{
			delete Stamps.GetAt(i++);
		}	                     
		Stamps.RemoveAll();
		for (i=0;i<stl.Stamps.GetSize();i++)
		{
			CStamp* st=stl.GetStamp(i);
			AddStamp(st);
		}
		for (j=0;j<Streams.GetSize();j++)
		{
			CStream* str=GetStream(j);
			i=0;
			while (i<str->Stamps.GetSize())
			{
				delete str->Stamps.GetAt(i++);
			}	                     
			str->Stamps.RemoveAll();
			for (i=0;i<Stamps.GetSize();i++)
			{
				CStamp* stm=GetStamp(i);
				str->AddStamp(stm);
			}
			str->PoStamps(efpo);
		}
	}
}

void CBemStreamDoc::OnSaveStream() 
{
	char szFile[256];
	UINT  cbString;
	int i;
	char  chReplace;    /* string separator for szFilter */
	char  szFilter[256];
	CString namef;
	CFileDialog fd(FALSE);    
	CFile hf;

    strcpy(szFilter,"Streamlines (*.STR)|*.str|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_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_EXPLORER;


	if (fd.DoModal()==IDOK) 
	{
		namef=fd.GetPathName();
		CString namex;
		namex=fd.GetFileExt();
		if (namex.IsEmpty()) namef+=".str";
		hf.Open(namef,CFile::typeBinary | CFile::modeWrite | CFile::modeCreate);
		CArchive ar(&hf,CArchive::store);
		ar << efpo;
		Streams.Serialize(ar);
		Stamps.Serialize(ar);
		ar.Close();
		hf.Close();
	}
}

void CBemStreamDoc::ReadStamps(CFile *hf)
{
	CArchive ar(hf,CArchive::load);
	ar >> efpo;
	Streams.Serialize(ar);
	Stamps.Serialize(ar);
	ar.Close();
	int i,j;
	for (j=0;j<Streams.GetSize();j++)
	{
		CStream* str=GetStream(j);
		i=0;
		while (i<str->Stamps.GetSize())
		{
			delete str->Stamps.GetAt(i++);
		}	                     
		str->Stamps.RemoveAll();
		for (i=0;i<Stamps.GetSize();i++)
		{
			CStamp* stm=GetStamp(i);
			str->AddStamp(stm);
		}
		str->PoStamps(efpo);
	}
}

void CBemStreamDoc::ChangeFont()
{
	LOGFONT pom;
	memcpy (&pom,&lfnt,sizeof(LOGFONT));
	CFontDialog dlg(&pom, CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT);
	if (dlg.DoModal() == IDOK)
	{      
		memcpy (&lfnt,&pom,sizeof(LOGFONT));
		SetModifiedFlag();
	}
}
