    

 ## On this page

  

 

 # Example 07 - C++ 

 Last update: 16.07.2025 

# <a class="anchor" id="ex07_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;

 

// 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()

{

 CoInitialize(nullptr);

 

 // 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;

 

 // Add your custom code here...

 // creates a new API directory

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

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

 _bstr_t FilePath = TheApplication-&gt;ZemaxDataDir + (_bstr_t)"\\\\Samples\\\\Sequential\\\\Objectives\\\\Cooke 40 degree field.zos";

 TheSystem-&gt;LoadFile(FilePath, false);

 

 // run the design lockdown tool to fix diameters, remove solves

 IDesignLockdownPtr LockdownTool = TheSystem-&gt;Tools-&gt;OpenDesignLockdown();

 LockdownTool-&gt;UsePrecisionRounding = 1;

 LockdownTool-&gt;DecimalPrecision = 2;

 ((ISystemToolPtr)LockdownTool)-&gt;RunAndWaitForCompletion(); // access the inherited functions from ISystemTool

 ((ISystemToolPtr)LockdownTool)-&gt;Close(); // access the inherited functions from ISystemTool

 

 // recreate the functionality of the tilt/decenter elements tool

 // apply Coordinate Breaks around the 2nd lens element (surf 3/4)

 ILDERowPtr surf3 = TheSystem-&gt;LDE-&gt;InsertNewSurfaceAt(3);

 ILDERowPtr surf6 = TheSystem-&gt;LDE-&gt;InsertNewSurfaceAt(6);

 ISurfaceTypeSettingsPtr CB = surf3-&gt;GetSurfaceTypeSettings(SurfaceType_CoordinateBreak);

 surf3-&gt;ChangeType(CB);

 surf6-&gt;ChangeType(CB);

 // insert a dummy surface after 2nd CB

 ILDERowPtr surf7 = TheSystem-&gt;LDE-&gt;InsertNewSurfaceAt(7);

 surf7-&gt;Thickness = TheSystem-&gt;LDE-&gt;GetSurfaceAt(5)-&gt;Thickness; // the dummy carries original thickness

 

 // we're going to play with the STOP surface position, so let's put STOP on surf 1

 TheSystem-&gt;LDE-&gt;GetSurfaceAt(1)-&gt;IsStop = true;

 

 // create position solve

 ISolveDataPtr PositionSolve = TheSystem-&gt;LDE-&gt;GetSurfaceAt(5)-&gt;ThicknessCell-&gt;CreateSolveType(SolveType_Position);

 // set the properties for the position solve

 // solve-specific properties are in ISolvePosition interface, accessed via \_S\_Position

 PositionSolve-&gt;_S_Position-&gt;FromSurface = 3;

 PositionSolve-&gt;_S_Position-&gt;Length = 0;

 // apply position solve

 TheSystem-&gt;LDE-&gt;GetSurfaceAt(5)-&gt;ThicknessCell-&gt;SetSolveData(PositionSolve);

 

 // create pickup solve

 ISolveDataPtr PickupSolve = TheSystem-&gt;LDE-&gt;GetSurfaceAt(6)-&gt;ThicknessCell-&gt;CreateSolveType(SolveType_SurfacePickup);

 // solve-specific properties are in ISolvePosition interface, accessed via \_S\_Position

 PickupSolve-&gt;_S_SurfacePickup-&gt;Surface = 5;

 PickupSolve-&gt;_S_SurfacePickup-&gt;ScaleFactor = -1;

 PickupSolve-&gt;_S_SurfacePickup-&gt;offset = 0;

 PickupSolve-&gt;_S_SurfacePickup-&gt;Column = SurfaceColumn_Thickness;

 // apply the pickup solve

 TheSystem-&gt;LDE-&gt;GetSurfaceAt(6)-&gt;ThicknessCell-&gt;SetSolveData(PickupSolve);

 

 // set pickup sovles for coordinate break tilt/decenter parameter cells

 // these are columns 12-16 in the Lens Data Editor (parameters 1-5)

 IEditorRowPtr surf3_EditorRow = TheSystem-&gt;LDE-&gt;GetSurfaceAt(3); // instantiate as IEditorRow to use inherited GetCellAt() function

 IEditorRowPtr surf6_EditorRow = TheSystem-&gt;LDE-&gt;GetSurfaceAt(6); // instantiate as IEditorRow to use inherited GetCellAt() function

 ISolveDataPtr ParameterPickup = surf6_EditorRow-&gt;GetCellAt(12)-&gt;CreateSolveType(SolveType_SurfacePickup);

 ParameterPickup-&gt;_S_SurfacePickup-&gt;Surface = 3;

 ParameterPickup-&gt;_S_SurfacePickup-&gt;ScaleFactor = -1;

 ParameterPickup-&gt;_S_SurfacePickup-&gt;MakePickupFromCurrentColumn();

 srand(time(NULL));

 for (int i = 12; i &lt;= 16; i++)

 {

 surf6_EditorRow-&gt;GetCellAt(i)-&gt;SetSolveData(ParameterPickup);

 surf3_EditorRow-&gt;GetCellAt(i)-&gt;DoubleValue = -0.1 + 0.2 * ((double)rand() / (double)RAND_MAX); // random value between +/-0.1

 }

 // also, set the 'order' flag for CB#2

 surf6_EditorRow-&gt;GetCellAt(17)-&gt;IntegerValue = 1;

 

 // check the global rotation matrix of surface 5 (rear of the tilted/decentered lens)

 [MeritOperandType](namespace_z_o_s_a_p_i_1_1_editors_1_1_m_f_e.xhtml#aa186922480921b908b329f1655025fe4) [GLCR](namespace_z_o_s_a_p_i_1_1_editors_1_1_m_f_e.xhtml#aa186922480921b908b329f1655025fe4ae9194dbd7a346bb627dc364670303480) = MeritOperandType_GLCR;

 // GLCR operand only uses two input parameters: the surface number and rotation matrix entry number.

 // But, GetOperandValue() expects the operand type, plus 8 more inputs because some

 // operands use all 8. We have to put 0's for the additional unused inputs

 double RotationMatrix[3][3] = {0};

 int iterate = 1;

 for (int row = 0; row &lt; 3; row++)

 {

 for (int col = 0; col &lt; 3; col++)

 {

 RotationMatrix[row][col] = TheSystem-&gt;MFE-&gt;GetOperandValue(GLCR, 5, iterate, 0, 0, 0, 0, 0, 0);

 iterate += 1;

 }

 }

 

 // save the file

 _bstr_t OutFilePath = TheApplication-&gt;ZemaxDataDir + (_bstr_t)"\\\\Samples\\\\API\\\\CPP\\\\CPP\_07\_TiltDecenterAndMFOperand.zos";

 TheSystem-&gt;SaveAs(OutFilePath);

 

 // 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.Editors.MFE.MeritOperandType](namespace_z_o_s_a_p_i_1_1_editors_1_1_m_f_e.xhtml#aa186922480921b908b329f1655025fe4)

MeritOperandType

All supported Merit Function operands.

**Definition:** InterfacesMFE.cs:19



[ZOSAPI.Editors.MFE.MeritOperandType.GLCR](namespace_z_o_s_a_p_i_1_1_editors_1_1_m_f_e.xhtml#aa186922480921b908b329f1655025fe4ae9194dbd7a346bb627dc364670303480)

@ GLCR



[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