Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
15
Добавлен:
17.04.2013
Размер:
7.59 Кб
Скачать
#include <graphics.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>

// Maximum graphs displayed at one time
#define MAX_GRAPHS		10

// Best grid step
#define BEST_STEP		60

// Number format
#define NUM_FORMAT		"%.1f"

// Axis labels
const char * szXLabel = "w";
const char * szYLabel = "A(w)";

// Our parameters
float T = 0.1;	// time constant
double xsi;		// coefficient

// structure to define a point
typedef struct
{
	float x;
	float y;
} POINT, *LPPOINT;

// Function definition
typedef float (*GRAPHFUNC)(float fArg);

// Our calculation function
float CalcFunction (float fArg)
{
	return (1.0/sqrt( pow(1-pow(T*fArg,2), 2) + 4*pow(xsi*T*fArg,2) ));
}

// Class CGraph - for drawing
class CGraph
{
public:
	void Create (POINT &ptLT, POINT &ptRB, POINT &ptMin, POINT &ptMax);
	void SetFunc (GRAPHFUNC lpFunc);
	void DrawGraph (int iColor);
	void DrawGrid ();

	char * m_szXAxis;
	char * m_szYAxis;

protected:
	int LogicalXToScreenX (float x);
	int LogicalYToScreenY (float y);

protected:
	GRAPHFUNC	m_lpFunc;

	POINT m_ptLeftTop;
	POINT m_ptRightBottom;

	float m_iMinX;
	float m_iMaxX;

	float m_iMinY;
	float m_iMaxY;

	int   m_iGridCoef[3];
	float m_iPropCoef;

	float m_fCorrX;
	float m_fCorrY;

};

void CGraph::Create (POINT &ptLT, POINT &ptRB, POINT &ptMin, POINT &ptMax)
{
	m_ptLeftTop = ptLT;
	m_ptRightBottom = ptRB;

	m_iMinX = ptMin.x;
	m_iMinY = ptMin.y;

	m_iMaxX = ptMax.x;
	m_iMaxY = ptMax.y;

	m_iGridCoef[0]=1;
	m_iGridCoef[1]=2;
	m_iGridCoef[2]=5;

	// Coordinate transformation coefficients
	m_fCorrX = ((float)m_ptRightBottom.x-m_ptLeftTop.x)/(m_iMaxX-m_iMinX);
	m_fCorrY = ((float)m_ptRightBottom.y-m_ptLeftTop.y)/(m_iMaxY-m_iMinY);
}

void CGraph::SetFunc (GRAPHFUNC lpFunc)
{
	m_lpFunc = lpFunc;
}

// Draw graph
void CGraph::DrawGraph (int iColor)
{
	setlinestyle (SOLID_LINE, 0, 1);
	float corrx = ((float)(m_iMaxX-m_iMinX))/(m_ptRightBottom.x-m_ptLeftTop.x);

	float fArg;
	int x, y;

	setcolor (iColor);

	moveto (m_ptLeftTop.x, LogicalYToScreenY(m_lpFunc(m_iMinX)));

	for (x=m_ptLeftTop.x; x<m_ptRightBottom.x; x++) {
		fArg = (x-m_ptLeftTop.x)*corrx + m_iMinX;

		lineto (x, LogicalYToScreenY (m_lpFunc(fArg)) );
	}
}

