zemax光学设计笔记[5]-ZPL或ZOS-API的简单使用

zemax的编程功能简介

An application programming interface (ZOS-API) has been developed for OpticStudio that enables connections to, and customization of, the application using the latest software technology. While ZOS-API relies on a COM interface, it is rooted in .NET libraries, and as such programming with the API can be done using either C++ (COM) or C# (.NET) – depending on the user’s comfort with either language.


可以直接使用ZPL宏(Zemax Programming Language)在ZEMAX内编程,也可以使用提供的ZOS-API在外部编程然后连接进入ZEMAX,其有如下四种方式:

  • 独立应用程序模式Standalone Mode
  • 自定义扩展模式User Extensions Mode
  • 自定义操作数模式User Operands Mode
  • 自定义分析模式User Analysis Mode
    支持的语言有:ZPL,C#,C++,MATLAB,Python。

ZPL快速使用

ZPL与BASIC语言类似,表达式之前不需要声明变量.表达式结尾不需要 特殊终止符(如 C 语言中的“;”)。因此,每条 ZPL 命令必须独占一行。ZPL内置示例文件:

编程->新建宏

x=5
PRINT "Hello ZPL编程,x=",x

然后另存为到~/Zemax/Macros/hello_zpl.ZPL,编程->编辑/执行选择刚才的文件执行.

ZOS-API快速使用

本文主要关注ZOS-API与C++的协作

连接ZOS-API

有两种不同方法连接到ZOS-API

  1. 用户的应用程序是“独立”的,并且将在执行期间启动ZemaxOpticStudio。
  2. Zemax OpticStudio 已经在运行,并且将“调用”用户的(“固有”)应用程序。

固有应用程序(ZOS Inherent(ZOS uses your Application))

  • 自定义扩展 User Extension
  • 自定义分析 User Analyses
  • 自定义操作数 User Operand
    这些均被视为“固有”程序,表示 ZOS 使用已编译的应用程序。

(不用看)配置Visual Studio Code编译C++并连接到ZOS-API(其实VSCODE不能用sln解决方案文件,这个是ZEMAX傲娇了,还是需要安装Visual Studio😭)

正确的操作是, ZOSAPI.dll 和 ZOSAPI_Interfaces.dll 必须保留在 OpticStudio 安装目录中。另一方面, ZOSAPI_NetHelper.dll 应始终位于运行应用程序的目录中。这意味着,如果您在开发自定义 分析、自定义操作数或自定义扩展程序,ZOSAP I_NetHelper.dll 应该与您的插件一起复制到 合适的位置。

Visual Studio Code安装C/C++(Microsoft),C/C++ Compile Run(danielpinto8zz6),Code Runner(Jun Han)三个插件
文件->首选项->设置搜索runInTerminal,勾选C-cpp-compile-run:Run-in-external-terminal和Code-runner:Run-In Terminal
安装MinGW-w64,看到

即安装成功,然后重启VS Code
新建文件hello.cpp

#include <iostream>
int main(void){
std::cout<<"hello world";
}

信任此工作区
右键,点击Run Code

(不用看)配置Code Runner插件的编译选项,连接ZOSAPI.dll,ZOSAPI_interfaces.dll和ZOSAPI_NetHelper.dll

上面几个dll文件可以用系统搜索寻找
同目录下新建.code-workspace

{
	"folders": [
		{
			"path": "."
		}
	],
	"settings": {
		"code-runner.executorMap": {
			"cpp": "cd $dir && gcc -std=c++20 -ld D:\\Zemax OpticStudio\\ZOSAPI.dll -ld D:\\Zemax OpticStudio\\ZOSAPI_interface.dll -ld C:\\Users\\mac\\Documents\\Zemax\\ZOS-API Projects\\CppStandaloneApplication\\CppStandaloneApplication\\ZOSAPI_NetHelper.dll -o .\\bin\\$fileNameWithoutExt.exe && .\\bin\\$fileNameWithoutExt.exe"
		},
		"files.associations": {
			"ostream": "cpp"
		}
	}
}
TLB文件

tlb文件是一个说明文件,通过TLB文件,用户可以得知你的DLL中的COM接口以及常量等信息。其可以单独发行,也可以作为组建DLL中的一个资源随组件一起发行。你可以在VS的Object Browser中看到该文件中包括哪些常数、接口、类,而每个类又包括什么方法和属性。微软提供的各种SDK中通常包括一个或数个TLB文件以方便编程。

