#include "stdafx.h"
#include "math.h"
#include "geom.h"
#include "bemraw.h"

#include "bemrawDoc.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////
// Class of nodes

IMPLEMENT_SERIAL (CNode,CObject,1);

CNode::CNode (float x,float y)
{
	xb=x;yb=y;ok=0;
}	                              

CNode::CNode() {ok=1;};

CNode::CNode (CPoint p,float *gc)
{
	xi=p.x;yi=p.y;ok=0;
	RevTran (gc);
}

void CNode::Bound (int i)
{
	ok=i;
}
		
void CNode::TranCoord (float *gcb)
{
// transformation from world coordinates to the logical coordinates
 	xi=gcb[0]+gcb[1]*(xb-gcb[2])+0.5;
 	yi=gcb[3]+gcb[4]*(yb-gcb[5])+0.5;
}

void CNode::RevTran (float *gcb)
{
 	xb=((float)xi-gcb[0])/gcb[1]+gcb[2];
 	yb=((float)yi-gcb[3])/gcb[4]+gcb[5];
}

void CNode::Serialize(CArchive& ar)
{               
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{           
		ar << xb << yb;
	}
	else
	{                                        
		ar >> xb >> yb;
	}
}

BOOL CNode::operator ==(const CNode& other) const
{
 return (fabs(other.xb-xb)<1e-6)&&(fabs(other.yb-yb)<1e-6);
}

int CNode::IsEqu (CPoint p,float *gc)
{                                  
	TranCoord (gc);
 	return (abs(xi-p.x)<3) && (abs(yi-p.y)<3);
}

void CNode::PlotNode (CDC *DC,int ib,int vel,float *gc)
{
  char msg[10];
  TranCoord(gc);                                
  switch (ok)
  {
  	case 1:DC->Rectangle (xi-vel,yi-vel,xi+vel,yi+vel);break;
  	case 0:
 	 	DC->MoveTo(xi,yi);DC->LineTo(xi+vel,yi);
  		DC->MoveTo(xi,yi);DC->LineTo(xi-vel,yi);
  		DC->MoveTo(xi,yi);DC->LineTo(xi,yi-vel);
  		DC->MoveTo(xi,yi);DC->LineTo(xi,yi+vel);
  		break;
  	case 2:
  		DC->Ellipse (xi-vel,yi-vel,xi+vel,yi+vel);break;	
  }	
  if (ib>0)
  {
	DC->SetTextAlign (TA_LEFT | TA_BOTTOM);
	sprintf (msg,"N%d",ib);
	DC->TextOut (xi+vel*1.5,yi-0.8*vel,msg,strlen(msg));
  }
}

void CNode::Coord (float& x,float &y)
{
	x=xb;y=yb;
}

void CNode::Mult (float nas)
{
	xb*=nas;yb*=nas;
}

CPoint CNode::Coord (void)
{
	CPoint p;
	p.x=xi;p.y=yi;
	return p;
}

//////////////////////////////////////////////////////////////////////////
//  Class of elements

IMPLEMENT_SERIAL (CElement,CObject,1);

CElement::CElement() 
{
	pot=der=dist=kf0=level=0.0f;
}

CElement::CElement (int u1,int u2)
{
	nod1=u1;nod2=u2;type=0;
	pot=der=dist=kf0=level=0.0f;
}	

void CElement::Serialize(CArchive& ar)
{                                               
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{                                                                        
		ar << nod1 << nod2 << type;
		ar << pot << der << level << kf0 << dist;
	}
	else
	{                                                            
		ar >> nod1 >> nod2 >> type;
		ar >> pot >> der >> level >> kf0 >> dist;
	}
}

/////////////////////////////////////////////////////////////////////////
// class of wells

IMPLEMENT_SERIAL (CWell,CObject,1);

CWell::CWell() {};

