Qt实战内容的实现功能

Posted 尚墨1111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt实战内容的实现功能相关的知识,希望对你有一定的参考价值。

1.实现button点击按钮切换绘制曲线由:辐射强度、入瞳入射亮度、激光散射截面自由切换
在main_win中新增点击响应函数

|-- 切换绘制 Itensity 曲线图像
    @pyqtSlot()
    def on_action_Itensity_triggered(self):
        # 利用变量 triggle_button 存储选择绘制的曲线类型
        # 1代表点辐射强度曲线,也是默认的曲线

        self.myCanvas.triggle_button = 1
        self.action_Itensity.setEnabled(False)
        self.action_LRCS.setEnabled(True)
        self.action_Irradiance.setEnabled(True)
        self.action_lightModel.setEnabled(False)
        # 将绘图axes中的内容清除
        self.myCanvas.axes.clear()
        # 通过定时器,定时调用绘图函数
        self.myCanvas.display_dynamic()
        # clock=60 ms的方式执行
        app.run(framerate=60)
        
|-- 在myCanvus中绘制曲线中新增判断语句,实现根据响应的按钮绘制相应的曲线
        if self.triggle_button == 3:
            self.timer.timeout.connect(self.update_figure_Irradiance)  # 连接需要动态刷新的方法函数
        elif self.triggle_button == 2:
            self.timer.timeout.connect(self.update_figure_LRCS)
        else:
            self.timer.timeout.connect(self.update_figure_Itensity)

        遇到的问题:定时器刷新不知道连接什么绘制函数,如果在init中调用就会失败,最后统一写在 display_dynamic 函数中

|-- 在myCanvus中增加绘制函数
        def update_figure_Itensity(self):
        def update_figure_LRCS(self):
        def update_figure_Irradiance(self):

2.实现button点击按钮,弹出 Dialog 改变光照模式
备注:By532与 BySun 的区别 只需要修改 light_color是白光还是绿光,以及视角方向,sun_view 还是 target_view

|-- 编写点击响应函数,打开对话框页面 LightDialog

    @pyqtSlot()
    def on_action_lightModel_triggered(self):
        dialog = LightDialog(parent=self)
        dialog.show()

|-- LightDialog中点击确定按钮的事件处理函数

    def accept(self):
        取出复选框中的值,拼成shading,并修改 P_target.shading 的值
        判断语句,根据shading的值不一样,打开光照模式的参数设置 Dialog 

3.实现选择光照模式的 Dialog 参数设置,(光照的颜色,不需要修改),太阳光波长范围设置
FSCookTorrenceBySun: d s f m color_using
FSCookTorrenceBy532: d s f m color_using

    (朗伯模型的能量不守恒)
    FSLambertBy532:d反射率 a环境光强 color_using
    FSLambertBySun:d反射率 a环境光强 color_using

    FSPhoneBy532: d s n(高光模型) color_using
    FSPhoneBySun:d s n(高光模型) color_using

    FSBlinnPhoneBySun:d s n(高光模型) color_using
    FSBlinnPhoneBy532:d s n(高光模型) color_using

    WithoutLight: color_using

|-- 在P_target中新增设置光照模式参数
    d=(0.5, 0.5, 0.5)
    s = (0.9, 0.9, 0.9)
    f = (0.9, 0.9, 0.9)
    m = 0.3
    n = 3.0
    color_using = 1
    light_color = (1.0, 1.0, 1.0)
    environment_a = (0.0, 0.0, 0.0)

|-- 光照模式的参数设置 Dialog 对话框,新增确定按钮的事件处理函数
    获取复选框中的值,并修改P_target中对应的值,关闭页面
    def accept(self):
        if self.comboBox_colorUsing.currentText()=="纹理填充":
            color_using = 1
        else:
            color_using=0

        d = (self.doubleSpinBox_dR.value(),self.doubleSpinBox_dG.value(),self.doubleSpinBox_dB.value())
        s = (self.doubleSpinBox_sR.value(), self.doubleSpinBox_sG.value(), self.doubleSpinBox_sB.value())
        n = self.doubleSpinBox_n.value()
        P_target.d = d
        P_target.s = s
        P_target.n = n
        P_target.color_using = color_using

        init()  # 重置星体
        self.close()

