// Connection.cpp: implementation of the CConnection class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Exp10.h"
#include "Connection.h"
// -- Exp10 (start)
#include <math.h>	// rqd. since DrawArrowHead() uses math fns.
// -- Exp10 (end)

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CConnection::CConnection()
{

}

CConnection::~CConnection()
{

}

CConnection::CConnection(CPoint ptFrom, CPoint ptTo)
{
	// Init of member vars.
	m_ptFrom = ptFrom;
	m_ptTo = ptTo;
}

void CConnection::DrawConnection(CDC *pDC)
{
	// Draw a line from the m_ptFrom pt. to the m_ptTo pt.
	pDC->MoveTo(m_ptFrom);
	pDC->LineTo(m_ptTo);

	// Draw arrow head
	DrawArrowHead(pDC);
}

void CConnection::DrawArrowHead(CDC *pDC)
{
	// Init.
	int block_width;	// width of an imaginary block from which length is derived.
	double d;			// opp. side length of subtriangle with hypotenuse h and base side length length/2.
	double h;			// hypotenuse of subtriangle with opp. side length d and base side length length/2.
	double length;		// a fraction of the block width, e.g. length = 0.1*BLOCK_WIDTH;
	double length_u;	// length of vector u
	double length_v;	// length of vector v
	double theta;		// angle of ith body rotated positively clockwise w.r.t. the global screen coord sys. X axis.
	double u[2];		// one of two vectors used to determined angle theta
	double v[2];		// one of two vectors used to determined angle theta: the unit vector [1,0]
	CBrush *pBrush;		// a ptr to brush
	CPoint A;			// vertex in anticlock direc from pointing vertex B of arrow head
	CPoint B;			// vertex of arrow head pointing in direc of arrow (m_ptTo)
	CPoint C;			// vertex in clock direc from pointing vertex B of arrow head
	CPoint vertices[3];	// vertices array to hold triangle vertices
	CString sMsg;		// main msg string
	UINT nType = MB_OK;	// style of msg. box
	UINT nIDhelp = 0;	// help context ID for the msg: 0 indicates the app's default help context will be used

	// Assign lengths to arrow head (triangle) paras.
	block_width = 50;
	length = 0.2*block_width;
	d = 0.2887*length;
	h = 0.5773*length;

	// Print msg.
	sMsg.Format("\n CConnection::DrawArrowHead(), d = %lf, h = %lf\n", d, h);
	//AfxMessageBox(sMsg, nType, nIDhelp);

	// Length of vecs u and v
	v[0] = 1.0;						// x cmpt. of unit vector [1,0]
	v[1] = 0.0;						// y cmpt. of unit vector [1,0]
	u[0] = m_ptTo.x - m_ptFrom.x;	// length in x direc of connection vector
	u[1] = m_ptTo.y - m_ptFrom.y;	// length in y direc of connection vector

	length_u = sqrt(pow(u[0],2) + pow(u[1],2));
	length_v = sqrt(pow(v[0],2) + pow(v[1],2));

	// Angle between vecs u and v
	theta = acos((u[0]*v[0] + u[1]*v[1])/(length_u*length_v));
	if(u[1] < 0)
	{
		theta = -theta;	// negate theta if y-cmpt of u < 0, since acos result is an element from [0,pi] radians ONLY (non-neg).
	}

	// Global position vecs of arrow head triangle vertices
	A.x = m_ptTo.x + long(cos(theta)*(-(h+d)) - sin(theta)*(-length*0.5));
	A.y = m_ptTo.y + long(sin(theta)*(-(h+d)) + cos(theta)*(-length*0.5));
	
	B.x = m_ptTo.x;
	B.y = m_ptTo.y;

	C.x = m_ptTo.x + long(cos(theta)*(-(h+d)) - sin(theta)*(length*0.5));
	C.y = m_ptTo.y + long(sin(theta)*(-(h+d)) + cos(theta)*(length*0.5));

	// Draw arrow head
	pDC->MoveTo(A);
	pDC->LineTo(B);
	pDC->LineTo(C);
	pDC->LineTo(A);

	// Prepare for filling the polygon
	CBrush NewBrush(RGB(0,0,0));	// create a new brush
	
	vertices[0] = A;
	vertices[1] = B;
	vertices[2] = C;

	// Select the new brush
	pBrush = pDC->SelectObject(&NewBrush);

	// Fill the polygon
	pDC->Polygon(vertices, 3);

	// Select the old brush
	pDC->SelectObject(pBrush);
}