CWell::CWell (CString s,float x,float y,float *gc,float dis,float d)
{
	name=s;
	xz=x;yz=y;yield=dis;diam=d;
	TranCoord (gc);
}

CWell::CWell (CString s,CPoint p,float *gc,float dis,float d)
{
	name=s;
	xi=p.x;yi=p.y;yield=dis;diam=d;
	RevTran (gc);
}

BOOL CWell::operator ==(const CWell& other) const { return &other == this; }

void CWell::TranCoord (float *gcb)
{
 	xi=gcb[0]+gcb[1]*(xz-gcb[2])+0.5;
 	yi=gcb[3]+gcb[4]*(yz-gcb[5])+0.5;
}

void CWell::RevTran (float *gcb)
{
 	xz=((float)xi-gcb[0])/gcb[1]+gcb[2];
 	yz=((float)yi-gcb[3])/gcb[4]+gcb[5];
}

int CWell::IsEqu (CPoint p,float *gc)
{                                  
	TranCoord (gc);
 	return (abs(xi-p.x)<5) && (abs(yi-p.y)<5);
}

CPoint CWell::GetCoord (void)
{
	CPoint p;
	p.x=xi;p.y=yi;
	return p;
}

void CWell::Serialize(CArchive& ar)
{                                       
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{            
		ar << name << xz << yz << yield << diam << drwdown;  
 	}
	else
	{   
		ar >> name >> xz >> yz >> yield >> diam >> drwdown;  
	}
}

void CWell::Plot(CDC *pDC, float *gc,int sz)
{
	CBrush bred(RGB(255,0,0)),*bpr;
	int sz1=MulDiv(sz,5,3);
	TranCoord(gc);
	pDC->Ellipse(xi-sz1,yi-sz1,xi+sz1,yi+sz1);
	bpr=pDC->SelectObject(&bred);
	pDC->Ellipse(xi-sz,yi-sz,xi+sz,yi+sz);
	pDC->SelectObject(bpr);
	pDC->TextOut(xi+sz1,yi,name);
}

/////////////////////////////////////////////////////////////////////////
// class of internal points

IMPLEMENT_SERIAL (CIntPoint,CObject,1);

CIntPoint::CIntPoint() {};

CIntPoint::CIntPoint (float x,float y,float *gc)
{
	xz=x;yz=y;
	TranCoord (gc);
}

CIntPoint::CIntPoint (CPoint p,float *gc)
{
	xi=p.x;yi=p.y;
	RevTran (gc);
}

BOOL CIntPoint::operator ==(const CIntPoint& other) const { return &other == this; }

void CIntPoint::TranCoord (float *gcb)
{
 	xi=gcb[0]+gcb[1]*(xz-gcb[2])+0.5;
 	yi=gcb[3]+gcb[4]*(yz-gcb[5])+0.5;
}

void CIntPoint::RevTran (float *gcb)
{
 	xz=((float)xi-gcb[0])/gcb[1]+gcb[2];
 	yz=((float)yi-gcb[3])/gcb[4]+gcb[5];
}

int CIntPoint::IsEqu (CPoint p,float *gc)
{                                  
	TranCoord (gc);
 	return (abs(xi-p.x)<5) && (abs(yi-p.y)<5);
}

CPoint CIntPoint::GetCoord (void)
{
	CPoint p;
	p.x=xi;p.y=yi;
	return p;
}

void CIntPoint::PlotPt (CDC *DC,int ib,int vel,float *gc)
{
	char msg[10];
	TranCoord(gc);                                
 	DC->MoveTo(xi-vel,yi-vel);DC->LineTo(xi+vel,yi+vel);
 	DC->MoveTo(xi+vel,yi-vel);DC->LineTo(xi-vel,yi+vel);
	if (ib>0)
	{
		DC->SetTextAlign (TA_LEFT | TA_BOTTOM);
		sprintf (msg,"P%d",ib);
		DC->TextOut (xi+vel*1.5,yi-0.8*vel,msg,strlen(msg));
	}
}

