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

#include "geom.h"
#include "BemStreamDoc.h"

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

/////////////////////////////////////////////////////////////////////////////
// CBemStreamDoc-function for integration

/*---------------------------------------------------------*/
/*  INVEL - analytical integration of velocity             */
/*---------------------------------------------------------*/
void CBemStreamDoc::InVel (double xp,double yp,double x1,double y1,double x2,double y2,double& hx,double& hy,double& gx,double& gy,double tt)
{
 	double r1,r2,dl,lg1,lg2,nx,ny,d,xo2,xop,yop,a2,b2,c2,fa,fb,
   		yo1,yo2,dx1,dx2,dy2,dy1,s2,pi=3.14159265,pi2;
 	pi2=pi*0.5;
	dx1=x1-x2;dy1=y1-y2;
 	c2=dx1*dx1+dy1*dy1;
 	dx1=x1-xp;dx2=x2-xp;dy1=y1-yp;dy2=y2-yp;
 	a2=dx1*dx1+dy1*dy1;
 	b2=dx2*dx2+dy2*dy2;
 	r1=sqrt(a2);r2=sqrt(b2);dl=sqrt(c2);
 	lg1=log(r1);lg2=log(r2);
 	ny=(x1-x2)/dl;nx=(y2-y1)/dl;
 	xo2=x2*nx+y2*ny;xop=xp*nx+yp*ny;
 	d=xo2-xop;
 	yo1=-ny*x1+nx*y1;
 	yo2=-ny*x2+nx*y2;yop=-ny*xp+nx*yp;
 	if (fabs(d)<1e-8)
	{
  		gx=(lg2-lg1)*ny;
  		gy=-nx*(lg2-lg1);
  		hx=hy=0.0;
 		gx*=tt;gy*=tt;
	}
	else
	{
 		fb=atan2 (yo2-yop,d);fa=atan2 (yo1-yop,d);
 		if (fabs(fa)==pi2||fabs(fb)==pi2)
		{
  			gx=(lg2-lg1)*ny;
  			gy=-nx*(lg2-lg1);
  			hx=hy=0.0;
 			gx*=tt;gy*=tt;
		}
		else
		{
 			s2=fa-fb;
 			gx=nx*s2+ny*(lg2-lg1);
 			gy=ny*s2-nx*(lg2-lg1);
 			hx=dy2/b2-dy1/a2;
 			hy=-dx2/b2+dx1/a2;
 			hx*=tt;hy*=tt;
 			gx*=tt;gy*=tt;
		}
	}
}

void CBemStreamDoc::Veloc (double& vx,double& vy,float xb,float yb)
{
	int j,i1,i2;
	float x1,y1,x2,y2,qq,sx,sy,dx,dy,rb,ra,ybb;
	double ax,ay,bx,by;
	ybb=yb*txy;
	vx=vy=0.0;
	for (j=0;j<nel;j++)
    {
     	CElement* el=GetElement(j);
		i1=el->nod1;i2=el->nod2;
		CNode* nd1=GetNode(i1);CNode* nd2=GetNode(i2);
		x1=nd1->xb;y1=nd1->yb*txy;
		x2=nd2->xb;y2=nd2->yb*txy;
     	InVel (xb,ybb,x1,y1,x2,y2,ax,ay,bx,by,tt);
     	vx+=el->der*bx-el->pot*ax;
     	vy+=el->der*by-el->pot*ay;
    }
    if (nwl>0)
    {
    	sx=sy=0.0;
     	for (j=0;j<nwl;j++)
     	{             
			CWell* wl=GetWell(j);
      		dx=xb-wl->xz;dy=ybb-wl->yz*txy;
      		rb=dx*dx+dy*dy;
       		qq=-wl->yield/tx;
      		ra=1./sqrt(rb);
      		sx+=qq*dx/rb;sy+=qq*dy/rb;
     	}
     	vx+=sx;vy+=sy;
    }
   	vx*=tp*kx;vy*=tp*ky*txy;
}

/*---------------------------------------------*/
/*  STREAM - computation of streamline points  */
/*---------------------------------------------*/
void CBemStreamDoc::Stream (CDC& td,CStream* str,float orient)
{
	int ii,i,strend;
	float xb,yb,tim,v,dx,dy;
	double vx,vy,vxn,vyn;
	CRgn rg;
	CPoint *pt,p;

	pt=new CPoint[nel];
	CStrPoint* sp=str->GetPoint(0);
	xb=sp->xb;yb=sp->yb;
	sp->TranCoord(gcb);
	p=sp->Coord();
	for (i=0;i<nel;i++)
	{
     	CElement* el=GetElement(i);
		ii=el->nod1;
		CNode* nd=GetNode(ii);
		pt[i]=nd->Coord();
	}
	rg.CreatePolygonRgn(pt,nel,ALTERNATE);
	if (!rg.PtInRegion(p)) return;  // starting point is out of the region!
	td.MoveTo (p);
	tim=0;
	strend=0;vxn=vyn=0.0f;
	do								// ------ loop of points -----
	{
		Veloc (vx,vy,xb,yb);
//		vx=vx/efpo;vy=vy/efpo;
		if ((vx*vxn<0.0f)&&(vy*vyn<0.0f)) 
		{
			strend=1;
			break;
		}
		vxn=vx;vyn=vy;
		v=sqrt(vx*vx+vy*vy);dx=orient*vx/v;dy=orient*vy/v;
		xb+=dx*delt;yb+=dy*delt;
		tim+=delt/v;
		CStrPoint* spn=str->AddPoint (xb,yb,tim);
		spn->TranCoord(gcb);
		p=spn->Coord();
		td.LineTo (p);
		str->time=tim;str->ixp=p.x;str->iyp=p.y;
		strend=TestWells(spn,str->iwl);
		if (!rg.PtInRegion(p)) strend=1;  // ------- end of streamline ?
	}          
	while (strend==0);
}

int CBemStreamDoc::TestWells (CStrPoint* pt,int nwl)
{
	int i;
	for (i=0;i<nwl;i++)
	{
		if (i==nwl) continue;
		CWell* wl=GetWell(i);
		if (fabs(wl->yield)<1e-8) continue;
		wl->TranCoord(gcb);
		if (abs(pt->xi-wl->xi)<5&&abs(pt->yi-wl->yi)<5) return 1;
	}
	return 0;
}
