    

 ## On this page

  

 

 # Example 15 - C++ 

 Last update: 17.07.2025 

# <a class="anchor" id="ex15_s2"></a>C++

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

 

\#include "stdafx.h"

\#include &lt;stdlib.h&gt;

\#include &lt;stdio.h&gt;

\#include &lt;iostream&gt;

\#include &lt;string&gt;

\#include &lt;ctime&gt;

\#include &lt;functional&gt;

\#include &lt;assert.h&gt;

 

// removes warning for using getenv function

\#pragma warning(disable:4996)

 

// 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](namespace_z_o_s_a_p_i.xhtml);

using namespace ZOSAPI_Interfaces;

 

void handleError(std::string msg);

void logInfo(std::string msg);

void finishStandaloneApplication(IZOSAPI_ApplicationPtr TheApplication);

 

int RunApplication()

{

\#if !\_WIN64

 int msgboxID = MessageBox(

 NULL,

 (LPCWSTR)L"This example needs to be run as a x64 configuration. Wizards are not supported via COM in 32-bit mode.",

 (LPCWSTR)L"ZOS-API Error",

 MB_ICONERROR | MB_OK

 );

 return 0;

\#endif

 CoInitialize(NULL);

 

 // Create the initial connection class

 IZOSAPI_ConnectionPtr TheConnection(__uuidof([ZOSAPI\_Connection](class_z_o_s_a_p_i_1_1_z_o_s_a_p_i___connection.xhtml)));

 

 

 // Attempt to create a Standalone connection

 IZOSAPI_ApplicationPtr TheApplication = TheConnection-&gt;CreateNewApplication();

 if (TheApplication == nullptr)

 {

 handleError("An unknown error occurred!");

 return -1;

 }

 

 // Check the connection status

 if (!TheApplication-&gt;IsValidLicenseForAPI)

 {

 handleError("License check failed!");

 return -1;

 }

 if (TheApplication-&gt;Mode != ZOSAPI_Mode::ZOSAPI_Mode_Server)

 {

 handleError("Standlone application was started in the incorrect mode!");

 return -1;

 }

 

 IOpticalSystemPtr TheSystem = TheApplication-&gt;PrimarySystem;

 

 // creates a new API directory

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

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

 

 // Load a double gauss design sample file

 TheSystem-&gt;LoadFile(_bstr_t(TheApplication-&gt;SamplesDir + "\\\\Short course\\\\Optical System Design Using OpticStudio\\\\sc\_dbga1.zos"), false);

 cout &lt;&lt; "Double Gauss Design:" &lt;&lt; endl;

 

 // Define path locations

 _bstr_t SamplesFolder = TheApplication-&gt;SamplesDir;

 _bstr_t SampleFile = TheApplication-&gt;SamplesDir + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization\\\\OptimizedFile.zos";

 CreateDirectory(_bstr_t(TheApplication-&gt;SamplesDir + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization"), NULL);

 TheSystem-&gt;SaveAs(SampleFile);

 

 // Define System Explorer

 // Define Aperture

 ISystemDataPtr SystExplorer = TheSystem-&gt;SystemData;

 SystExplorer-&gt;Aperture-&gt;ApertureType = ZemaxApertureType::ZemaxApertureType_EntrancePupilDiameter;

 SystExplorer-&gt;Aperture-&gt;ApertureValue = 20;

 

 // Add 3 fields

 IFieldPtr Field_1 = SystExplorer-&gt;Fields-&gt;GetField(1);

 IFieldPtr NewField_2 = SystExplorer-&gt;Fields-&gt;AddField(0, 5.0, 1.0);

 SystExplorer-&gt;Fields-&gt;SetFieldType(FieldType::FieldType_ParaxialImageHeight);

 SystExplorer-&gt;Fields-&gt;MakeEqualAreaFields(3, 21.6);

 

 // Add 3 wavelengths: F, d, C

 bool slPreset = SystExplorer-&gt;Wavelengths-&gt;SelectWavelengthPreset(WavelengthPreset::WavelengthPreset_FdC_Visible);

 

 // Open a shaded model

 IA_Ptr analysis = TheSystem-&gt;Analyses-&gt;New_Analysis(AnalysisIDM::AnalysisIDM_ShadedModel);

 analysis-&gt;Terminate();

 analysis-&gt;WaitForCompletion();

 IAS_Ptr settings = analysis-&gt;GetSettings();

 //need to use - #pragma warning(disable:4996)

 char* pUserprofile = getenv("Temp");

 _bstr_t cfgFile = _bstr_t(pUserprofile) + "\\\\sha.cfg";

 // Save the current settings to the temp file

 settings-&gt;SaveTo(cfgFile);

 // make your modifications to it

 // MODIFYSETTINGS are defined in the ZPL help files : The Programming Tab &gt; About the ZPL &gt; Keywords

 settings-&gt;ModifySettings(cfgFile, "SHA\_ROTX", "90");

 settings-&gt;ModifySettings(cfgFile, "SHA\_ROTY", "0");

 settings-&gt;ModifySettings(cfgFile, "SHA\_ROTZ", "0");

 // now load in the modified settings

 settings-&gt;LoadFrom(cfgFile);

 // If you want to overwrite your default CFG, copy it after you are done modifying the settings :

 //\_bstr\_t CFG\_fullname = \_bstr\_t(getenv("USERPROFILE")) + "\\\\Documents\\\\Zemax\\\\Configs\\\\POP.CFG";

 // copyfile(cfgFile, CFG\_fullname) // generic psuedo code

 // We don't need the temp file any more, so delete it

 std::remove(cfgFile);

 // Run the analysis with the new settings

 analysis-&gt;ApplyAndWaitForCompletion();

 

 // remove all variables and add a F# solve on last surface radius

 ILensDataEditorPtr TheLDE = TheSystem-&gt;LDE;

 //IOpticalSystemTools

 IOpticalSystemToolsPtr tools = TheSystem-&gt;Tools;

 tools-&gt;RemoveAllVariables();

 ILDERowPtr Surface_Last = TheLDE-&gt;GetSurfaceAt(TheLDE-&gt;NumberOfSurfaces - 2);

 ISolveDataPtr Solver = Surface_Last-&gt;RadiusCell-&gt;CreateSolveType(SolveType::SolveType_FNumber);

 Solver-&gt;_S_FNumber-&gt;FNumber = 3.1415;

 Surface_Last-&gt;RadiusCell-&gt;SetSolveData(Solver);

 SampleFile = _bstr_t(TheApplication-&gt;SamplesDir) + "\\\\API\\\\\\Seq\_Optimization\\\\\\OptimizedFile1.zos";

 TheSystem-&gt;SaveAs(SampleFile);

 

 // change BFL &amp; run quick focus

 Surface_Last-&gt;Thickness = 40.0;

 IQuickFocusPtr QFocus = tools-&gt;OpenQuickFocus();

 QFocus-&gt;Criterion = QuickFocusCriterion::QuickFocusCriterion_SpotSizeRadial;

 QFocus-&gt;UseCentroid = true;

 ISystemToolPtr baseTool = QFocus;

 baseTool-&gt;RunAndWaitForCompletion();

 baseTool-&gt;Close();

 SampleFile = _bstr_t(TheApplication-&gt;SamplesDir) + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization\\\\OptimizedFile2.zos";

 TheSystem-&gt;SaveAs(SampleFile);

 

 // setup a few variables

 tools-&gt;SetAllRadiiVariable();

 ILDERowPtr [Surface1](namespace_z_o_s_a_p_i_1_1_tools_1_1_tolerancing.xhtml#a18ffc5c5c02195e015067483e4439229a6c4ed555a70d463f08be6c7dd75270ba) = TheLDE-&gt;GetSurfaceAt(1);

 ILDERowPtr [Surface2](namespace_z_o_s_a_p_i_1_1_tools_1_1_tolerancing.xhtml#a18ffc5c5c02195e015067483e4439229a50ba23165f586b14ed916c6119b06129) = TheLDE-&gt;GetSurfaceAt(2);

 ILDERowPtr Surface5 = TheLDE-&gt;GetSurfaceAt(5);

 ILDERowPtr Surface6 = TheLDE-&gt;GetSurfaceAt(6);

 ILDERowPtr Surface9 = TheLDE-&gt;GetSurfaceAt(9);

 ILDERowPtr Surface10 = TheLDE-&gt;GetSurfaceAt(10);

 ILDERowPtr Surface11 = TheLDE-&gt;GetSurfaceAt(11);

 

 // Thickness 2, 5, 6, 9, and 11 variable

 [Surface2](namespace_z_o_s_a_p_i_1_1_tools_1_1_tolerancing.xhtml#a18ffc5c5c02195e015067483e4439229a50ba23165f586b14ed916c6119b06129)-&gt;ThicknessCell-&gt;MakeSolveVariable();

 Surface5-&gt;ThicknessCell-&gt;MakeSolveVariable();

 Surface6-&gt;ThicknessCell-&gt;MakeSolveVariable();

 Surface9-&gt;ThicknessCell-&gt;MakeSolveVariable();

 Surface11-&gt;ThicknessCell-&gt;MakeSolveVariable();

 

 // Thickness 10 pick up from 1

 Solver = Surface10-&gt;ThicknessCell-&gt;CreateSolveType(SolveType::SolveType_SurfacePickup);

 ISolveSurfacePickupPtr SolverPickup = Solver-&gt;_S_SurfacePickup;

 SolverPickup-&gt;Surface = 1;

 SolverPickup-&gt;ScaleFactor = 1;

 SolverPickup-&gt;Column = SurfaceColumn::SurfaceColumn_Thickness;

 Surface10-&gt;ThicknessCell-&gt;SetSolveData(Solver);

 SampleFile = _bstr_t(TheApplication-&gt;SamplesDir + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization\\\\OptimizedFile3.zos");

 TheSystem-&gt;SaveAs(SampleFile);

 

 // define merit function

 // load merit function

 

 IMeritFunctionEditorPtr TheMFE = TheSystem-&gt;MFE;

 // need to ensure that you have the Platform set as x64 and not Win32

 ISEQOptimizationWizardPtr OptWizard = TheMFE-&gt;SEQOptimizationWizard;

 // Optimize for smallest RMS Spot, which is "Data" = 1

 OptWizard-&gt;Data = 1;

 OptWizard-&gt;OverallWeight = 1;

 // Gaussian Quadrature with 3 rings(refers to index number = 2)

 OptWizard-&gt;Ring = 2;

 // Set air &amp; glass boundaries

 OptWizard-&gt;IsGlassUsed = true;

 OptWizard-&gt;GlassMin = 3.0;

 OptWizard-&gt;GlassMax = 15.0;

 OptWizard-&gt;GlassEdge = 3.0;

 OptWizard-&gt;IsAirUsed = true;

 OptWizard-&gt;AirMin = 0.5;

 OptWizard-&gt;AirMax = 1000.0;

 OptWizard-&gt;AirEdge = 0.5;

 // And click OK!

 IWizardPtr baseToolWiz = OptWizard;

 baseToolWiz-&gt;Apply();

 _bstr_t mf_filename = _bstr_t(TheApplication-&gt;SamplesDir + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization\\\\RMS\_Spot\_Radius.mf");

 TheMFE-&gt;SaveMeritFunction(mf_filename);

 TheMFE-&gt;LoadMeritFunction(mf_filename);

 SampleFile = _bstr_t(TheApplication-&gt;SamplesDir + "\\\\API\\\\CPP\\\\e15\_Seq\_Optimization\\\\OptimizedFile4.zos");

 TheSystem-&gt;SaveAs(SampleFile);

 

 // Run local optimization and measure time

 // Local optimization until completion

 double clo = clock();

 ILocalOptimizationPtr LocalOpt = TheSystem-&gt;Tools-&gt;OpenLocalOptimization();

 // need to determine how to check to validity

 if (LocalOpt != nullptr) {

 LocalOpt-&gt;Algorithm = OptimizationAlgorithm::OptimizationAlgorithm_DampedLeastSquares;

 LocalOpt-&gt;Cycles = OptimizationCycles::OptimizationCycles_Automatic;

 LocalOpt-&gt;NumberOfCores = 8;

 cout &lt;&lt; "Local Optimization..." &lt;&lt; endl;

 cout &lt;&lt; "Initial Merit Function " + _bstr_t(LocalOpt-&gt;InitialMeritFunction) &lt;&lt; endl;

 ISystemToolPtr baseToolLocal = LocalOpt;

 baseToolLocal-&gt;RunAndWaitForCompletion();

 cout &lt;&lt; "Final Merit Function " + _bstr_t(LocalOpt-&gt;CurrentMeritFunction) &lt;&lt; endl;

 baseToolLocal-&gt;Close();

 }

 // Get the elapsed time.

 cout &lt;&lt; "Time elapsed " + _bstr_t((clock() - clo) / 1000) &lt;&lt; endl;

 

 

 // run global search

 int GlobalOptimTimeInSeconds = 15;

 IGlobalOptimizationPtr GlobalOpt = TheSystem-&gt;Tools-&gt;OpenGlobalOptimization();

 if (GlobalOpt != nullptr) {

 GlobalOpt-&gt;Algorithm = OptimizationAlgorithm::OptimizationAlgorithm_DampedLeastSquares;

 GlobalOpt-&gt;NumberOfCores = 8;

 cout &lt;&lt; "Global Optimization for " &lt;&lt; GlobalOptimTimeInSeconds &lt;&lt; " seconds..." &lt;&lt; endl;

 cout &lt;&lt; "Initial Merit Function " + _bstr_t(GlobalOpt-&gt;InitialMeritFunction) &lt;&lt; endl;

 GlobalOpt-&gt;NumberToSave = OptimizationSaveCount::OptimizationSaveCount_Save_10;

 ISystemToolPtr baseToolGlobal = GlobalOpt;

 baseToolGlobal-&gt;RunAndWaitWithTimeout(GlobalOptimTimeInSeconds);

 for (int j = 1; j &lt;= 10; j++) {

 cout &lt;&lt; _bstr_t(int(j)) + ": " + _bstr_t(GlobalOpt-&gt;CurrentMeritFunction(j)) &lt;&lt; endl;

 }

 baseToolGlobal-&gt;Cancel();

 // wait for tool to stop running before closing

 //bool stillRunning = baseToolGlobal-&gt;IsRunning;

 //while (stillRunning) {

 // stillRunning = baseToolGlobal-&gt;IsRunning;

 //}

 baseToolGlobal-&gt;WaitForCompletion();

 baseToolGlobal-&gt;Close();

 }

 

 // run hammer optimization

 int HammerOptimTimeInSeconds = 15;

 IHammerOptimizationPtr HammerOpt = TheSystem-&gt;Tools-&gt;OpenHammerOptimization();

 if (HammerOpt != nullptr) {

 HammerOpt-&gt;Algorithm = OptimizationAlgorithm::OptimizationAlgorithm_DampedLeastSquares;

 HammerOpt-&gt;NumberOfCores = 8;

 cout &lt;&lt; "Hammer Optimization for " + _bstr_t(HammerOptimTimeInSeconds) + " seconds..." &lt;&lt; endl;

 cout &lt;&lt; "Initial Merit Function " + _bstr_t(HammerOpt-&gt;InitialMeritFunction) &lt;&lt; endl;

 ISystemToolPtr baseToolHammer = HammerOpt;

 baseToolHammer-&gt;RunAndWaitWithTimeout(HammerOptimTimeInSeconds);

 cout &lt;&lt; "Final Merit Function " + _bstr_t(HammerOpt-&gt;CurrentMeritFunction) &lt;&lt; endl;

 baseToolHammer-&gt;Cancel();

 baseToolHammer-&gt;WaitForCompletion();

 baseToolHammer-&gt;Close();

 }

 

 TheSystem-&gt;Save();

 

\#if defined(\_DEBUG)

 // keeps console open when in debug mode

 system("pause");

\#endif

 

 // 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-&gt;CloseApplication();

 }

}

 

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

 return RunApplication();

}

 

int _tmain(int argc, _TCHAR* argv[])

{

 return RunApplication();

}

[ZOSAPI.ZOSAPI\_Connection](class_z_o_s_a_p_i_1_1_z_o_s_a_p_i___connection.xhtml)

**Definition:** ZemaxService.cs:198



[ZOSAPI.Tools.Tolerancing.TolerancingParameterName.Surface2](namespace_z_o_s_a_p_i_1_1_tools_1_1_tolerancing.xhtml#a18ffc5c5c02195e015067483e4439229a50ba23165f586b14ed916c6119b06129)

@ Surface2



[ZOSAPI.Tools.Tolerancing.TolerancingParameterName.Surface1](namespace_z_o_s_a_p_i_1_1_tools_1_1_tolerancing.xhtml#a18ffc5c5c02195e015067483e4439229a6c4ed555a70d463f08be6c7dd75270ba)

@ Surface1



[ZOSAPI](namespace_z_o_s_a_p_i.xhtml)

The ZOSAPI namespace contains classes for initially connecting to zemax. See also ZOSAPI_Connection,...

**Definition:** IAS_FieldCurvatureAndDistortion.cs:5