|-- 在accept函数中页面close之后,如果选择的模式时太阳光,设置太阳光波长的对话框
        if P_target.shading=="FSBlinnPhongBySun":
            # 打开太阳光波段设置
            dialog_light = SunDialog(parent=self)
            dialog_light.show()

|-- myMath类中新增 参数E_sun + 根据波长计算太阳辐照度的积分函数
    # 计算太阳辐照度
    def cal(min, max):
        Re = 6378e3  # 地球半径,单位m
        Rs = 6.955e8  # 太阳半径,单位m
        D = 1.4959787e11  # 太阳地球距离

        T = 5800  # 太阳表面温度
        c1 = 3.74e-16
        c2 = 1.4398e-2

        def cal_prefix():
            return Rs ** 2 / ((D - Rs - Re) ** 2)

        def integrand(x):
            return (c1 / x ** 5) * (1 / (np.exp(c2 / (x * T)) - 1))

        return cal_prefix() * quad(integrand, min, max)[0]

    E_sun = cal(0,4000e-9)# 太阳辐射强度 W/m2

|--SunDialog 获取复选框中选择的太阳波长范围,按钮的事件处理函数,修改E_sun
    def accept(self):
        lambda_min = self.doubleSpinBox_min.value()*1e-9
        lambda_max = self.doubleSpinBox_max.value()*1e-9
        myMath.E_sun = myMath.cal(lambda_min,lambda_max)
        #print(lambda_min,lambda_max,myMath.E_sun)

        init()  # 重置星体
        self.close()

4.实现弹出文件选择,导入txt、xml、csv、json 四种文本格式的相机、卫星模型参数导入

|-- 设置函数,根据文件位置和类型将文件中的数据读取出来,函数中分别判断是四种类型中的何种,然后分别实现数据的读取,并将数据存储在一个字典中
    # 导入相机参数文件
    def importCamOrbit(self,file_path,file_type):

    # 导入卫星参数文件
    def importSatOrbit(self,file_path,file_type):
    
|--  页面点击按钮出发函数
    # 导入卫星轨道参数外部文本文件
    @pyqtSlot()
    def on_action_importSatOrbit_triggered(self):
        调用读取函数,返回字典,修改P_target 中对应参数的值

    # 导入相机轨道参数外部文本文件
    @pyqtSlot()
    def on_action_importCamOrbit_triggered(self):
  1. 导入卫星3D模型
    |-- 先将原有的东方红和风云4 导出成npz 格式的 numpy 数据

     mySat = FongYun4()
     xyz = mySat.xyz
     xy_texture = mySat.xy_texture
     tex_index = mySat.tex_index
     normal = mySat.normal
     draw_mode = mySat.draw_mode
    
     np.savez("Dongfanghong.npz", xyz=xyz,xy_texture =xy_texture,
             tex_index =tex_index,normal =normal,draw_mode =draw_mode)
    
     # 加载一次即可
     r = np.load("D:/MyLearning/PyCharm/myQt01/test/FongYun4.npz")
    

    |-- 点击按钮触发槽函数,函数打开ImportModelTypeDialog 对话框

     # 导入卫星3D模型
     @pyqtSlot()
     def on_action_importSatModel_triggered(self):
    
         dialog = ImportModelTypeDialog(parent=self)
         dialog.show()
    

    |-- ImportModelTypeDialog 对话框
    1.确定导入的模型是东方红还是风云4
    myMath 中新增模型类型:modelType = 0 为东方红

     2.P_target 中新增参数
         isImport = False #传递信息,是否导入了模型
         xyz = None
         xy_texture = None
         tex_index = None
         normal = None
         draw_mode = gl.GL_TRIANGLES
    
     3.确定之后选择文件,并将模型中的值赋给 P_target
         def accept(self):
             myMath.modelType = self.comboBox_modelType.currentIndex()
             self.close()
    
             file_path, file_type = QFileDialog.getOpenFileName(self, '选择文件', '', 'Text files (*.npz)')
    
             if file_path == '':
                 pass  # 防止关闭或取消导入关闭所有页面
             else:
                 # 将是否导入模型状态改为true
                 P_target.isImport = True
                 satModel = np.load(file_path)
    
                 if (satModel["draw_mode"] == 7):
                     P_target.draw_mode = gl.GL_QUADS
    
                 if (satModel["draw_mode"] == 4):
                     P_target.draw_mode = gl.GL_TRIANGLES
    
                 P_target.xyz = satModel["xyz"]
                 P_target.xy_texture = satModel["xy_texture"]
                 P_target.tex_index = satModel["tex_index"]
                 P_target.normal = satModel["normal"]
    
                 init()  # 重置星体
                 self.close()
    
     4.sat_target = SatelliteTarget().getClass(P_target)
     初始化创建卫星类实例,SatelliteTarget,根据模型类型,返回类实例
         def getClass(self,paramters):
             if myMath.modelType==0: 
                 return SatelliteTargetDongFH(paramters)
             else:
                 return SatelliteTargetFY(paramters)
         
         class SatelliteTargetFY(myMath.FongYun4):
         class SatelliteTargetDongFH(myMath.Dongfanghong):
    
     5.实例中init函数,新增判断,如果导入了模型,才进行赋值,否则,以默认值
    
         # 有模型文件导入时才赋值
         if(not parameters.isImport):
             pass
         else:
             self.normal = parameters.normal
             self.xyz = parameters.xyz
             self.xy_texture = parameters.xy_texture
             self.tex_index = parameters.tex_index
    

