    

 ## On this page

  

 

 # Example 22 - C++ 

 Last update: 16.07.2025 

# <a class="anchor" id="ex22_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;fstream&gt;

\#include &lt;string&gt;

\#include &lt;ctime&gt;

\#include &lt;functional&gt;

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

\#include &lt;sstream&gt;

\#include &lt;iomanip&gt;

\#include &lt;vector&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(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;

 

 // Add your custom code here...

 

 // creates new directory

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

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

 

 // Set up primary optical system

 _bstr_t sampleDir = TheApplication-&gt;SamplesDir;

 _bstr_t testFile = sampleDir + "\\\\Sequential\\\\Objectives\\\\Double Gauss 28 degree field.zos";

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

 

 // Set up Batch Ray Trace

 IBatchRayTracePtr raytrace = TheSystem-&gt;Tools-&gt;OpenBatchRayTrace();

 int nsur = TheSystem-&gt;LDE-&gt;NumberOfSurfaces;

 int max_rays = 30;

 IRayTraceNormUnpolDataPtr normUnPolData = raytrace-&gt;CreateNormUnpol((max_rays + 1) * (max_rays + 1), RaysType::RaysType_Real, nsur);

 

 // Define batch ray trace constants

 double hx = 0.0;

 int max_wave = TheSystem-&gt;SystemData-&gt;Wavelengths-&gt;NumberOfWavelengths;

 int num_fields = TheSystem-&gt;SystemData-&gt;Fields-&gt;NumberOfFields;

 double hy_ary[] = { 0, 0.707, 1 };

 

 // Initialize x/y image plane arrays

 std::vector&lt;vector&lt;vector&lt;double&gt;&gt;&gt; x_ary;

 std::vector&lt;vector&lt;vector&lt;double&gt;&gt;&gt; y_ary;

 x_ary.resize(num_fields, vector&lt;vector&lt;double&gt; &gt;(max_wave, vector&lt;double&gt;((max_rays + 1) * (max_rays + 1))));

 y_ary.resize(num_fields, vector&lt;vector&lt;double&gt; &gt;(max_wave, vector&lt;double&gt;((max_rays + 1) * (max_rays + 1))));

 

 // Determine maximum field in Y only

 double max_field = 0.0;

 for (int i = 1; i &lt;= num_fields; i++) {

 if (TheSystem-&gt;SystemData-&gt;Fields-&gt;GetField(i)-&gt;Y &gt; max_field) {

 max_field = TheSystem-&gt;SystemData-&gt;Fields-&gt;GetField(i)-&gt;Y;

 }

 }

 

 fstream textfile;

 string filepath = sampleDir + "\\\\API\\\\CPP\\\\e22\_seq\_spot\_diagram.txt";

 textfile.open(filepath, fstream::trunc | ios::out);

 textfile &lt;&lt; "Field \\t Wave \\t X \\t Y" &lt;&lt; endl;

 

 for (int field = 1; field &lt;= num_fields; field++) {

 for (int wave = 1; wave &lt;= max_wave; wave++) {

 // Adding Rays to Batch, varying normalised object height hy

 normUnPolData-&gt;ClearData();

 int waveNumber = wave;

 for (int i = 1; i &lt;= ((max_rays + 1) * (max_rays + 1)); i++) {

 double px, py;

 

 px = (double)rand() / (double)RAND_MAX * 2 - 1;

 py = (double)rand() / (double)RAND_MAX * 2 - 1;

 while (px*px + py*py &gt; 1) {

 py = (double)rand() / (double)RAND_MAX * 2 - 1;

 }

 normUnPolData-&gt;AddRay(waveNumber, hx, hy_ary[field - 1], px, py, OPDMode::OPDMode_None);

 }

 

 // Run Batch Ray Trace

 ISystemToolPtr baseTool = raytrace;

 baseTool-&gt;RunAndWaitForCompletion();

 

 // Read batch raytrace and save results

 normUnPolData-&gt;StartReadingResults();

 long rayNumber, ErrorCode, vignetteCode;

 double dbl_X, dbl_Y, dbl_Z, dbl_L, dbl_M, dbl_N, dbl_L2, dbl_M2, dbl_N2, OPD, Intensity;

 bool success;

 

 success = normUnPolData-&gt;ReadNextResult(&amp;rayNumber, &amp;ErrorCode, &amp;vignetteCode, &amp;dbl_X, &amp;dbl_Y, &amp;dbl_Z, &amp;dbl_L, &amp;dbl_M, &amp;dbl_N, &amp;dbl_L2, &amp;dbl_M2, &amp;dbl_N2, &amp;OPD, &amp;Intensity);

 while (success) {

 if ((ErrorCode == 0) &amp;&amp; (vignetteCode == 0)) {

 x_ary[field - 1][wave - 1][rayNumber - 1] = dbl_X;

 y_ary[field - 1][wave - 1][rayNumber - 1] = dbl_Y;

 textfile &lt;&lt; _bstr_t(field) + "\\t" + _bstr_t(wave) + "\\t" + _bstr_t(dbl_X) + "\\t" + _bstr_t(dbl_Y) &lt;&lt; endl;

 }

 success = normUnPolData-&gt;ReadNextResult(&amp;rayNumber, &amp;ErrorCode, &amp;vignetteCode, &amp;dbl_X, &amp;dbl_Y, &amp;dbl_Z, &amp;dbl_L, &amp;dbl_M, &amp;dbl_N, &amp;dbl_L2, &amp;dbl_M2, &amp;dbl_N2, &amp;OPD, &amp;Intensity);

 }

 textfile &lt;&lt; "" &lt;&lt; endl;

 }

 }

 

 // Spot Diagram Analysis Results

 IA_Ptr spot = TheSystem-&gt;Analyses-&gt;New_Analysis(AnalysisIDM::AnalysisIDM_StandardSpot);

 IAS_SpotPtr spot_setting = spot-&gt;GetSettings();

 spot_setting-&gt;Field-&gt;SetFieldNumber(0);

 spot_setting-&gt;Wavelength-&gt;SetWavelengthNumber(0);

 spot_setting-&gt;ReferTo = Reference::Reference_Centroid;

 

 // Extract RMS &amp; Geo spot size for field points

 spot-&gt;ApplyAndWaitForCompletion();

 IAR_Ptr spot_results = spot-&gt;GetResults();

 cout.precision(3);

 cout &lt;&lt; fixed &lt;&lt; "RMS radius: \\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetRMSSpotSizeFor(1, 1) &lt;&lt; "\\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetRMSSpotSizeFor(2, 1) &lt;&lt; "\\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetRMSSpotSizeFor(3, 1) &lt;&lt; endl;

 cout &lt;&lt; fixed &lt;&lt; "GEO radius: \\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetGeoSpotSizeFor(1, 1) &lt;&lt; "\\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetGeoSpotSizeFor(2, 1) &lt;&lt; "\\t" &lt;&lt; spot_results-&gt;SpotData-&gt;GetGeoSpotSizeFor(3, 1) &lt;&lt; endl;

 

 textfile.close();

\#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](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