当前位置: 首页 > news >正文

数据类设计_图片类设计之8_自由图形类设计_(前端架构)

前言

        学的东西多了,要想办法用出来.C和C++是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容

引入

        前面的内容都是矩阵图形类,现在讨论自由图形类设计

矩阵图形类和自由图形类的差别

        

        左图为矩阵图形类对象,右图为自由图形类对象.矩阵图形类对象单独占据一个矩形框大小的位置,自由图形类对象是单独图形.在拖动时,左边对象带着矩形框,而右边不用. 

自由图形类定义

        自由图形类和前面的不规则图形类是差不多的,只不过当时举了一个字符的例子,算一个特例,现在让自由图形回到他最初的样子---像素图

//自由图形类(像素图)定义
struct Pixel_pic{
    vector<Pixel_point> pps;    //像素点集合
}

//像素点类型定义
struct Pixel_point{
    short x_cord;
    short y_cord;
    short red;
    short green;
    short blue;
}

         说明:这里的像素点定义和前面的字符定义有所区别,加上了颜色.原因是节省空间.试想有10000个字符,每个字符平均有50个屏幕点,那么节省空间有10000x50x6=300万字节,即3MB,看起来不大但无颜色的更简洁.

多张像素图的混合

        顾名思义,几张图合成一张图,具有层叠效果,区别于矩阵图形类对象.例如上一张图可以看作是"/"和"\"的组合.

        1>形式选择

        前面矩阵图形类采用函数的写法,这里用类的写法.如果采用"数据类"定义的话,如下

//自由图形类(像素图)定义---不好用
struct Pixel_pic{
    vector<Pixel_point> pps;    //像素点集合
    vector<Pixel_pic>   pcs;    //像素图由其他像素图组成
}

        和前面的矩阵类定义比起来,看起来有些别扭,因为矩阵类对象用了散列表,而这里好像也不需要.所以考虑用工具类定义.

        工具类用什么名称呢?前面有提到过类名要使用名词.建议采用generator或者builder,表示"生成器",用Pixel_pic_Builder.

//像素混合器定义
class Pixel_pic_Builder{
    vector<Pixel_pic> pps;
    ...                    //内容暂定
}

        2>混合算法

        笔者尝试了两种方案,也可以作为一种思维的锻炼.

        方案一

                代码思路:

                1)生成的最终对象,仍是Pixel_pic对象,即"原材料"和"产品"都是相同的数据类型

                2) 在一个矩形方框内混合,每加一张图,每加一个点,去遍历之前存在的点,如果没有,则添加,如果有,则修改.

===============================内容分割线↓=================================

                问题:如何确定矩形方框的大小?有一个办法:修改像素图定义如下   

//更新并略过---自由图形类(像素图)定义
struct Pixel_pic{
    vector<Pixel_point> pps;    //像素点集合
    short length;               //图的长度
    short height;               //图的高度
}

          然而这个是无法确定的,因为考虑到直接叠起来的高度比较高,因此略过这一点.

          对于高度的问题,可以固定一个,例如软件里的一个框,让像素图的高度来适应他.

===============================内容分割线↑=================================

//像素混合器定义---不成熟方案
class Pixel_pic_Builder{
    public:    
        //materials原材料像素图集合;result结果像素图
        Pixel_pic build(vector<Pixel_pic> & materials,Pixel_pic& result){
            //遍历原材料像素图集合
            for(msd=materials.begin();msd!=materials.end();msd++){
                //遍历原材料像素图中的点
                for(msdd=(*msd).pps.begin();msdd!=(*msd).pps.end();msdd++){  
                    //遍历结果像素图中的点              
                    for(rtd=result.pps.begin();rtd!=result.pps.end();rtd++){
                         //点已存在   
                         if((*msdd).x_cord==(*rtd).x_cord)&& (*msdd).y_cord==(*rtd).y_cord){                             
                            //颜色覆盖 
                             (*rtd).red=(*msdd).red;
                             (*rtd).green=(*msdd).green;
                             (*rtd).blue=(*msdd).blue;
                         }
                          //否则加上这个点
                         else
                            result.pps.add(Pixel_point{(*msdd).x_cord,(*msdd).y_cord,(*msdd).red,(*msdd).green,(*msdd).blue});
                     }       
                }
            }
        return result;
        }           
}

        说明:遍历图的每一个点,同时遍历已生成的结果图里的点,查询是否有坐标重叠.如果坐标已存在,则用新点颜色覆盖;如果坐标未存在,则在结果中加上这个点.

        这个写法非常复杂,而且时间复杂度达到n的3次方了---有一层是像素图动态数组,不算在内的话,复杂度是n的2次方.如果不是没有其他选择方案,不会被用于工程中.

        方案二

                代码思路:用一个辅助的矩阵类对象.

                1>将像素图混合到矩阵类对象中,并记录图中所有点经过的位置.

                2>重新遍历矩阵类对象,取出其中经过位置的点组成像素图.

        1.定义一个辅助矩阵类

//辅助矩阵点定义
struct Assistant_point{
    bool is_choosed;
    short red;
    short green;
    short blue;
}

//辅助矩阵类定义
struct Assistant_matrix{
    short length;
    short height;
    vector<vector<Assistant_point>> aps;
}

                为了让程序清晰,不把所有像素图放一起,而是采用每一张都和矩阵类对象混合.引用上面的工具类来做这件事:

        2.将像素图写入辅助矩阵类对象