6.导入相机模型
|-- 生成模型
myCam = SatelliteCam(P_cam)
cam_xyz = myCam.xyz
cam_xy_texture = myCam.xy_texture
cam_normal = myCam.normal
cam_texture = myCam.texture
np.savez(“Cam.npz”, cam_xyz=cam_xyz,cam_xy_texture =cam_xy_texture,
cam_normal =cam_normal,cam_texture =cam_texture)

|-- P_cam 中新增参数
    # 构造观测平台3D模型
    xyz = None
    xy_texture = None
    texture = None
    normal = None
    # 新增导入相机模型的参数
    isImport = False  # 传递信息,是否导入了模型

|-- 点击按钮触发槽函数,导入观测平台3D模型
  @pyqtSlot()
  def on_action_importCamModel_triggered(self):

    file_path, file_type = QFileDialog.getOpenFileName(self, '选择文件', '', 'Text files (*.npz)')

    if file_path == '':
        pass  # 防止关闭或取消导入关闭所有页面
    else:
        P_cam.isImport = True
        camModel = np.load(file_path)

        P_cam.xyz = camModel["cam_xyz"]
        P_cam.xy_texture = camModel["cam_xy_texture"]
        P_cam.texture = camModel["cam_texture"]
        P_cam.normal = camModel["cam_normal"]

        init()  # 重置星体

|-- init重置星体 中 sat_cam = SatelliteCam(P_cam),调用类的__init__函数
增加判断,有模型文件导入时才赋值,不然默认值

    if (not parameters.isImport):
        pass
    else:
        self.normal = parameters.normal
        self.xyz = parameters.xyz
        self.xy_texture = parameters.xy_texture
        self.texture = parameters.texture
        print("进入导入模型操作",self.normal)

附录:各光照模式的参数默认初始值

BRDF(双向反射分布函数)   
d:漫反射比例
s:镜面反射比例
f:镜面反射率
m:微平面分布参数
color_using:0-color纯色;1-texture纹理;

FSCookTorrenceBy532
     d=(0.8, 0.8, 0.8),
     s=(0.2, 0.2, 0.2),
     f=(0.9, 0.9, 0.9),
     m=0.3, color_using=0,
     color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
     light_color=(0.0,1.0,0.0))用绿光

FSCookTorrenceBySun
    d=(0.5,0.5,0.5),
    s=(0.9,0.9,0.9),
    f=(0.9,0.9,0.9),
    m=0.3, color_using=0,
    color=(189.0/255, 203.0/255, 216.0/255),
    light_color=(1.0,1.0,1.0)

FSLambertBy532: 

    d=(1.0, 1.0, 1.0),
    a=(0.0, 0.0, 0.0),
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(0.0, 1.0, 0.0)

FSLambertBySun:
d漫反射:表面对入射光的反射为各向同性
    d=(1.0, 1.0, 1.0),
    a=(0.0, 0.0, 0.0),
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(1.0,1.0,1.0)

