?? zarraytrace.cpp
字號(hào):
// zArrayTrace.cpp Derived from.
// Zclient: ZEMAX client template program
// Originally written by Kenneth Moore June 1997
// Copyright 1997-2001 Kenneth Moore
//
// Modified by D Griffith, November 2003
// Converted to DLL, calleable as Matlab mex.
// Implements mass ray-tracing as documented in the Zemax Manual
// $Revision: 1.0 $
// The zclient program is responsible for establishing communication
// with the ZEMAX server. All data from ZEMAX can be obtained by calling
// PostRequestMessage or PostArrayTraceMessage with the item name and a buffer to hold the data.
//
// Zclient will call UserFunction when the DDE communication link is established and ready.
// Zclient will automatically terminate the connection when UserFunction returns.
//
// Version 1.1 modified to support Array ray tracing September, 1997
// Version 1.2 modified for faster execution October, 1997
// Version 1.3 modified for faster execution November, 1997
// Version 1.4 modified to fix memory leak January, 1998
// Version 1.5 modified to add support for long path names and quotes November, 1998
// Version 1.6 modified to fix missing support for long path names and quotes in MakeEmptyWindow March, 1999
// Version 1.7 modified to fix memory leak in WM_DDE_ACK, March 1999
// Version 1.8 modified to add E-field data to DDERAYDATA for ZEMAX 10.0, December 2000
// Version 1.9 modified PostRequestMessage and PostArrayTraceMessage to return -1 if data failed (usually because of a timeout) or 0 otherwise, April 2001
#include <windows.h>
#include <dde.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include "mex.h"
#define WM_USER_INITIATE (WM_USER + 1)
#define DDE_TIMEOUT 5000
typedef struct
{
double x, y, z, l, m, n, opd, intensity;
double Exr, Exi, Eyr, Eyi, Ezr, Ezi;
int wave, error, vigcode, want_opd;
}DDERAYDATA;
/* Here are the field names for the DDERAYDATA struct */
#define NUMFIELDS 18
const char *FieldNames[NUMFIELDS] = {"x", "y", "z", "l", "m", "n", "opd", "intensity",
"Exr","Exi","Eyr","Eyi", "Ezr", "Ezi",
"wave", "error", "vigcode", "want_opd"};
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
void WaitForData(HWND hwnd);
char *GetString(char *szBuffer, int n, char *szSubString);
void remove_quotes(char *s);
int PostRequestMessage(char *szItem, char *szBuffer);
int PostArrayTraceMessage(char *szBuffer, DDERAYDATA *RD);
void CenterWindow(HWND hwnd);
void UserFunction(void);
void MakeEmptyWindow(int text, char *szAppName, char *szOptions);
void Get_2_5_10(double cmax, double *cscale);
int myGetInt(mxArray *ScalarNumeric);
/* global variables used by the client code */
char szAppName[] = "ZemaxClient";
int GotData, ngNumRays;
char szGlobalBuffer[5000], szCommandLine[260];
HINSTANCE globalhInstance;
HWND hwndServer, hwndClient;
DDERAYDATA *rdpGRD = NULL;
mxArray *gplhs;
mxArray *dval; /* Temporary variable */
const mxArray *gprhs;
int nfields, nelems, mode, numrays;
DDERAYDATA *MyRayData;
unsigned int DDE_Timeout;
/* BEEP related stuff - mainly for debugging*/
void BEEP(int freq, int duration);
bool isNTxyz();
void DoEvents();
void BEEP(int freq, int duration)
{
if(isNTxyz() == false){
int tmp;
long frq = 1190000L / (long)freq;
_outp(67, 0xb6);
_outp(66, frq & 0xff);
_outp(66, (frq >> 8) & 0xff);
tmp = _inp(97);
_outp(97, tmp | 0x03);
long firstTick;
firstTick = GetTickCount();
do{DoEvents();}
while((GetTickCount() - firstTick) <= (long)duration);
tmp = _inp(97);
_outp(97, tmp & 0xfc);}
else{Beep(freq, duration);}
}
bool isNTxyz()
{
OSVERSIONINFO osVerInfo;
memset(&osVerInfo, 0, sizeof(OSVERSIONINFO));
osVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osVerInfo);
if(osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
{return true;}
else{return false;}
return false;
}
void DoEvents()
{
MSG msg;
while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)){DispatchMessage(&msg);}
}
/* End of BEEP-related stuff */
int CALLBACK LibMain(HANDLE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine)
{
//if (wHeapSize > 0)
// UnlockDate (0); //Unlocks the data segment of the library.
globalhInstance = (HINSTANCE)hInstance;
//BEEP(500,500); //debug
return 1;
}
//int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
void mexFunction(
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
int nfields, field_num, elem_num, FieldIndex;
char FieldName[10];
mxClassID ClassID;
wndclass.cbSize = sizeof (wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = globalhInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
RegisterClassEx (&wndclass);
hwnd = CreateWindow (szAppName, "ZEMAX Client", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, globalhInstance, NULL);
UpdateWindow (hwnd);
// Check the number of arguments. There must be one lhs and one or two rhs.
if (nrhs < 1)
mexErrMsgTxt("One input DDERaydata struct is required.");
if (nrhs > 2)
mexErrMsgTxt("Too many input arguments. Type help zArrayTrace");
if (nlhs > 1)
mexErrMsgTxt("Too many output arguments.");
if (nrhs == 2) // There is a timeout argument as well ?
{
if (mxIsNumeric(prhs[1]))
switch (mxGetClassID(prhs[1])) // We cater for all numeric classes you know
{
case mxDOUBLE_CLASS : DDE_Timeout = (unsigned int)*mxGetPr(prhs[1]); break;
case mxSINGLE_CLASS : DDE_Timeout = (unsigned int)*(float *)mxGetData(prhs[1]); break;
case mxINT8_CLASS : DDE_Timeout = (unsigned int)*(char *)mxGetData(prhs[1]); break;
case mxUINT8_CLASS : DDE_Timeout = (unsigned int)*(unsigned char *)mxGetData(prhs[1]); break;
case mxINT16_CLASS : DDE_Timeout = (unsigned int)*(short *)mxGetData(prhs[1]); break;
case mxUINT16_CLASS : DDE_Timeout = (unsigned int)*(unsigned short *)mxGetData(prhs[1]); break;
case mxINT32_CLASS : DDE_Timeout = (unsigned int)*(int *)mxGetData(prhs[1]); break;
case mxUINT32_CLASS : DDE_Timeout = *(unsigned int *)mxGetData(prhs[1]); break;
}
else
{
mexPrintf("Second argument must be numeric timeout in milliseconds - default assumed.");
DDE_Timeout = DDE_TIMEOUT;
}
}
else
DDE_Timeout = DDE_TIMEOUT; // Use the default defined above
// Set a global pointer to the rhs that we can pick up later if need be
gprhs = prhs[0];
gplhs = plhs[0];
// Set a global pointer to the lhs that we can pick up later.
gplhs = plhs[0];
if (!mxIsStruct(gprhs))
mexErrMsgTxt("Input must be a structure.");
// Get the number of fields in the struct
nfields = mxGetNumberOfFields(gprhs);
// mexPrintf("Fields : %i\n", nfields); //debug
nelems = mxGetNumberOfElements(gprhs);
// mexPrintf("Elements : %i\n", nelems); //debug
// It turns out to be wise to check that the user has correctly specified the
// Here we insert the Matlab struct data into the global raydata struct array MyRayData
// Firstly we must establish how much memory is required and allocate the memory for the ray data.
// Mode 5 requires a whole lot of memory for a single ray, this is the most difficult case.
// So find out if the user want mode 5.
dval = mxGetField(gprhs, 0, "opd"); /* Get the opd field from the first element */
if (dval == NULL) mode = 0;
else mode = myGetInt(dval);
if (mode > 5) // This is mode 5
{
// nelems = mode - 4; // Not sure this is correct
numrays = mode - 5;
mode = 5;
mexPrintf("Mode 5 ... \n"); //debug
}
else
{
dval = mxGetField(gprhs, 0 , "error"); //This is supposedly the number of rays - has the user screwed up or not
if (dval != NULL)
{
numrays = myGetInt(dval);
if ((nelems-1) != numrays)
{
mexPrintf("Field \"error\" set to %i does not correspond with array size of %i.\n", numrays, nelems);
mexErrMsgTxt("Aborted.");
}
}
else // The user did not even set the error field.
{
mexPrintf("The \"error\" field was not set. Should be set to the number of rays.\n");
mexErrMsgTxt("Aborted.");
}
}
// Allocate the memory using the Matlab routine.
MyRayData = (DDERAYDATA *)mxCalloc(numrays+1, sizeof(DDERAYDATA));
if (MyRayData == NULL) mexErrMsgTxt("Unable to allocate memory for the DDERAYDATA structure.");
mexPrintf("Got to after mxCalloc\n"); //debug
// Now copy the Matlab struct array into the MyRayData struct array.
// mxCalloc zeroes out the memory, so it should be OK to just insert the fields that do have values
for (field_num=0; field_num<nfields; field_num++) // Run through the fields in the struct and prepare to put into MyRayData
{
strcpy(FieldName, mxGetFieldNameByNumber(gprhs, field_num));
// mexPrintf("%s\n", FieldName); //debug
FieldIndex = 0;
if (strcmp("x", FieldName)==0) FieldIndex = 1;
else if (strcmp("y", FieldName)==0) FieldIndex = 2;
else if (strcmp("z", FieldName)==0) FieldIndex = 3;
else if (strcmp("l", FieldName)==0) FieldIndex = 4;
else if (strcmp("m", FieldName)==0) FieldIndex = 5;
else if (strcmp("n", FieldName)==0) FieldIndex = 6;
else if (strcmp("opd", FieldName)==0) FieldIndex = 7;
else if (strcmp("intensity", FieldName)==0) FieldIndex = 8;
else if (strcmp("Exr", FieldName)==0) FieldIndex = 9;
else if (strcmp("Exi", FieldName)==0) FieldIndex = 10;
else if (strcmp("Eyr", FieldName)==0) FieldIndex = 11;
else if (strcmp("Eyi", FieldName)==0) FieldIndex = 12;
else if (strcmp("Ezr", FieldName)==0) FieldIndex = 13;
else if (strcmp("Ezi", FieldName)==0) FieldIndex = 14;
else if (strcmp("wave", FieldName)==0) FieldIndex = 15;
else if (strcmp("error", FieldName)==0) FieldIndex = 16;
else if (strcmp("vigcode", FieldName)==0) FieldIndex = 17;
else if (strcmp("want_opd", FieldName)==0) FieldIndex = 18;
else mexPrintf("Warning : Unknown field \"%s\"\n", FieldName);
for (elem_num=0; elem_num<nelems; elem_num++) // Run through the elements which have values and pop them into MyRayData
{
dval = mxGetField(gprhs, elem_num, FieldName);
if (dval != NULL) // No value here, move on
{
if (mxIsNumeric(dval)) // We will cater for all numeric classes just to be thorough
{
ClassID = mxGetClassID(dval);
switch (ClassID)
{
case mxDOUBLE_CLASS : // The data is a double
// mexPrintf("%f\n", *mxGetPr(dval)); // debug
// sharp end - will have to put in a switch statement for every numeric type - ouch.
switch (FieldIndex)
{
case 1: MyRayData[elem_num].x = (double)*mxGetPr(dval); break;
case 2: MyRayData[elem_num].y = (double)*mxGetPr(dval); break;
case 3: MyRayData[elem_num].z = (double)*mxGetPr(dval); break;
case 4: MyRayData[elem_num].l = (double)*mxGetPr(dval); break;
case 5: MyRayData[elem_num].m = (double)*mxGetPr(dval); break;
case 6: MyRayData[elem_num].n = (double)*mxGetPr(dval); break;
case 7: MyRayData[elem_num].opd = (double)*mxGetPr(dval); break;
case 8: MyRayData[elem_num].intensity = (double)*mxGetPr(dval); break;
case 9: MyRayData[elem_num].Exr = (double)*mxGetPr(dval); break;
case 10: MyRayData[elem_num].Exi = (double)*mxGetPr(dval); break;
case 11: MyRayData[elem_num].Eyr = (double)*mxGetPr(dval); break;
case 12: MyRayData[elem_num].Eyi = (double)*mxGetPr(dval); break;
case 13: MyRayData[elem_num].Exr = (double)*mxGetPr(dval); break;
case 14: MyRayData[elem_num].Ezi = (double)*mxGetPr(dval); break;
case 15: MyRayData[elem_num].wave = (int)*mxGetPr(dval); break;
case 16: MyRayData[elem_num].error = (int)*mxGetPr(dval); break;
case 17: MyRayData[elem_num].vigcode = (int)*mxGetPr(dval); break;
case 18: MyRayData[elem_num].want_opd = (int)*mxGetPr(dval); break;
} break;
case mxSINGLE_CLASS : // The data is a single precision float
// mexPrintf("%f\n", *(float *)mxGetData(dval)); //debug
switch (FieldIndex)
{
case 1: MyRayData[elem_num].x = (double)*(float *)mxGetData(dval); break;
case 2: MyRayData[elem_num].y = (double)*(float *)mxGetData(dval); break;
case 3: MyRayData[elem_num].z = (double)*(float *)mxGetData(dval); break;
case 4: MyRayData[elem_num].l = (double)*(float *)mxGetData(dval); break;
case 5: MyRayData[elem_num].m = (double)*(float *)mxGetData(dval); break;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -