二维几何光学模拟

内容目录

项目材料

目录结构

本仿真模拟程序的目录结构如下图所示

├── README.md
├── index.html
└── static
    ├── css
    │   ├── bootstrap.css
    │   ├── bootstrap.css.map
    │   ├── font-awesome.css
    │   ├── font-awesome.min.css
    │   └── style.css
    ├── fonts
    │   ├── FontAwesome.otf
    │   ├── fontawesome-webfont.*
    │   ├── glyphicons-halflings-regular.*
    └── js
        ├── bootstrap.js
        ├── jquery-3.6.0.js
        ├── lens3.js
        ├── light2D3.js
        └── light3.js
  • index.html
    整个仿真模拟的入口文件,用户交互界面
  • README.md
    仿真程序代码的说明文档,即本文件
  • static/
    静态资源目录

    • css/
      样式表目录,存放所有的css样式

      • style.css
        所有自定义的css样式表
    • fonts/
      字体目录,存放所有的网络字体
    • js/
      脚本目录,存放所有的js控制脚本

      • light2D3.js
        整个程序的控制脚本,最核心的代码逻辑
      • lens3.js
        透镜、平面镜等元件类的定义文件
      • light3.js
        光线类的定义文件

外部依赖

  • Bootstrap

    • v3.4.1
    • 简洁、直观、强悍的前端开发框架
    • 包含css样式与js插件
    • 官方中文文档
  • jQuery

    • v3.6.0
    • A fast, small, and feature-rich JavaScript library
    • 包含js脚本
    • 官方API文档
  • Font Awesome

    • v4.7.9
    • An Internet's icon library and toolkit
    • 包含css样式与特殊字体
    • 官方文档

代码说明

HTML

整个index.html主要分为三个部分,即#header#body#footer三个<div>标签,分别容纳页面的页头、主体与页脚。

页头

页头即为页面导航栏部分,由导航头、两个左导航条组成与一个右导航条,导航头显示标题,第一个左导航条是物理系Phylab的跳转网址,第二个左导航条即为程序工具栏页面,右导航条为制作者信息。

控制栏由按钮组组成,其中按钮组的类型包括普通按钮与下拉菜单启动按钮两种,下拉菜单启动按钮后面需要跟上下拉菜单的具体内容。普通按钮用于切换程序状态或触发事件,本程序中,添加光线添加平面镜清空画布
等按钮为触发事件,绘制路径绘制透镜平移、旋转等操作为切换程序状态。下拉菜单启动按钮用于输入初始化参数,其具体内容包括各类输入参数的表单组。

下拉菜单启动按钮等部分的具体实现请参照Bootstrap官网文档

主体

主体即为程序的呈现部分,包括左侧边栏(控制栏)、主显示框两部分。控制栏部分使用nav-pills实现,可以修改已创建的光学对象。主显示框包含显示主程序的<canvas>画布#canvas

页脚

页脚也是一个导航栏,它是程序的状态栏,会显示当前鼠标下的元件信息。

JavaScript

整个light2D3.js主要分为3个部分,包括全局变量定义区、功能函数与事件函数定义区、主程序函数定义区

全局变量定义区

根据 ECMAScript 6 标准,我们不再推荐使用var定义变量,因此,在本文件中,我们一律使用constlet
定义变量。关于这三者的具体区别,可以参考MDN Web Docs

  • 常量部分

    • drawing
      主程序画布#canvasHTMLElement
    • context
      主程序画布的CanvasRenderingContext2D
    • 其余常量分别表示对应id的HTMLElement,请在index.html中查找对应的id
  • 变量部分

    • add_pole
      光线的偏振状态,0为S波,1为P波,默认为S波
    • light_set
      所有光线的集合
    • mirro_set
      所有面镜的集合
    • lens_set
      所有透镜的集合
    • refract_only
      光线的参数,是否只显示折射
    • rotate_ref
      旋转操作的参考点,一个具有xy属性的对象
    • paintset
      在绘制路径模式下的点集,每个元素是一个点对象,对象有xy属性
    • Cpoint
      在绘制弧形模式下的圆心,是一个点对象
    • angle_info
      在绘制弧形模式下的起始与结束角度,是一个对象,有beginend属性
    • is_concave
      在绘制弧形模式下的凹凸性,true指凸透镜,false指凹面镜
    • locp
      各透镜状态下鼠标的点,有paintcirclerect三种属性,这个属性应该可以舍弃,之前的学长应该没有设计好,这个变量之后可以删掉
    • rect_p
      在绘制矩形模式下的第一个点
    • ele_operate
      操作对象,平移与旋转等动作下被操作的元件对象
    • ele
      当前鼠标所指代的元件对象
    • is_**
      各种状态,默认只有is_transfertrue,其他为false,即默认是平移模式

