基于easyX和vs使用c++绘制坐标系以及实时显示

由于现在在windows下用c语言写一些算法,c语言并没有自己的图形界面库,所以在调试的时候很不方便。相信很多使用c语言开发的朋友都会为此而苦恼。所以最近我基于easyX写了一个实时绘制数据的程序,希望可以给大家一些帮助。

easyX是一个c++的图形库,只能在windows上使用,而且一般只能在vs或者vc上面使用(我用的vs),限制条件比较多,如果大家想用,还是老老实实安装软件吧,先装vs,然后安装easyX。easyX安装起来很简单。

先给大家看一下效果:

静态显示(不带网格):

静态显示(带网格,这里网格线将刻度值的负号遮盖了,理解万岁):

动态绘制(无网格):

动态绘制(有网格):

动态绘制时,使用了一个循环队列,然后每一次重新绘制队列中的所有元素

接下来是代码:

先是循环队列的代码:

queue.h

#ifndef _QUEUE_H
#define _QUEUE_H

//循环队列的大小
#define MAXSIZE  1000  

typedef struct queueint {
	int data[MAXSIZE];
	int front, rear;
}QueueInt;

typedef struct queueintfloat {
	float data[MAXSIZE];
	int front, rear;
}QueueFloat;

void queueInitFloat(QueueFloat* queue);

int insertFloat(QueueFloat* queue,float a);

int deleteFloat(QueueFloat* queue);

int getSizeFloat(QueueFloat* queue);

void queueInitInt(QueueInt* queue);

int insertInt(QueueInt* queue, int a);

int deleteInt(QueueInt* queue);

int getSizeInt(QueueInt* queue);


#endif

queue.cpp

#include "queue.h"


void queueInitFloat(QueueFloat* queue) {
	queue->front = 0;
	queue->rear = 0;
	for (int i = 0; i < MAXSIZE; i++)
		queue->data[i] = 0;
}

int insertFloat(QueueFloat* queue, float a) {
	if ((queue->rear + 1)%MAXSIZE==queue->front) {
		return 1;
	}
	queue->data[queue->rear++] = a;
	return 0;
}

int deleteFloat(QueueFloat* queue) {
	if (queue->front == queue->rear) {
		return 1;
	}
	queue->front++;
	return 0;
}

int getSizeFloat(QueueFloat* queue) {
	int res = queue->rear - queue->front;
	if (res < 0) {
		res += MAXSIZE;
	}
	return res;
}

void queueInitInt(QueueInt* queue) {
	queue->front = 0;
	queue->rear = 0;
	for (int i = 0; i < MAXSIZE; i++)
		queue->data[i] = 0;
}

int insertInt(QueueInt* queue, int a) {
	if ((queue->rear + 1) % MAXSIZE == queue->front) {
		return 1;
	}
	queue->data[queue->rear++] = a;
	queue->rear %= MAXSIZE;
	return 0;
}

int deleteInt(QueueInt* queue) {
	if (queue->front == queue->rear) {
		return 1;
	}
	queue->front++;
	queue->front %= MAXSIZE;
	return 0;
}

int getSizeInt(QueueInt* queue) {
	int res = queue->rear - queue->front;
	if (res < 0) {
		res += MAXSIZE;
	}
	return res;
}

然后是坐标系的绘制,以及绘图代码

drawCoordinateSystem.h

#pragma once
#ifndef DrawCoordinateSystem 
#define DrawCoordinateSystem
#include "queue.h"
/*
这是绘制坐标系的函数
1、轴
2、刻度
3、原点
4、网格
5、图幅
6、箭头
*/

//轴结构体
struct Axis {
	int xlow, xhigh;
	int ylow, yhigh;
	int centerx,centery;
	float ax, ay;   //压缩
	int color;
};

//刻度结构体
struct Scale {
	int openflag;  //是否开启
	int scalex;     //刻度大小
	int scaley;
	int color;
};
struct Grid{
	int openflag;
	int color;
};

typedef struct coordinatesystem {
	struct Axis axis;
	struct Scale scale;
	int zerox, zeroy;  //坐标系原点
	struct Grid grid;
	int length, width;  //图幅长宽
	int color;     //背景颜色
	int borderx, brodery; //边界空出的范围
}CoordinateSystem;


void coordinateSystemInit(CoordinateSystem* cs);

void createCS(CoordinateSystem* cs);

void plotInt(CoordinateSystem* cs, int* data, int len, int color);

void plotFloat(CoordinateSystem* cs, float* data, int len, int color);

