本帖最后由 阿童木 于 2022-7-9 15:17 编辑
zemax自定义面型(userdefinedsurface)
1、寻找模板源代码自定义面型文件一般位于:文档->zemax->DLL->surfaces
自定义面型时,以surface文件夹中的stand源代码作为基础,在该源文件中进行自定义表面的定义。
2、编辑自定义面型以定义biconic zernikepolynomial为例
寻找标准源代码:surface->us_stand.c
首先,在zemax提供的源文件中,已经规定好了两个系统用于读取数据的指针
int __declspec(dllexport)APIENTRY UserDefinedSurface2(USER_DATA *UD, FIXED_DATA2 *FD);
FD指针用于读取源文件规定的相关数据接口
UD用于后续编程时读取所需的面型数据
将自定义面型所需要的参数在源文件中进行定义,这些参数定义为double类
int i, loop;
double alpha, xpower, ypower, t, tp, x, y, z, dz, sag, mx, my;
double CX, CY, KX, KY,X,Y, X2, Y2,X3,Y3,X4,Y4,X5,Y5,X6,Y6,X7,Y7,X8,Y8, temp;
......
switch (FD->type)下的case 0:
根据源文件已有的备注进行对应更改
case 1:
将自定义表面的基本面型的参数添加到此处
switch (FD->numb)
{
case 1:strcpy(UD->string, "Cx");break;
case 2:strcpy(UD->string, "Cy");break;
case 3:strcpy(UD->string, "Kx");break;
case 4:strcpy(UD->string, "Ky");break;
default:
UD->string[0] = '\0';
break;
}
break;
case2:
将自定义表面的高阶面型参数添加到此处,定义方式与case1相同
case3:
计算自定义表面的矢高
利用UD指定矢高的输出接口、利用FD指针获取需要的参数
UD->sag1 = 0.0;
UD->sag2 = 0.0;
CX = FD->param[1];
CY = FD->param[2];
C1 = FD->xdata[1];
C2 = FD->xdata[2];
获得了数据输入端口,指定了结果输出端口,将计算矢高的式子编译进源文件中,这一步注意数据的类别兼容
/*若要用到x^2这类的指数项,预先定义X2=x*x;不然C程序会出现数组数据大小冲突的问题*/
X2 = x * x;
Y2 = y * y;
UD->sag1 = (CX* X2 + CY * Y2) / (1.0+ sqrt(alpha));
case4:
近轴光线追迹,此处追迹一般只考虑基本面型,忽略非球面项
UD->ln = 0.0;
UD->mn = 0.0;
UD->nn = -1.0;
CX = FD->param[1];
CY = FD->param[2];
xpower = (FD->n2 - FD->n1) * CX;
ypower = (FD->n2 - FD->n1) * CY;
if ((UD->n) != 0.0)
{
(UD->l) = (UD->l) / (UD->n);
(UD->m) = (UD->m) / (UD->n);
(UD->l) = (FD->n1 * (UD->l) - (UD->x) * xpower) / (FD->n2);
(UD->m) = (FD->n1 * (UD->m) - (UD->y) * ypower) / (FD->n2);
/* normalize */
(UD->n) = sqrt(1 / (1 + (UD->l) * (UD->l) + (UD->m) * (UD->m)));
/* de-paraxialize */
(UD->l) = (UD->l) * (UD->n);
(UD->m) = (UD->m) * (UD->n);
}
break;
case5:
真实光线追迹,需要我们提供的参数有:面形与光线的交点,方向向量,法向量
具体代码可参考surface 文件夹中各类自定义面型的追迹算法。
case6:
渐变折射率材料才会用到这一case
case7:
初始化面型参数
3、编译DLL文件matlab读取的时DLL文件,需要将我们编写的C++文件编译为DLL文件
注意:zemax以前的面型源文件都是C文件,现在使用C++进行编写后,需要在源文件开头做如下更改
extern "C"
{
int __declspec(dllexport) APIENTRY UserDefinedSurface(USER_DATA*UD, FIXED_DATA* FD);
}
/*添加了extern c 接口*/
int Refract(double thisn, double nextn, double* l, double* m,double* n,double ln, double mn, double nn);
/* a generic Snells law refraction routine */
/*将BOOL注释掉*/
/*BOOL WINAPI DllMain(HANDLE hInst, ULONGul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
} */
接下来进行编译工作:
具体操作参考连接:
https://support.zemax.com/hc/zh-cn/articles/1500005577602-%E5%A6%82%E4%BD%95%E7%BC%96%E8%AF%91%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89DLL
https://support.zemax.com/hc/en-us/articles/1500005577602-How-to-compile-a-User-Defined-DLL
4、将编译好的DLL文件放置到surface文件夹中接下来就能在zemax中愉快地使自己定义的面型啦!