功能函数与事件函数定义区

  • string2RGB(color)
    • color
      颜色字符串,如"#aa759f"
    • return
      返回一个RGB数值的数组
  • dis(p1, p2)
    • p1
      一个点对象
    • p2
      另一个点对象
    • return
      返回两个点之间的距离
  • rgb2rgba(rgb, a)
    • rgb
      一个储存RGB三个数值的数组
    • a
      透明度
    • return
      一个rgba格式的字符串,如"rgba(122,53,200,0.6)"
  • modtheta(x, y, r)
    • x
      一个角度数值(弧度)
    • y
      一个角度数值(弧度)
    • r
      一个角度数值(弧度)
    • return
      (x + r) % y - r
  • Rreflect(t1, t2, pole, n1, n2)
    • t1
      入射角
    • t2
      折射角
    • pole
      偏振方向,同全局变量add_pole
    • n1
      入射空间折射率
    • n2
      折射空间折射率
    • return
      透射系数R
  • Rrefract(t1, t2, pole, n1, n2)
    • t1
      入射角
    • t2
      反射角
    • pole
      偏振方向,同全局变量add_pole
    • n1
      入射空间折射率
    • n2
      反射空间折射率
    • return
      反射系数R
  • *.onclick
    各个按钮点击后程序对应的改变
  • changeStates(obj)
    • obj
      一个HTMLElement,见index.html中该函数的使用
    • obj所代表的状态改为true,其他状态改为false
  • createInput(set, index=set.length-1)
    • set
      一个集合,如mirro_set
    • index
      集合的下标,默认为最后一个元素
    • return
      set中下标为index的元素创建一个属性输入框组

主程序函数定义区

  • canvas.onmousemove
    • 鼠标移动事件函数,该函数是本文件中最复杂最庞大的函数,这也表明了该函数定义的不合理性,但是重新构建事件函数的成本过高,由之后的开发者自己决定是否需要重构。
    • 本函数首先确定鼠标的位置,然后判断当前的状态,如果状态为平移、旋转,则进入if语句的第一个分支。
    • 绘制路径、绘制弧形、绘制矩形、删除四个模式分别对应if语句的剩下四个分支。
    • 每个分支各自定义了该分支下的onmousedownonmouseup事件
    • 对于绘制路径、绘制弧形、绘制矩形以及旋转等操作,均有两次或多次点击操作,这些操作分别在onmousedown事件中有不同的分支语句。
  • mouse_on_ele(loc)
    • loc
      一个点对象,其实就是当前鼠标的位置
    • return
      返回当前鼠标下的元件对象
  • light_on()
    • return
      返回是否有光线在本函数中被操作,如果有则返回true,否则返回false
    • 本函数也非常复杂,是追踪光线的折射与反射行为的函数,每次所有光线遍历一次,检查子光线是否会有折射或反射操作
  • draw_all(context)
    • context
      主画布的CanvasRenderingContext2D对象
    • 在主画布上绘制所有的元件与光线
  • draw_tem(context)
    • context
      主画布的CanvasRenderingContext2D对象
    • 在主画布上绘制所有临时元件,例如正在绘制中的透镜
  • init()
    • 初始化每一条光线
  • main()
    • 主函数,重复运行。每次运行都会清空画布,初始化光线,进行光线追踪,重新绘制元件与光线