void dynamicPlotInt(CoordinateSystem* cs,QueueInt* queue,int color);

void addInt(QueueInt* queue,int a);


#endif // !DrawCoordinateSystem 


 

drawCoordinateSystem.cpp

#include "drawCoordinateSystem.h"
#include <easyx.h>			// 引用图形库头文件
#include <Windows.h>
#include <math.h>
#include <stdio.h>
#include "queue.h"


void coordinateSystemInit(CoordinateSystem* cs) {
	//图幅初始化
	cs->length = 1280;
	cs->width = 780;
	//坐标轴初始化
	cs->axis.xhigh = 100;
	cs->axis.xlow = -100;
	cs->axis.yhigh = 100;
	cs->axis.ylow = 0;
	cs->axis.centerx = (cs->axis.xhigh + cs->axis.xlow) / 2;
	cs->axis.centery = (cs->axis.yhigh + cs->axis.ylow) / 2;
	int len1 = cs->axis.xhigh - cs->axis.xlow;
	int len2 = cs->axis.yhigh - cs->axis.ylow;
	cs->axis.ax = cs->length*1.0 / len1;
	cs->axis.ay = cs->width*1.0 / len2;
	cs->axis.color = BLACK;
	//坐标原点初始化
	cs->zerox = 0;
	cs->zeroy = 50;
	//刻度初始化
	cs->scale.openflag = 1;
	cs->scale.scalex = 10;
	cs->scale.scaley = 10;
	cs->scale.color = BLACK;
	//网格初始化
	cs->grid.openflag = 1;
	cs->grid.color = BLACK;
	//边界空出范围
	cs->borderx = 10;
	cs->brodery = 10;
	cs->color = WHITE;
	//创建窗口
	HWND hwnd = initgraph(cs->length + cs->borderx, cs->width + cs->brodery, EW_SHOWCONSOLE);
	setrop2(R2_MASKPEN); //加一个光栅更好看
}

int transX(CoordinateSystem* cs, float x) {
	x -= cs->axis.centerx;
	x *= cs->axis.ax;
	int k = x;
	if (x - k > 0.5)
		k++;
	return k;
}
int transY(CoordinateSystem* cs, float y) {
	y -= cs->axis.centery;
	y *= cs->axis.ay;
	int k = y;
	if (y - k > 0.5)
		k++;
	return k;
}