void CIntPoint::Serialize(CArchive& ar)
{                                       
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{            
		ar << xz << yz << drwdown << vx << vy;
 	}
	else
	{   
		ar >> xz >> yz >> drwdown >> vx >> vy;
	}
}

/////////////////////////////////////////////////////////////////////////
// class of internal elements

IMPLEMENT_SERIAL (CIntElem,CObject,1);

CIntElem::CIntElem() {};

CIntElem::CIntElem (float *x,float *y,float pr)
{
	for (int i=0;i<3;i++) {xp[i]=x[i];yp[i]=y[i];}
	precip=pr;
}

void CIntElem::Serialize(CArchive& ar)
{                                       
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{            
		ar.Write (xp,sizeof(xp));
		ar.Write (yp,sizeof(yp));
		ar << precip;
 	}
	else
	{   
		ar.Read (xp,sizeof(xp));
		ar.Read (yp,sizeof(yp));
		ar >> precip;
	}
}

/////////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL (CTimeInt,CObject,1);

CTimeInt::CTimeInt (float tm)
{
	tim=tm;
	int i=0;
	while (i<Parts.GetSize())
	{
		delete Parts.GetAt(i++);
	}	                     
	Parts.RemoveAll();
}	                              

CTimeInt::CTimeInt() {};

CTimeInt::~CTimeInt() 
{
	int i=0;
	while (i<Parts.GetSize())
	{
		delete Parts.GetAt(i++);
	}	                     
	Parts.RemoveAll();
}

void CTimeInt::Serialize(CArchive& ar)
{                                       
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{
		ar << tim;
 	}
	else
	{
		ar >> tim;
	}
	Parts.Serialize(ar);
}

CPartic* CTimeInt::GetPartic(int i)
{
	return (CPartic*)Parts.GetAt(i);
}

CPartic* CTimeInt::AddParts(float x, float y)
{
	CPartic* pr=new CPartic(x,y);
	Parts.Add(pr);
	return pr;
}

/////////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL (CPartic,CObject,1);

CPartic::CPartic (float x,float y)
{
	xb=x;yb=y;flg=0;
}	                              

CPartic::CPartic() {};

CPartic::CPartic (CPoint p,float *gc)
{
	xi=p.x;yi=p.y;flg=0;
	RevTran (gc);
}
		
void CPartic::TranCoord (float *gcb)
{
// transformation from world coordinates to the logical coordinates
	float dx,dy;
	dx=gcb[1]*(xb-gcb[2]);dy=gcb[4]*(yb-gcb[5]);
	if (dx>0.0f) dx+=0.5f;
	else dx-=0.5f;
	if (dy>0.0f) dy+=0.5f;
	else dy-=0.5f;
 	xi=gcb[0]+dx;
 	yi=gcb[3]+dy;
}

void CPartic::RevTran (float *gcb)
{
 	xb=((float)xi-gcb[0])/gcb[1]+gcb[2];
 	yb=((float)yi-gcb[3])/gcb[4]+gcb[5];
}

void CPartic::Serialize(CArchive& ar)
{               
	CObject::Serialize(ar);
	if (ar.IsStoring())
	{           
		ar << xb << yb;
	}
	else
	{                                        
		ar >> xb >> yb;
	}
}

BOOL CPartic::operator ==(const CPartic& other) const
{
 return (fabs(other.xb-xb)<1e-6)&&(fabs(other.yb-yb)<1e-6);
}

void CPartic::Coord (float& x,float &y)
{
	x=xb;y=yb;
}

CPoint CPartic::Coord (void)
{
	CPoint p;
	p.x=xi;p.y=yi;
	return p;
}

void CPartic::Plot(CDC &dc, float *gc, COLORREF clr)
{
	TranCoord(gc);
	dc.SetPixelV (xi,yi,clr);
}