light3.jslens3.js定义了光线与各类原件的类

  • Light(begin, rgba, width, length, theta, pole, index)

    • 光线类
    • 成员变量
      • type
        对象类型,light
      • length
        这个属性也没有用到,应该是之前学长定义的冗余的变量,可以删除
      • rgba
        含有四个元素的数组,每个元素为RGBA中的一个数值
      • color
        字符串表示的颜色,如"#34383c"
      • begin
        一个点对象,作为光线的起始点
      • begintheta
        起始点出的出射角度,弧度制
      • index
        当前对象在对应的set中的下标
      • width
        光线的宽度
      • chlidlight
        包含本条光线所有子光线(ChildLight)对象的数组
      • anchor
        一个点对象,是在移动操作中,鼠标在对象上点击的位置
      • transferable
        当前对象是否可平移
      • rotatable
        当前对象是否可旋转
      • info
        控制栏中当前对象的信息的HTMLElement
    • 成员方法
      • addchild(begin, theta, n, rgba, width)
        • begin
          • 一个对象点,子光线的起始点
        • theta
          • 子光线的出射方向
        • n
          • 子光线所在空间的折射率
        • rgba
          一个长度为4的数组,数组中每个数值对应于RGBA值
        • width
          子光线的宽度
        • 为当前光线添加一条新的子光线
      • addchilds(beginset, thetaset, nset, alphaset, widthset)
        • addchild()函数对应,每个参数都是addchild()函数参数的列表形式。只有alphaset不同,alphaset是颜色透明度alpha的列表,alpha为 0~1
          之间的实数。
      • deletechild(i)
        • 删除第i个子光线
      • draw(context)
        • context
          主画布的CanvasRenderingContext2D对象
        • 在画布上绘制当前光线
      • init()
        • 初始化当前光线使得子光线只有一条
      • transfer(x, y)
        • x,y
          沿xy方向平移的距离
        • 平移操作,平移当前光线
      • rotate(theta)
        • theta
          旋转的角度,弧度制
        • 旋转操作,沿起始点旋转theta角度
      • pole_info()
        • return
          当前光线的偏振信息,如"S波"
      • show_info()
        • return
          字符串格式的当前元件的信息
      • attributes_input()
        • return
          返回控制栏中一个元件及其相关属性的输入框组,比panel_body()函数要多一个下拉菜单的包装
      • panel_body()
        • return
          只返回属性的输入框组
  • ChildLight(begin, theta, rgba, n, width, length, pole)

    • 子光线类
    • 成员变量
      • path
        一个包含光线的路径的所有的点对象的数组,
      • end
        该子光线路径上的最后一个端点
      • theta
        初设角度
      • n
        所在空间的折射率
      • length
        没用用到过,看起来也是冗余的变量
      • rgb
        数组表示的颜色值
      • Intensityset
        路径中每条光线所对应的透明度alpha
      • endintersity
        最后一个端点出射的光线透明度alpha
      • widthset
        路径中每条光线所对应的宽度width
      • endwidth
        最后一个端点出射的光线宽度width
      • pole
        光线的偏振性
    • 成员方法
      • draw(context)
        • context
          主画布的CanvasRenderingContext2D对象
        • 在画布上绘制当前子光线
      • addpath(loc)
        • this.path中添加一个点
      • reflect(normal, loc, R)
        • normal
          反射面的法向量角度
        • loc
          反射面上的入射点坐标
        • R
          反射率
        • 根据反射行为添加新的光线路径点、透明度与宽度
      • refract(normal, n2, loc)
        • normal
          折射面的法向量角度
        • n2
          折射面另一侧的折射率
        • loc
          折射面上的入射点坐标
        • 根据折射行为添加新的光线路径点、透明度与宽度
  • Lens(n, index, type, xlist, ylist)

    • 透镜类
    • 成员变量
      • types
        对象类型,lens
      • n
        折射率
      • index
        当前对象在对应的set中的下标
      • color
        字符串表示的颜色,如"rgba(0,255,255,0.5)"
      • xlist
        透镜边界点的x值组成的数组
      • ylist
        透镜边界点的y值组成的数组
      • typeOfLen
        透镜的类型,0,1,2分别表示路径、弧形、矩形绘制的透镜
      • anchor
        一个点对象,是在移动操作中,鼠标在对象上点击的位置
      • transferable
        当前对象是否可平移
      • rotatable
        当前对象是否可旋转
      • info
        控制栏中当前对象的信息的HTMLElement
    • 成员方法
      • buildfacet(xlist, ylist)
        • 利用xlistylist构建透镜
      • buildfacet2(path)
        • 利用path构建透镜
      • buildcircle(xc, yc, r, begin, end, concave, thick, percise)
        • xc, yc
          圆心的坐标
        • r
          圆弧的半径
        • begin, end
          起始角度与结束角度
        • concave
          凹凸性
        • thick
          厚度,只对凹面镜有效
        • percise
          精度,本质上是圆弧的线段个数(圆弧还是由有限数量的线段绘制而成)
      • draw(context)
        • context
          主画布的CanvasRenderingContext2D对象
        • 在画布上绘制当前元件
      • transfer(x, y)
        • x,y
          沿xy方向平移的距离
        • 平移操作,平移当前元件
      • rotate(theta)
        • theta
          旋转的角度,弧度制
        • 旋转操作,沿起始点旋转theta角度
      • checkcross(light)
        • light
          一个ChildLight对象
        • return
          • 一个对象,包括三个属性crosslight与当前透镜的交点,normol:入射面的法向量角度,n:出射空间的折射率
      • show_info()
        • return
          字符串格式的当前元件的信息
      • attributes_input()
        • return
          返回控制栏中一个元件及其相关属性的输入框组,比panel_body()函数要多一个下拉菜单的包装
      • panel_body()
        • return
          只返回属性的输入框组
        • TODO: 矩形元件的输入框组还没有制作完毕
  • Mirros(loc1, loc2, R, index)

    • 平面镜类
    • 成员变量
      • types
        对象类型,mirros
      • loc1, loc2
        平面镜的两个端点
      • R
        反射率
      • index
        当前对象在对应的set中的下标
      • color
        字符串表示的颜色,如"blue"
      • anchor
        一个点对象,是在移动操作中,鼠标在对象上点击的位置
      • transferable
        当前对象是否可平移
      • rotatable
        当前对象是否可旋转
      • info
        控制栏中当前对象的信息的HTMLElement
    • 成员方法
      • draw(context)
        • context
          主画布的CanvasRenderingContext2D对象
        • 在画布上绘制当前元件
      • transfer(x, y)
        • x,y
          沿xy方向平移的距离
        • 平移操作,平移当前元件
      • rotate(theta)
        • theta
          旋转的角度,弧度制
        • 旋转操作,沿起始点旋转theta角度
      • checkcross(light)
        • light
          一个ChildLight对象
        • return
          • 一个对象,包括三个属性crosslight与当前透镜的交点,normol:入射面的法向量角度,n:出射空间的折射率
      • show_info()
        • return
          字符串格式的当前元件的信息
      • attributes_input()
        • return
          返回控制栏中一个元件及其相关属性的输入框组,比panel_body()函数要多一个下拉菜单的包装
      • panel_body()
        • return
          只返回属性的输入框组

留下回复