安装Visual Studio 2022 Community

[https://blog.csdn.net/candy5204/article/details/124950279]
下载地址
下载下来的是一个下载器
安装过程:下载器->安装器

以下是用Visual Studio实现的

Zemax中编程->C++->独立应用程序
会自动打开一个项目目录,进入CppStandaloneApplicatioin,复制ZOSAPI_NetHelper.dll文件到代码文件夹,
同目录下已经存在zosapi.h文件

CppStandaloneApplication.cpp

// CppStandaloneApplication.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <ctime>
#include <functional>
#include <assert.h>

// Note - .tlh files will be generated from the .tlb files (above) once the project is compiled.
// Visual Studio will incorrectly continue to report IntelliSense error messages however until it is restarted.
#include "zosapi.h"

using namespace std;
using namespace ZOSAPI;
using namespace ZOSAPI_Interfaces;

void handleError(std::string msg);
void logInfo(std::string msg);
void finishStandaloneApplication(IZOSAPI_ApplicationPtr TheApplication);
int main(void) {
    std::cout << "ok!\n";
}
int RunApplication()
{
    CoInitialize(NULL);

    // Create the initial connection class
    IZOSAPI_ConnectionPtr TheConnection(__uuidof(ZOSAPI_Connection));


    // Attempt to create a Standalone connection
    IZOSAPI_ApplicationPtr TheApplication = TheConnection->CreateNewApplication();
    if (TheApplication == nullptr)
    {
        handleError("An unknown error occurred!");
        return -1;
    }

    // Check the connection status
    if (!TheApplication->IsValidLicenseForAPI)
    {
        handleError("License check failed!");
        return -1;
    }
    if (TheApplication->Mode != ZOSAPI_Mode::ZOSAPI_Mode_Server)
    {
        handleError("Standlone application was started in the incorrect mode!");
        return -1;
    }

    IOpticalSystemPtr TheSystem = TheApplication->PrimarySystem;

    // Add your custom code here...

    // creates a new API directory
    CreateDirectory(_bstr_t(TheApplication->SamplesDir + "\\API"), NULL);
    CreateDirectory(_bstr_t(TheApplication->SamplesDir + "\\API\\CPP"), NULL);

    // Set up primary optical system
    _bstr_t sampleDir = TheApplication->SamplesDir;
    _bstr_t testFile = sampleDir + (_bstr_t)"\\API\\CPP\\e01_new_file_and_quickfocus.zmx";

    // Make new file
    TheSystem->New(false);
    TheSystem->SaveAs(testFile);

    ISDMaterialCatalogDataPtr(TheSystem->SystemData->MaterialCatalogs)->AddCatalog("SCHOTT");

    // Aperture
    ISystemDataPtr TheSystemData = TheSystem->SystemData;
    TheSystemData->Aperture->ApertureValue = 40;

    // Fields
    IFieldPtr Field_1 = TheSystemData->Fields->GetField(1);
    IFieldPtr NewField_2 = TheSystemData->Fields->AddField(0, 5.0, 1.0);

    // Wavelength preset
    bool slPreset = TheSystemData->Wavelengths->SelectWavelengthPreset(WavelengthPreset_d_0p587);

    // Lens data 
    ILensDataEditorPtr TheLDE = TheSystem->LDE;
    TheLDE->InsertNewSurfaceAt(2);
    TheLDE->InsertNewSurfaceAt(2);
    ILDERowPtr Surface_1 = TheLDE->GetSurfaceAt(1);
    ILDERowPtr Surface_2 = TheLDE->GetSurfaceAt(2);
    ILDERowPtr Surface_3 = TheLDE->GetSurfaceAt(3);

    // Changes surface cells in LDE
    Surface_1->Thickness = 50.0;
    Surface_1->Comment = "Stop is free to move";
    Surface_2->Radius = 100.0;
    Surface_2->Thickness = 10.0;
    Surface_2->Comment = "front of lens";
    Surface_2->Material = "N-BK7";
    Surface_3->Comment = "rear of lens";

    // Solver
    ISolveDataPtr Solver = Surface_3->RadiusCell->CreateSolveType(SolveType_FNumber);
    Solver->_S_FNumber->FNumber = 10;
    Surface_3->RadiusCell->SetSolveData(Solver);

    // QuickFocus
    IQuickFocusPtr quickFocus = TheSystem->Tools->OpenQuickFocus();
    quickFocus->Criterion = QuickFocusCriterion_SpotSizeRadial;
    quickFocus->UseCentroid = true;
    ISystemToolPtr baseTool = quickFocus;
    baseTool->RunAndWaitForCompletion();
    baseTool->Close();

    // Save and close
    TheSystem->Save();

    // Clean up
    finishStandaloneApplication(TheApplication);

    return 0;
}

void handleError(std::string msg)
{
    throw new exception(msg.c_str());
}

void logInfo(std::string msg)
{
    printf("%s", msg.c_str());
}

void finishStandaloneApplication(IZOSAPI_ApplicationPtr TheApplication)
{
    // Note - TheApplication will close automatically when this application exits, so this isn't strictly necessary in most cases
    if (TheApplication != nullptr)
    {
        TheApplication->CloseApplication();
    }
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    return RunApplication();
}

int _tmain(int argc, _TCHAR* argv[])
{
    return RunApplication();
}


然后运行

可以设置简单的序列系统,然后使用快速聚焦工具使像面聚焦,并将系统另存为: “e01_new_file_and_quickfocus.zmx”,保存在 Documents\Zemax\Samples\API\CPP.

C++使用ZOS-API与ZEMAX交互

示例文件在:编程->ZOS-API帮助->ZOS-API语法帮助->查看更多示例
zemax新建一个简单序列系统

优化->快速聚焦

保存文件到~\Documents\Zemax\Samples\API\CPP\e01_new_file_and_quickfocus.zmx

编程->C++->独立应用程序
会自动打开VS编辑器,cpp文件中

//大概第50行
// Add your custom code here...
// creates a new API directory

CreateDirectory(_bstr_t(TheApplication->SamplesDir + "\\API"), NULL);

CreateDirectory(_bstr_t(TheApplication->SamplesDir + "\\API\\CPP"), NULL);

 

// Set up primary optical system

_bstr_t sampleDir = TheApplication->SamplesDir;

_bstr_t testFile = sampleDir + (_bstr_t)"\\API\\CPP\\e01_new_file_and_quickfocus.zmx";

 

// Make new file

TheSystem->New(false);

TheSystem->SaveAs(testFile);

 

ISDMaterialCatalogDataPtr(TheSystem->SystemData->MaterialCatalogs)->AddCatalog("SCHOTT");

 

// Aperture

ISystemDataPtr TheSystemData = TheSystem->SystemData;

TheSystemData->Aperture->ApertureValue = 40;

 

// Fields

IFieldPtr Field_1 = TheSystemData->Fields->GetField(1);

IFieldPtr NewField_2 = TheSystemData->Fields->AddField(0, 5.0, 1.0);

 

// Wavelength preset

bool slPreset = TheSystemData->Wavelengths->SelectWavelengthPreset(WavelengthPreset_d_0p587);

 

// Lens data

ILensDataEditorPtr TheLDE = TheSystem->LDE;

TheLDE->InsertNewSurfaceAt(2);

TheLDE->InsertNewSurfaceAt(2);

ILDERowPtr Surface_1 = TheLDE->GetSurfaceAt(1);

ILDERowPtr Surface_2 = TheLDE->GetSurfaceAt(2);

ILDERowPtr Surface_3 = TheLDE->GetSurfaceAt(3);

 

// Changes surface cells in LDE

Surface_1->Thickness = 50.0;

Surface_1->Comment = "Stop is free to move";

Surface_2->Radius = 100.0;

Surface_2->Thickness = 10.0;

Surface_2->Comment = "front of lens";

Surface_2->Material = "N-BK7";

Surface_3->Comment = "rear of lens";

 

// Solver

ISolveDataPtr Solver = Surface_3->RadiusCell->CreateSolveType(SolveType_FNumber);

Solver->_S_FNumber->FNumber = 10;

Surface_3->RadiusCell->SetSolveData(Solver);

 

// QuickFocus

IQuickFocusPtr quickFocus = TheSystem->Tools->OpenQuickFocus();

quickFocus->Criterion = QuickFocusCriterion_SpotSizeRadial;

quickFocus->UseCentroid = true;

ISystemToolPtr baseTool = quickFocus;

baseTool->RunAndWaitForCompletion();

baseTool->Close();

 

// Save and close

TheSystem->Save();

编译执行

然后查看~\Documents\Zemax\Samples\API\CPP\e01_new_file_and_quickfocus.ZDA文件,可以看到代码执行效果

😏

posted @ 2022-08-17 02:26  qsBye  阅读(2084)  评论(0编辑  收藏  举报