FSPhongBySun:
    d=(0.5, 0.5, 0.5),
    a=(0.0, 0.0, 0.0),
    s=(0.5, 0.5, 0.5),
    n=3.0,
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(1.0, 1.0, 1.0)

FSPhongBy532:
    d=(0.5, 0.5, 0.5),
    a=(0.0, 0.0, 0.0),
    s=(0.5, 0.5, 0.5),
    n=3.0,
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(0.0, 1.0, 0.0)

FSBlinnPhongBySun:
    d=(0.5, 0.5, 0.5),
    a=(0.0, 0.0, 0.0),
    s=(0.5, 0.5, 0.5),
    n=6.0,
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(1.0, 1.0, 1.0)

FSWithoutLight:
    d=(1.0, 1.0, 1.0),
    a=(0.0, 0.0, 0.0),
    color_using=0,
    color=(189.0 / 255, 203.0 / 255, 216.0 / 255),
    light_color=(1.0, 1.0, 1.0)

BySun
    vec3 l = normalize(sun_direction);
    vec3 v = normalize(view_direction);
    vec3 h = normalize(l+v);
    vec3 n = normalize(0*c*h+v_normal);
    

    vec3 lc = vec3""" + str(light_color) + """;                                   
    vec3 d = vec3"""+str(d)+""";
    vec3 s = vec3"""+str(s)+""";
    vec3 F = vec3"""+str(f)+""";
    F = F + (1-F)*pow((1-dot(h,v)),5);
    float m = """+str(m)+""";
    float pi =3.1415926;
    float dot_nv = dot(n,v);  
    float dot_nh = dot(n,h);  
    float dot_vh = dot(v,h);
    float dot_nl = dot(n,l);                        
    float G = min(1.0,min(2*dot_nh*dot_nv/dot_vh,2*dot_nh*dot_nl/dot_vh));
    float D = (1/m/m/pow(dot_nh,4))*exp((1-1/pow(dot_nh,2))/pow(m,2));
    
    gl_FragColor = vec4(4*c*lc*(d*dot_nl+s*F*D*G/(4*dot_nv))/pi,1.0);

By532
    vec3 v = normalize(view_direction);
    vec3 l = v;
    vec3 h = normalize(l+v);
    vec3 n = normalize(0*c*h+v_normal);
   
    vec3 lc = vec3""" + str(light_color) + """;                                   
    vec3 d = vec3""" + str(d) + """;
    vec3 s = vec3""" + str(s) + """;
    vec3 F = vec3""" + str(f) + """;
    //F = F + (1-F)*pow((1-dot(h,v)),5);
    float m = """ + str(m) + """;
    float pi =3.1415926;
    float dot_nv = dot(n,v);  
    float dot_nh = dot(n,h);  
    float dot_vh = dot(v,h);
    float dot_nl = dot(n,l);                        
    float G = min(1.0,min(2*dot_nh*dot_nv/dot_vh,2*dot_nh*dot_nl/dot_vh));
    float D = (1/m/m/pow(dot_nh,4))*exp((1-1/pow(dot_nh,2))/pow(m,2));
    gl_FragColor = vec4(4*c*lc*(d*dot_nl+s*F*D*G/(4*dot_nv))/pi,1.0); 

选择光照模型:

# Lambert模型:漫反射,表现粗糙表面的光照现象
# Phong模型:光滑物体的镜面发射
# Blin-Phong模型:基于Phone,优于Phone
# CookTorrance模型:真实的漫反射和镜面反射都需要依据材质特征和物体表面微平面特征,
# 光照模型将物体粗糙表面看作由很多微小平面(微平面)组成,每一个微平面都被看作一个
# 理想的镜面反射体,物体表面的粗糙度由微平面斜率的变化来衡量。

以上是关于Qt实战内容的实现功能的主要内容,如果未能解决你的问题,请参考以下文章

Qt实战之酷狗音乐

Qt实战:云曦Convert

QT读取剪切板内容-实现复制粘贴文本和图片

网络协议ARP协议介绍

Python Qt GUI设计:做一款串口调试助手(实战篇—1)

Qt6网络抓包工具项目实战3.2抓包过滤器功能开发