// Draw coordinate grid
void CGraph::DrawGrid()
{
	float stepx, stepy;

	float c = 1;
	int k=0;
	float delta, mindelta;

	// Select best step on OX direction...
	float cur = c*m_iGridCoef[k]*m_fCorrX;
	mindelta = fabs(BEST_STEP-cur);

	while (1) {
		if (cur>BEST_STEP) {
			if (k>0) k--;
			else c/=10;
		}
		else if (cur<BEST_STEP) {
			if (k<2) k++;
			else c*=10;
		}

		cur = c*m_iGridCoef[k]*m_fCorrX;
		delta = fabs(BEST_STEP-cur);

		if (delta<mindelta)
			mindelta = delta;
		else if (mindelta==delta)
			break;
	}

	stepx = c*m_iGridCoef[k];

	// Select best step on OY direction...
	cur = c*m_iGridCoef[k]*m_fCorrY;
	mindelta = fabs(BEST_STEP-cur);

	while (1) {
		if (cur>BEST_STEP) {
			if (k>0) k--;
			else c/=10;
		}
		else if (cur<BEST_STEP) {
			if (k<2) k++;
			else c*=10;
		}

		cur = c*m_iGridCoef[k]*m_fCorrY;
		delta = fabs(BEST_STEP-cur);

		if (delta<mindelta)
			mindelta = delta;
		else if (mindelta==delta)
			break;
	}

	stepy = c*m_iGridCoef[k];

	// Calculate start and end logical coordinates

	float iStartX, iStartY;
	float iEndX, iEndY;

	iStartX = ((int)(m_iMinX/stepx))*stepx;
	iStartY = ((int)(m_iMinY/stepy))*stepy;

	iEndX = ((int)(m_iMaxX/stepx))*stepx;
	iEndY = ((int)(m_iMaxY/stepy))*stepy;

	float lx, ly;		// Logical coordinates (current)
	int x, y;

	// Draw axises (OY)
	settextstyle(1,0,1);
	if (m_iMinX>=0)
		lx = m_iMinX;
	else if (m_iMinX<0 && m_iMaxX>0)
		lx = 0;
	else
		lx = m_iMaxX;

	setcolor (1);
	setlinestyle (0, 0, 3);
	x = LogicalXToScreenX(lx);
	moveto (x, m_ptRightBottom.y+15);
	lineto (x, m_ptLeftTop.y-15);
	linerel (-3, 10); linerel (6, 0); linerel(-3, -10);
	outtextxy (x+10, m_ptLeftTop.y-20, m_szYAxis);

	// Draw axises (OX)
	if (m_iMinY>=0)
		ly = m_iMinY;
	else if (m_iMinY<0 && m_iMaxY>0)
		ly = 0;
	else
		ly = m_iMaxY;

	setcolor (4);
	y = LogicalYToScreenY(ly);
	moveto (m_ptLeftTop.x-15, y);
	lineto (m_ptRightBottom.x+15, y);
	linerel (-10, -3); linerel (0, 6); linerel(10, -3);
	outtextxy (m_ptRightBottom.x+15-textwidth(m_szXAxis), y, m_szXAxis);

	// Draw bounding rectangle
	setlinestyle(0,0,1);
	setcolor(7);
	rectangle (m_ptLeftTop.x-20, m_ptLeftTop.y-20, m_ptRightBottom.x+20, m_ptRightBottom.y+20);

	char sz[10];

	// Draw grid
	setlinestyle (USERBIT_LINE, 0x5555, 1);
	settextstyle(2,0,2);
	for (lx=iStartX; lx<=iEndX; lx+=stepx) {
		x = LogicalXToScreenX(lx);
		moveto (x, m_ptLeftTop.y);
		lineto (x, m_ptRightBottom.y);
		if (lx!=iStartX && lx!=iEndX) {
			sprintf(sz, NUM_FORMAT, lx);
			outtextxy (x-textwidth(sz)/2, m_ptRightBottom.y, sz);
		}
	}

	for (ly=iStartY; ly<=iEndY; ly+=stepy) {
		y = LogicalYToScreenY(ly);
		moveto (m_ptLeftTop.x, y);
		lineto (m_ptRightBottom.x, y);
		if (ly!=iStartY && ly!=iEndY) {
			sprintf(sz, NUM_FORMAT, ly);
			outtextxy (m_ptLeftTop.x-textwidth(sz), y-textheight(sz)/2, sz);
		}
	}
}


int CGraph::LogicalXToScreenX (float x)
{
	return m_ptLeftTop.x + ( x-m_iMinX )*m_fCorrX;
}

int CGraph::LogicalYToScreenY (float y)
{
	return m_ptRightBottom.y - ( y-m_iMinY )*m_fCorrY;
}

// Class CLegend - draws a legend of a values
class CLegend
{
public:
	void Create (POINT &ptLT, POINT &ptRB);
	void Add (float fVal, int iColor);

protected:
	POINT m_ptLeftTop;
	POINT m_ptRightBottom;

	int m_iLastX;
};

void CLegend::Create(POINT &ptLT, POINT &ptRB)
{
	m_ptLeftTop = ptLT;
	m_ptRightBottom = ptRB;
	m_iLastX = ptLT.x+10;

	setcolor (7);
	rectangle (ptLT.x, ptLT.y, ptRB.x, ptRB.y);
}

void CLegend::Add (float fVal, int iColor)
{
	setcolor(7);
	settextstyle(2,0,2);

	char sz[10];
	sprintf (sz, "ksi=%.2f", fVal);

	rectangle (m_iLastX, m_ptLeftTop.y+10, m_iLastX+10, m_ptLeftTop.y+20);
	setfillstyle (1, iColor);
	bar (m_iLastX+1, m_ptLeftTop.y+11, m_iLastX+9, m_ptLeftTop.y+19);

	outtextxy (m_iLastX+15, m_ptLeftTop.y+10, sz);

	m_iLastX+=64;
}

// Program entry point
void main ()
{
	// Clear screen
	clrscr ();

	// Init graphic mode
	int iDriver = DETECT, iMode, iError;

	// This is a path to BGI driver
	char szDriverPath[] = "D:\\BORLANDC\\BGI";

	initgraph (&iDriver, &iMode, szDriverPath);

	iError = graphresult();

	if (iError!=grOk) {
		// Error initializing graphic mode
		puts ("ERROR: Initializing graphic mode");
		puts ("Unexpected program termination...");
		return;
	}

	// Define points for our graphs
	POINT ptLT = {20, 20};			// Left-Top corner
	POINT ptRB = {619, 420};		// Right-Bottom corner

	POINT ptMin = {0, 0};       	// Minimum values of arg and function
	POINT ptMax = {20, 6};		// Maximum values

	// Define points for our legend
	POINT ptlLT = {0, 450};
	POINT ptlRT = {639, 479};

	// Define one instance of a graph
	CGraph graph;

	// Define one instance of a legend
	CLegend legend;

	graph.Create (ptLT, ptRB, ptMin, ptMax);
	graph.SetFunc (CalcFunction);
	graph.m_szXAxis = (char*)szXLabel;
	graph.m_szYAxis = (char*)szYLabel;
	graph.DrawGrid ();

	legend.Create (ptlLT, ptlRT);

	int i=1;

	// Draw our graphs, changing T...
	for (xsi = 0.1; xsi<=1.0; xsi+=0.1) {
		graph.DrawGraph (i);
		legend.Add (xsi, i++);
	}

	if (!getch()) getch();

	// Exit graphic mode
	closegraph();
}
Соседние файлы в папке 03