前言
学的东西多了,要想办法用出来.C和C++是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容
引入
图形在底层是怎么表示的,用C++来表示
认识图片
图片是个风景,动物,还是其他内容,人是可以看出来的.那么计算机是怎么看懂的呢?在有自主意识的人工智能被设计出来之前,他是看不懂图片的.他只知道那是一堆点,而且是有顺序的点,这些点有颜色(是黑白两色,或者多少位的颜色看显示器和显卡能否支持)
图片=有顺序的点集合+点的颜色
其中点的颜色可选,就是说如果是白底黑字的图,可以没有颜色.
图片类的分类
一开始不好说能分几类,和创造一个概念一样,需要慢慢摸索.假设图片有下面两种:一个有规则,一个没规则.左边是一个矩形,右边是一个样条曲线画的像"人"字
设计两个类:Reg_pic对应左边图形 ,Unreg_pic对应右边图形.他们的点类型不一样,一个命名为Reg_point,另一个命名为Unreg_point.
//规则点类
struct Reg_point{
short red;
short green;
short blue;
}
//不规则点类
struct Unreg_point{
short x_cord; //x坐标
short y_cord; //y坐标
short red;
short green;
short blue;
}
注意:
在图片设计时有个默认设定,每张图左上角的坐标点作为基点存在,Reg_pic可以通过长度和宽度来描述每个点和基点的相对位置,所以不用再定义x_cord和y_cord的属性
基点存在的意义是什么?前面说了图片里的点有顺序关系在里面,而顺序关系如何表达出来.在规则图类中无需表达(因为这里使用的是实心矩形类),而不规则图类中包含的点坐标,实际上是每个点和基点之间的坐标差值.
Reg_pic的类设计
"规则图"类暂时还是个概念,可以先从矩形实心类开始,给他取个形象的名字Matrix(矩阵类)
Matrix矩阵类
写法一:站在笔者个人角度,不大愿意用双重指针,或者双重容器的写法,所以如下代码
//规则类接口,暂未定义
struct Reg_pic{
};
//矩阵类声明
struct Matrix : public Reg_pic{
short length; //表示长度的点个数,冗余
short height; //表示高度的点个数
vector<Row> rows; //图,height多的行数集合
Matrix(short Length,short Height,Row row)//构造函数
{
for(short i=0;i<height;i++){
rows.push_back(row);
}
}
}
//行类声明
struct Row {
short length; //一行有length多的点组成
short red; //红色值,16位65536色
short green; //绿色值,16位
short blue; //蓝色值,16位
vector<Reg_point> reg_points; //列,点集合
Row(short Length, short Red, short Green, short Blue) //构造函数
{
for (short i = 0; i < length; i++) {
reg_points.push_back(Reg_point{ red,green,blue });
};
}
};
//生成黑色矩阵1000x500像素
int main(void){
Row black_row(1000,0,0,0); //生成1000点长的行(一根黑线1000点组成)
Matrix black_matrix(1000,500,black_row); //生成500高的图(一张图有500根黑线)
}
这种写法意思能把层次表达清楚:即图由行集合组成,行由点集合组成.但是给人有些繁琐的感觉,特别是冗余属性(照理说颜色的几个属性也应该写在Matrix类声明里,这样一眼能看出图想表达什么).所以引出第二种写法.
写法二:很明显矩阵类对象包含的是一个点的二维数组
//更新后的矩阵类声明
struct Matrix : public Reg_pic {
short length; //表示长度的点个数
short height; //表示高度的点个数
short red;
short green;
short blue;
vector<vector<Reg_point>> matrix; //图,点的二维数组
Matrix(short Length, short Height, short Red,
short Green, short Blue) //构造函数
{
vector<Reg_point> tmp; //临时容器
for (short i = 0; i < height; i++)
for (short j = 0; j < length; j++)
{
tmp.push_back(Reg_point{ Red,Green,Blue });
}
matrix.push_back(tmp); //临时容器内容添加到矩阵对象
}
};
//生成黑色矩阵1000x500像素
int main(void) {
Matrix matrix(1000, 500, 0, 0, 0); //一步生成矩阵对象
}
和第一种写法比起来,清爽了许多
一个小问题
如果面向对象理解的比较深,发现一个问题:属性中除了vector<vector<Reg_point>> matrix之外,都可以不要.因为matrix本身就已经包含了矩阵需要的所有元素,其余属性都可以看作冗余属性.
笔者认为这是面向对象的特性,多一点容易理解,不在乎每个对象多10个字节.应用级别的程序毕竟不是机器指令级别或者系统级别的代码,每一个字节或者每条指令周期都想"抠"出来以提高性能(争取把使用存储减少到每个字节,指令周期能少一个就是一个).写代码首先是准确,然后命名优雅,但用不着太拘谨了,开源的精神也在于此.
假设用C语言来定义矩阵类,他是这样写的
//C语言的矩阵类描述
struct Matrix{
short length;
short height;
Reg_point ** rp;
}//算法略
看起来更加清爽.
C++牺牲了一些性能,方便构建大型程序.
============================注意==========================================
本贴是尝试用C++描述数据类,至于应用级别的绘图软件,或许为了追求更好的性能用C语言甚至汇编语言编写的也不一定,特此声明
============================注意==========================================
小结
矩阵类是数据类中最简单的一类,但他是计算机中用得最多的图形.不管是元素,场景(背景),或者硬件,都需要用到矩阵.在桌面端更是屡见不鲜,到处都是方块.
题外话:底层对于理解数据有所帮助
预告
接下来有"非规则图形"的定义
鸣谢
笔者另一篇帖子数据在硬件和软件中的表示-CSDN博客里有求下载链接,如果您感觉有所帮助,请帮忙点击,下载,提高等级