//像素混合器定义
class Pixel_pic_Builder{
    public:
        Assistant_matrix & build_in(short x_ref,short y_ref,Assistant_matrix & ax,Pixel_pic & source){    
            //辅助矩阵类对象的初始行指针,定位到被放入像素图的基点位置
            auto axd=ax.aps.begin()+x_ref;
            //遍历像素图
            for(pcd=source.pps.begin();pcd!=source.pps.end();pcd++){
                axd=axd+(*pcd).x_cord;                    //行指针偏移
                //*axd表示得到该行,行仍然是一个vector对象,所以调用begin()基点位置,并计算坐标
                auto axdd=(*axd).begin()+y_ref+(*pcd).y_cord; 
                (*axdd).red=(*pcd).red;
                (*axdd).green=(*pcd).green;        
                (*axdd).blue=(*pcd).blue;   
                (*axdd).is_choosed=true;                   //该点已被选中
            }
        //返回辅助矩阵类对象
        return ax;                                        
        }

}

上面混合了一张图,按照这方法并可以把所有需要混合的图都写入辅助矩阵类对象.

        3.将想要得到的Pixel_pic对象从辅助矩阵类对象中抽出来

        本来可以用前面的build_in函数写在一起,为了看得清楚一些,分成了两个程序来写.

//像素混合器定义---有问题不能用
class Pixel_pic_Builder{
    public:
        Pixel_pic & build_out(Assistant_matrix & ax){ 
            //生成一个空的对象表示结果
            Pixel_pic result();   
            for (short i = 0; i <ax.height; i++)
                for (short j = 0; j <ax.length; j++){
                    //如果显示被标记
                    if(ax[i][j].is_choosed){
                        result.pps.push_back(Pixel_point{i,j,ax[i][j].red,ax[i][j].green,ax[i][j].blue});
                    }    
                }

            }
        return result;
        }
}

        这里没有用二维数组的两次vector遍历,用了C语言一样的[][]来表示元素,意思是一样的.如果不成功,可以改成迭代器遍历.

更新

        果然上面代码有点问题,修改如下:

   Pixel_pic& build_out(Assistant_matrix& ax) {
        //生成一个空的对象表示结果
        Pixel_pic result;
        short i = 0,j=0;
        for ( auto axd=ax.aps.begin() ; axd!=ax.aps.end();axd++,i++)
            for (auto axdd = (*axd).begin(); axdd != (*axd).end(); j++) {
                //如果显示被标记
                if ((*axdd).is_choosed) {
                    result.pps.push_back(Pixel_point{ i,j,(*axdd).red,(*axdd).green,(*axdd).blue });
                }
            }
        return result;
    }

        现在可以得到一个以辅助矩阵类对象基点作为基点的像素混合图

问题

        代码里有个问题,辅助矩阵类对象的长和高,像素图的长和高,没有表示.怎么解决?

        1.不解决

        假设辅助矩阵是在ps软件中的画布,给他固定一个尺寸,然后规定像素图的长和高比他小才能用

        2.部分解决

        给像素图设置两个属性,即修改定义如下:        

//自由图形类(像素图)定义
struct Pixel_pic{
    short height;
    short length;
    vector<Pixel_point> pps;    //像素点集合
}

        再写个算法,像素图超过尺寸后截取图像,规定尺寸小于矩阵对象才能混合.

        这样做可能还会有问题.因为限制了图形尺寸功能差许多.

        还可以想到的解决方法:把源像素图放到另一个场景中,根据情况从另一个场景写到当前画布来.

        重申:毕竟是为了开拓思路而写的帖子,不是真正开发个ps软件,写工程级别代码遇到什么问题再说.

小结

        自由图形类的混合算法,从中可以看出解决问题有多种方案,从中选择适当的使用.

        每个类型设计中,属性定义很重要;不过也不要太纠结,想到什么都给他写上去也不会错.

相关文章:

  • 云资源开发学习应用场景指南,场景 1 云上编程实践平台
  • 【Linux网络(五)】传输层协议
  • 说说MyBatis一、二级缓存和Spring一二级缓存有什么关系?
  • Vue Router动态改变路由参数的两种方法
  • 装饰器模式介绍和典型实现
  • k8s常用命令
  • js的闭包
  • linux 运行脚本命令区别
  • Pinecone数据库介绍、Milvus数据库介绍
  • 基于FastAPI与Kimi AI的智能聊天应用开发实践
  • 6. 使用VUE实现前端页面的分级嵌套
  • Spring Boot集成阿里云OSS:对象存储实战指南
  • 【学习】数字经济下数据价值化的内在逻辑与关键挑战
  • Vue的实例
  • SpringBoot整合Log4j2进行日志记录异步写入日志文件
  • 《深度剖析Android 12 SystemUI锁屏通知布局亮屏流程:从源码到实现》
  • 0323-B树、B+树
  • Mybatis-plus配置动态多数据源
  • Linux系统之yum本地仓库创建
  • EMC知识学习一
  • 网站谷歌地图提交/电商代运营一般收多少服务费
  • 西宁建设工程官方网站/seo权重优化
  • 穹拓做网站/软件推广的渠道是哪里找的
  • 网站关键字及说明/厦门人才网唯一官网
  • 简约大方网站/自建网站平台有哪些
  • 校园网站首页模板/如何提高自己的营销能力