void createCS(CoordinateSystem* cs) {
	
	//设置原点
	int avex = (cs->length + cs->borderx) / 2;
	int avey = (cs->width + cs->brodery) / 2;
	setorigin(avex, avey);

	//设置缩放与坐标轴方向
	setaspectratio(1,-1); //将y轴翻转为 向上为正

	//设置背景色
	setbkcolor(cs->color);
	cleardevice();
	//绘制坐标轴
	setlinecolor(cs->axis.color); //设置颜色
	setlinestyle(PS_SOLID,3);     //线的样式:实线,宽度
	line(-cs->length/2,0,cs->length/2,0);
	line(transX(cs,cs->zerox),cs->width/2, transX(cs, cs->zerox),-cs->width/2);
	//绘制箭头
	float angle = 15/180.0*3.14159; //箭头角度
	float len3 =20;
	float x11 = cs->zerox*1.0;
	float x12 = cs->zerox*1.0 + len3 * tan(angle)/cs->axis.ax;
	float x13 = cs->zerox*1.0 - len3 * tan(angle) / cs->axis.ax;
	float y11 = cs->axis.yhigh*1.0;
	float y12 = cs->axis.yhigh*1.0 - len3 / cs->axis.ay;
	float y13 = cs->axis.yhigh*1.0 - len3/cs->axis.ay;
	line(transX(cs,x11),cs->width/2,transX(cs, x12 ),cs->width/2-len3);
	line(transX(cs, x11), cs->width / 2, transX(cs, x13), cs->width / 2 - len3);

	float x21 = cs->axis.xhigh;
	float x22 = cs->axis.xhigh - len3 / cs->axis.ax;
	float x23 = cs->axis.xhigh - len3 / cs->axis.ax;
	float y21 = cs->zeroy;
	float y22 = cs->zeroy+len3* tan(angle) / cs->axis.ay;
	float y23 = cs->zeroy - len3 * tan(angle) / cs->axis.ay;
	line(transX(cs, x21), transY(cs, y21), transX(cs, x22), transY(cs, y22));
	line(transX(cs, x21), transY(cs, y21), transX(cs, x23), transY(cs, y23));
	// 绘制刻度
	if (cs->scale.openflag) {
		int len4 = 5;  //刻度的高度
		float rlen = 50 / cs->axis.ax, rwid = 30 / cs->axis.ay; //刻度值长宽
		int bias = 2; //刻度值离坐标轴的距离
		char s[10];
		int i = 0;
		setaspectratio(1, 1); //将y轴翻转为 向上为负
		settextcolor(cs->scale.color); //设置文字颜色
		setbkmode(TRANSPARENT); //背景透明
		while (cs->zerox - i * cs->scale.scalex > cs->axis.xlow) {
			setlinecolor(cs->axis.color); //设置刻度颜色
			setlinestyle(PS_SOLID, 3);     //线的样式:实线,宽度

			line(transX(cs, cs->zerox - i * cs->scale.scalex), transY(cs, cs->zeroy), transX(cs, cs->zerox - i * cs->scale.scalex), transY(cs, cs->zeroy) - len4);
			RECT r = { transX(cs, cs->zerox - i * cs->scale.scalex - rlen / 2), transY(cs, cs->zeroy) + bias,transX(cs, cs->zerox - i * cs->scale.scalex + rlen / 2),transY(cs, cs->zeroy + rwid) + bias };
			sprintf(s, "%d", cs->zerox - i * cs->scale.scalex);
	//		printf("%s\n", s);
			drawtext(s, &r, DT_CENTER | DT_TOP | DT_SINGLELINE);
			//绘制网格
			if (cs->grid.openflag&&i!=0) {
				setlinecolor(cs->grid.color); //设置网格颜色
				setlinestyle(PS_DASH, 1);     //线的样式:虚线,宽度
				line(transX(cs, cs->zerox - i * cs->scale.scalex), transY(cs, cs->axis.ylow), transX(cs, cs->zerox - i * cs->scale.scalex), transY(cs, cs->axis.yhigh));
			}
			i++;
		}
		i = 1;
		while (cs->zerox + i * cs->scale.scalex < cs->axis.xhigh) {
			setlinecolor(cs->axis.color); //设置刻度颜色
			setlinestyle(PS_SOLID, 3);     //线的样式:实线,宽度

			line(transX(cs, cs->zerox + i * cs->scale.scalex), transY(cs, cs->zeroy), transX(cs, cs->zerox + i * cs->scale.scalex), transY(cs, cs->zeroy) - len4);
			RECT r = { transX(cs, cs->zerox + i * cs->scale.scalex - rlen / 2), transY(cs, cs->zeroy) + bias,transX(cs, cs->zerox + i * cs->scale.scalex + rlen / 2),transY(cs, cs->zeroy + rwid) + bias };
			sprintf(s, "%d", cs->zerox + i * cs->scale.scalex);
//			printf("%s\n", s);
			drawtext(s, &r, DT_CENTER | DT_TOP | DT_SINGLELINE);
			//绘制网格
			if (cs->grid.openflag&&i != 0) {
				setlinecolor(cs->grid.color); //设置网格颜色
				setlinestyle(PS_DASH, 1);     //线的样式:虚线,宽度
				line(transX(cs, cs->zerox + i * cs->scale.scalex), transY(cs, cs->axis.ylow), transX(cs, cs->zerox + i * cs->scale.scalex), transY(cs, cs->axis.yhigh));
			}
			i++;
		}
		i = 0;
		while (cs->zeroy - i * cs->scale.scaley > cs->axis.ylow) {
			setlinecolor(cs->axis.color); //设置刻度颜色
			setlinestyle(PS_SOLID, 3);     //线的样式:实线,宽度

			line(transX(cs, cs->zerox), transY(cs, cs->zeroy + i * cs->scale.scaley), transX(cs, cs->zerox) + len4, transY(cs, cs->zeroy + i * cs->scale.scaley));
			RECT r = { transX(cs, cs->zerox - rlen) - bias, transY(cs,cs->zeroy + i * cs->scale.scaley - rwid / 2),transX(cs, cs->zerox) - bias, transY(cs,cs->zeroy + i * cs->scale.scaley + rwid / 2) };
			sprintf(s, "%d", cs->zeroy - i * cs->scale.scaley);
//			printf("%s\n", s);
			drawtext(s, &r, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
			//绘制网格
			if (cs->grid.openflag&&i != 0) {
				setlinecolor(cs->grid.color); //设置网格颜色
				setlinestyle(PS_DASH, 1);     //线的样式:虚线,宽度
				line(transX(cs, cs->axis.xlow), transY(cs, cs->zeroy + i * cs->scale.scaley), transX(cs, cs->axis.xhigh), transY(cs, cs->zeroy + i * cs->scale.scaley));
			}
			i++;
		}
		i = 1;
		while (cs->zeroy + i * cs->scale.scaley < cs->axis.yhigh) {
			setlinecolor(cs->axis.color); //设置刻度颜色
			setlinestyle(PS_SOLID, 3);     //线的样式:实线,宽度

			line(transX(cs, cs->zerox), transY(cs, cs->zeroy - i * cs->scale.scaley), transX(cs, cs->zerox) + len4, transY(cs, cs->zeroy - i * cs->scale.scaley));
			RECT r = { transX(cs, cs->zerox - rlen) - bias, transY(cs,cs->zeroy - i * cs->scale.scaley - rwid / 2),transX(cs, cs->zerox) - bias, transY(cs,cs->zeroy - i * cs->scale.scaley + rwid / 2) };
			sprintf(s, "%d", cs->zeroy + i * cs->scale.scaley);
//			printf("%s\n", s);
			drawtext(s, &r, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
			//绘制网格
			if (cs->grid.openflag&&i != 0) {
				setlinecolor(cs->grid.color); //设置网格颜色
				setlinestyle(PS_DASH, 1);     //线的样式:虚线,宽度
				line(transX(cs, cs->axis.xlow), transY(cs, cs->zeroy - i * cs->scale.scaley), transX(cs, cs->axis.xhigh), transY(cs, cs->zeroy - i * cs->scale.scaley));
			}
			i++;
		}
	}
}

void setRange(CoordinateSystem*cs, int xlow, int xhigh, int ylow, int yhigh) {
	cs->axis.ylow = ylow;
	cs->axis.yhigh = yhigh;
	cs->axis.xlow = xlow;
	cs->axis.xhigh = xhigh;
	cs->axis.centerx = (cs->axis.xlow + cs->axis.xhigh) / 2;
	cs->axis.centery = (cs->axis.ylow + cs->axis.yhigh) / 2;
	int len1 = cs->axis.xhigh - cs->axis.xlow;
	int len2 = cs->axis.yhigh - cs->axis.ylow;
	cs->axis.ax = cs->length*1.0 / len1;
	cs->axis.ay = cs->width*1.0 / len2;
	cs->scale.scalex =(int) (100 / cs->axis.ax)/10*10;
	cs->scale.scaley = (int)(100 / cs->axis.ay) / 10*10;
	if (cs->scale.scalex <= 0)
		cs->scale.scalex=(int)(100 / cs->axis.ax);
	if (cs->scale.scaley <= 0)
		cs->scale.scaley=(int)(100 / cs->axis.ay);
	if (cs->scale.scalex <= 0)
		cs->scale.scalex = 1;
	if (cs->scale.scaley <= 0)
		cs->scale.scaley = 1;
	cs->zerox = 0;
	cs->zeroy = cs->axis.centery;
}

//直接给一组数据,将数据绘制出来
void plotInt(CoordinateSystem* cs, int* data, int len, int color) {
	//找出最大最小值
	int min = data[0];
	int max = data[0];
	for (int i = 1; i < len; i++) {
		if (data[i] > max) {
			max = data[i];
		}
		if (data[i] < min) {
			min = data[i];
		}
	}
	int range = max - min;
	coordinateSystemInit(cs);
	setRange(cs, 0-len*0.1, len*1.1, min-range*0.1, max+range*0.1);
	
	createCS(cs);
	setlinecolor(color);
	setaspectratio(1, -1);
	setlinestyle(PS_SOLID, 2);
	for (int i = 0; i < len - 1; i++) {
		line(transX(cs,i + 1),transY(cs, data[i]),transX(cs, i + 2),transY(cs, data[i + 1]));
	}
	for (int i = 0; i < len; i++) {
		putpixel(transX(cs,i + 1),transY(cs, data[i]),color);
	}
}

//直接给一组数据,将数据绘制出来
void plotFloat(CoordinateSystem* cs, float* data, int len, int color) {
	//找出最大最小值
	float min = data[0];
	float max = data[0];
	for (int i = 1; i < len; i++) {
		if (data[i] > max) {
			max = data[i];
		}
		if (data[i] < min) {
			min = data[i];
		}
	}
	float range = max - min;
	coordinateSystemInit(cs);
	setRange(cs, 0 - len * 0.1, len*1.1, min - range * 0.1, max + range * 0.1);

	createCS(cs);
	setlinecolor(color);
	setaspectratio(1, -1);
	setlinestyle(PS_SOLID, 2);
	for (int i = 0; i < len - 1; i++) {
		line(transX(cs, i + 1), transY(cs, data[i]), transX(cs, i + 2), transY(cs, data[i + 1]));
	}
	for (int i = 0; i < len; i++) {
		putpixel(transX(cs, i + 1), transY(cs, data[i]), color);
	}
	//
}


void dynamicPlotInt(CoordinateSystem* cs, QueueInt* queue, int color) {
	int len = getSizeInt(queue);
	int min, max;
	if (len == 0) {
		min = 0;
		max = 100;
	}else if (len==1) {
		min = queue->data[queue->front] - 10;
		max = queue->data[queue->front] + 10;
	}else {
		int p = (queue->front+1)%MAXSIZE;
		min = queue->data[queue->front];
		max = queue->data[queue->front];
		while (p% MAXSIZE != queue->rear) {
			if (queue->data[p ]>max) {
				max = queue->data[p ];
			}
			if (queue->data[p ] < min) {
				min = queue->data[p ];
			}
			p++;
			p %= MAXSIZE;
		}
	}
	if (min == max) {
		min = min - 10;
		max = max + 10;
	}
	float range = max - min;

//	coordinateSystemInit(cs);
	if (len <= 10) {
		setRange(cs, -10, 10, min - range * 0.1, max + range * 0.1);
	}
	else {
		setRange(cs, 0 - len * 0.1, len*1.1, min - range * 0.1, max + range * 0.1);
	}
	BeginBatchDraw();//开始批量画图
	createCS(cs);

	if (len == 0) {
		EndBatchDraw();
		return;
	}

	setlinecolor(color);
	setaspectratio(1, -1);
	setlinestyle(PS_SOLID, 2);
	int i = 0;
	int k = 0;
	
	for (int p = queue->front; (p+1)%MAXSIZE != queue->rear;p++,p%=MAXSIZE,i++) {
		line(transX(cs, i + 1), transY(cs,queue->data[p]), transX(cs, i + 2), transY(cs, queue->data[(p+1)%MAXSIZE]));
		k++;
		if (k == 10) {
//			FlushBatchDraw();
			k = 0;
		}
	}
	EndBatchDraw();
//	i = 0;
//	for (int p = queue->front; p%MAXSIZE != queue->rear; p++, p %= MAXSIZE, i++) {
//		putpixel(transX(cs, i + 1), transY(cs, queue->data[p]), color);
//	}
//	for (int i = 0; i < len; i++) {
//		putpixel(transX(cs, i + 1), transY(cs, data[i]), color);
//	}
}

void addInt(QueueInt* queue, int a) {
	if (insertInt(queue, a)) {
		deleteInt(queue);
		insertInt(queue, a);
	}
}

最后是绘制代码

绘制静态数据代码:

#include <math.h>
#include <windows.h>
#include <stdio.h>
#include <easyx.h>			// 引用图形库头文件
#include <conio.h>
#include "drawCoordinateSystem.h"
#include "queue.h"


int main() {
	CoordinateSystem cs;
	coordinateSystemInit(&cs);
	float a[1001];
	int j = 0;
	for (float i = 0; i < 2 * 3.14; i += 3.14 / 500) {
		a[j++] = 10 * sin(i);
	}
	plotFloat(&cs, a, 1000, RED);
	getchar();
	return 0;
}

绘制动态数据代码:

#include <math.h>
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <easyx.h>			// 引用图形库头文件
#include <conio.h>
#include "drawCoordinateSystem.h"
#include "queue.h"

void fun(void* p) {
	CoordinateSystem cs;
	coordinateSystemInit(&cs);
	while (1) {
		dynamicPlotInt(&cs,&queue,RED);
		Sleep(20);
	}
	_endthread();
}

int main(){
	queueInitInt(&queue);
	_beginthread(fun, 0, NULL);
	float t = 0;
	getchar();
	while (1) {
		if (int(t+1) % 500 == 0) {
			addInt(&queue, 100 * sin(t / 100));
		}else
			addInt(&queue,100*sin(t/100));
		Sleep(10);
		t++;
		printf("%d\n",getSizeInt(&queue));
	}
	return 0;
}

这里动态绘制只写了绘制int类型的代码,float类型的其实也基本一样,复制一下就好,如果各位有需求,可以自己动手或评论或者私信,我来加上。

猜你喜欢

转载自blog.csdn.net/qq_39545674/article/details/105260116