由于现在在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 // 引用图形库头文件
#include
#include
#include
#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
#include
#include
#include // 引用图形库头文件
#include
#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
#include
#include
#include
#include // 引用图形库头文件
#include
#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类型的其实也基本一样,复制一下就好,如果各位有需求,可以自己动手或评论或者私信,我来加上。