// ******************************************************************************** 
// ** RaaToCsvDlg
// **
// ** Copyright (C) 2012-2017 3D at Depth Inc. All Rights Reserved
// ** www.3DatDepth.com  This software can not be copied and/or distributed without 
// ** the express permission of 3D at Depth Inc.
// ******************************************************************************** 


#include "stdafx.h"
#include "RaaToCsv.h"
#include "RaaToCsvDlg.h"
#include "afxdialogex.h"
#include "WSPacket.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CRaaToCsvDlg dialog




CRaaToCsvDlg::CRaaToCsvDlg(CWnd* pParent /*=NULL*/)
:  CDialogEx(CRaaToCsvDlg::IDD, pParent),
   m_nBytesRead(0),
   m_nMslFileSize(0),
   m_thdConvert("Conversion Thread", SysThread::PRI_PROCESS),
   m_bConvertFile(false),
   m_pfileMSL(0),
   m_pfileCSV(0),
   m_bInitialized(false)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   m_thdConvert.Start(ConversionThreadEntry, (void*) this);
}

void CRaaToCsvDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_AZ_ROTATION_A, m_ctlAzRotationA);
	DDX_Control(pDX, IDC_EDIT_EL_ROTATION_A, m_ctlElRotationA);
	DDX_Control(pDX, IDC_EDIT_AZ_ROTATION_B, m_ctlAzRotationB);
	DDX_Control(pDX, IDC_EDIT_EL_ROTATION_B, m_ctlElRotationB);
	DDX_Control(pDX, IDC_PROGRESS_CONVERT, m_ctlConvertProgress);
}

BEGIN_MESSAGE_MAP(CRaaToCsvDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
   ON_BN_CLICKED(IDC_BUTTON1, &CRaaToCsvDlg::OnBnClickedSelectFile)
   ON_WM_TIMER()
   ON_BN_CLICKED(IDC_BUTTON_STOP, &CRaaToCsvDlg::OnBnClickedStop)
END_MESSAGE_MAP()


// CRaaToCsvDlg message handlers

BOOL CRaaToCsvDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

   m_ctlConvertProgress.SetRange(0, 100);

   SetTimer(1, 1000, NULL);

   m_bInitialized = true;

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRaaToCsvDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRaaToCsvDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRaaToCsvDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CRaaToCsvDlg::OnBnClickedSelectFile()
{
   m_bConvertFile = false;

   CFileDialog* pdlgFile = new CFileDialog(true);

   if ( pdlgFile->DoModal() == IDOK )
   {
      m_strMslFileName = pdlgFile->GetFolderPath() + "\\" + pdlgFile->GetFileName();
      m_strCsvFileName = pdlgFile->GetFolderPath() + "\\csv\\" + pdlgFile->GetFileName();
      m_strCsvFileName = m_strCsvFileName.Left(m_strCsvFileName.GetLength()-3) + "csv";

      GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("Converting File...");
      GetDlgItem(IDC_STATIC_CSV)->SetWindowText("CSV File...");
      GetDlgItem(IDC_STATIC_MSL_FILE)->SetWindowText(m_strMslFileName);
      GetDlgItem(IDC_STATIC_CSV_FILE)->SetWindowText(m_strCsvFileName);

      if ( VerifyFolderExists(pdlgFile->GetFolderPath() + "\\csv\\", true) )
      {
         m_nMslFileSize = FileSize(m_strMslFileName);
         m_nBytesRead = 0;

         fopen_s(&m_pfileMSL, m_strMslFileName, "r+b");

         if ( m_pfileMSL )
         {
            fopen_s(&m_pfileCSV, m_strCsvFileName, "w+t");

            if ( m_pfileCSV )
               m_bConvertFile = true;
            else
               ::AfxMessageBox("ERROR - COULDN'T CREATE CSV FILE");
         }
         else
         {
            ::AfxMessageBox("ERROR - COULDN'T OPEN SELECTED FILE");
         }
      }
   }
}


/************************************************************************************
/*** CRaaToCsvDlg::VerifyFolderExists
/***
*************************************************************************************/
bool CRaaToCsvDlg::VerifyFolderExists(CString strFolder, bool bCreateNonExistentFolder /*= false*/)
{
   bool  bOK = false;
   char  pchCurrentDirectory[200];
   DWORD nError;

   // save current directory location
   GetCurrentDirectory(200, pchCurrentDirectory);

   // determine if specified folder exists (error if it doesn't)
   if ( SetCurrentDirectory(strFolder) )
   {
      bOK = true;
   }
   // specified folder does not exist, caller has requested that it try to be created
   else if ( bCreateNonExistentFolder )
   {
      string strSubDirectory, strDirectory = strFolder;
      size_t nOffset;

      // search for first sub-directory separator character in full directory name
      nOffset = strDirectory.find_first_of("\\/");

      if ( nOffset != string::npos )
      {
         bOK = true;
         
         // iteratively work down from root directory to lowest level sub-directory
         while ( bOK && (nOffset != string::npos || strDirectory.length()) )
         {
            // iteratively build full directory path to create if it doesn't exist
            strSubDirectory += strDirectory.substr(0, nOffset);

            // determine if this directory level already exists
            bOK = SetCurrentDirectory(strSubDirectory.c_str()) ? true : false;

            // this directory level does not exist, try to create it
            if ( !bOK )
            {
               bOK = CreateDirectory(strSubDirectory.c_str(), NULL) ? true : false;
               nError = GetLastError();

               if ( nError == 5 )
                  ::AfxMessageBox("ERROR - Access denied, cannot create directory!");
            }

            // succeeded creating this directory level, seach for another sub-directory level
            if ( bOK )
            {
               // add sub-directory separator
               strSubDirectory += "\\";

               // got another sub-directory level, add it to path
               if ( nOffset != string::npos )
                  strDirectory = strDirectory.substr(nOffset+1, strDirectory.length());
               // no more sub-directory levels
               else
                  strDirectory = "";

               // get location extent of next sub-directory level name
               nOffset = strDirectory.find_first_of("\\/");
            }
         }
      }
   }

   // return to saved current directory location
   SetCurrentDirectory(pchCurrentDirectory);

   // true if folder exists 
   // OR
   // true if folder does not exist and user requested it be created and it could be created
   return bOK;       
}


/************************************************************************************
/*** CRaaToCsvDlg::OnTimer
/***
*************************************************************************************/
void CRaaToCsvDlg::OnTimer(UINT_PTR nIDEvent)
{
   if ( nIDEvent == 1 )
   {
      if ( m_nMslFileSize )
         m_ctlConvertProgress.SetPos((int) (100.0*m_nBytesRead/m_nMslFileSize));
      else
         m_ctlConvertProgress.SetPos(0);
   }

   CDialog::OnTimer(nIDEvent);
}


/************************************************************************************
/*** CRaaToCsvDlg::FileSize
/***
*************************************************************************************/
UINT64 CRaaToCsvDlg::FileSize(CString strFile)
{
   UINT64 nSize;
   LARGE_INTEGER size;

   HANDLE hFile = CreateFile(strFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

   if (hFile==INVALID_HANDLE_VALUE)
      nSize = 0;

   if ( !GetFileSizeEx(hFile, &size) )
   {
      CloseHandle(hFile);
      nSize = 0;
   }

   CloseHandle(hFile);

   nSize = size.QuadPart;

   return nSize;
}

/************************************************************************************
/*** CRaaToCsvDlg::ConversionThreadEntry
/***
*************************************************************************************/
void CRaaToCsvDlg::ConversionThreadEntry(void *pThreadObj)
{
	((CRaaToCsvDlg*) pThreadObj)->ConversionThread();
}


/************************************************************************************
/*** CRaaToCsvDlg::ConversionThread
/***
*************************************************************************************/
void CRaaToCsvDlg::ConversionThread()
{
   float    pfRange[5], fTimeOffset, fCrossTrackAz, fForwardTrackEl, fCrossTrackAzOffset, fForwardTrackElOffset;
   float    pfX[5], pfY[5], pfZ[5], pfRotatedX[5], pfRotatedY[5], pfRotatedZ[5];
   UINT16   pnIntensity[5];
   UINT32   nPoint;

   while ( !m_bInitialized )
      ::Sleep(100);

   GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("");
   GetDlgItem(IDC_STATIC_CSV)->SetWindowText("");
   GetDlgItem(IDC_STATIC_MSL_FILE)->SetWindowText("");
   GetDlgItem(IDC_STATIC_CSV_FILE)->SetWindowText("");

	while ( true )
	{
      if ( m_bConvertFile )
      {
         ReadHeaderData();

         sprintf_s(m_pch, 500, "sep=,\nID,0X%x\nPacket,0X%x\nVersion,%d\nSubvesion,%d\n\n", m_nId, m_nMagicNumber, m_nVersion, m_nSubVersion);
         fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
         sprintf_s(m_pch, 500, "AZ Start deg,%1.2f\nAZ End deg,%1.2f\nPulses per Scanline,%d\nPulses per LOS,%d\nHead A Scanline Cnt,%d\nHead B ScanlineCnt,%d\n\n", 
                   m_fAzStart, m_fAzEnd, m_nPulsesPerCrossTrack, m_nPulsesPerLOS, m_nScanLineCount1, m_nScanLineCount2);
         fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

         while ( ReadLaserData() && m_bConvertFile )
         {
            sprintf_s(m_pch, 500, "%s\n", m_nRecordID == 0x3D53 ? "Head A" : "Head B");
            fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
            sprintf_s(m_pch, 500, "%02d%02d%04d.%02d%02d%02d::%06d\n", m_sTimeStamp.tm_mon, m_sTimeStamp.tm_mday, m_sTimeStamp.tm_year,
               m_sTimeStamp.tm_hour, m_sTimeStamp.tm_min, m_sTimeStamp.tm_sec, m_sTimeStamp.m_nanoseconds/1000);
            fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
            sprintf_s(m_pch, 500, "Pulse Count Scanline,%d\n", m_nPulseCountThisScanLine);
            fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

				sprintf_s(m_pch, 500, "AZ deg, EL deg, AZ offset m, EL offset m, time offset s, Range m, Intensity, X local, Y local, Z local, X global, Y global, Z global\n" ); 
            fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
            for ( UINT32 nLos = 0; nLos < m_nPulseCountThisScanLine; nLos++ )
            {
               //nPoint = 0;

               m_pktScanLine.Los(nLos, &fCrossTrackAz, &fForwardTrackEl, pfRange, pnIntensity, 
                                 &fTimeOffset, &fCrossTrackAzOffset, &fForwardTrackElOffset);
					m_fTimeOffset = fTimeOffset;

               //m_pktScanLine.ComputeXYZ(pfRange[nPoint], fCrossTrackAz, fForwardTrackEl, fCrossTrackAzOffset, fForwardTrackElOffset, &fX, &fY, &fZ);
               m_pktScanLine.ComputeXYZ();
               m_pktScanLine.Los(nLos, pfX, pfY, pfZ);
               m_pktScanLine.ComputeHeadRotation(m_nRecordID == 0x3D53 ? 1 : 2, m_fAzRotation, m_fElRotation);
               m_pktScanLine.Los(nLos, pfRotatedX, pfRotatedY, pfRotatedZ);

               sprintf_s(m_pch, 500, "%1.5f, %1.5f, %1.5f, %1.5f, %1.6f,", 
                  fCrossTrackAz, fForwardTrackEl, fCrossTrackAzOffset, fForwardTrackElOffset, m_fTimeOffset);
               fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

                 // sprintf_s(m_pch, 500, "%1.3f, %1.3f, %1.3f\n", fX, fY, fZ);
               //fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

               for ( nPoint = 0; nPoint < m_nPulsesPerLOS; nPoint++ )
               {
                  //m_pktScanLine.ComputeXYZ(pfRange[nPoint], fCrossTrackAz, fForwardTrackEl, fCrossTrackAzOffset, fForwardTrackElOffset, &fX, &fY, &fZ);

                  if ( nPoint == 0 )
                     sprintf_s(m_pch, 500, "%1.5f, %d, %1.5f, %1.5f, %1.5f, %1.5f, %1.5f, %1.5f\n", 
                        pfRange[nPoint], pnIntensity[nPoint], 
                        pfX[nPoint], pfY[nPoint], pfZ[nPoint], pfRotatedX[nPoint], pfRotatedY[nPoint], pfRotatedZ[nPoint]);
                  else
                     sprintf_s(m_pch, 500, "%c, %c, %c, %c, %c, %1.5f, %d, %1.5f, %1.5f, %1.5f, %1.5f, %1.5f, %1.5f\n", 
                        ' ', ' ', ' ', ' ', ' ', pfRange[nPoint], pnIntensity[nPoint], 
                        pfX[nPoint], pfY[nPoint], pfZ[nPoint], pfRotatedX[nPoint], pfRotatedY[nPoint], pfRotatedZ[nPoint]);

                  fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

                  //m_pktScanLine.ComputeHeadRotation(m_nRecordID == 0x3D53 ? 1 : 2, m_fAzRotation, m_fElRotation, &fX, &fY, &fZ);

                  //sprintf_s(m_pch, 500, "%1.3f, %1.3f, %1.3f\n", fX, fY, fZ);
                  //fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
               }
            }

            sprintf_s(m_pch, 500, "\n");
            fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
         }

         fclose(m_pfileCSV);

         GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("File Convertion Complete!");
      }
      else
      {
         if ( m_pfileMSL )
         {
            fclose(m_pfileMSL);
            m_pfileMSL = 0;
         }
         if ( m_pfileCSV )
         {
            fclose(m_pfileCSV);
            m_pfileCSV = 0;
         }

         m_strCsvFileName = m_strMslFileName = "";

         if ( m_bInitialized )
         {
            //GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("");
            //GetDlgItem(IDC_STATIC_MSL_FILE)->SetWindowText(m_strMslFileName);
            //GetDlgItem(IDC_STATIC_CSV_FILE)->SetWindowText(m_strCsvFileName);

            m_nBytesRead = 0;
         }
      }

		Sleep(1000);
	}
}


/************************************************************************************
/*** CRaaToCsvDlg::OnBnClickedStop
/***
*************************************************************************************/
void CRaaToCsvDlg::OnBnClickedStop()
{
   m_bConvertFile = false;
}


/************************************************************************************
/*** CRaaToCsvDlg::ReadHeaderData
/***
*************************************************************************************/
void CRaaToCsvDlg::ReadHeaderData()
{
   // file header - .raa format
   m_nBytesRead = fread(&m_nId, sizeof(m_nId), 1, m_pfileMSL) * sizeof(m_nId);
   m_nBytesRead += fread(&m_nMagicNumber, sizeof(m_nMagicNumber), 1, m_pfileMSL) * sizeof(m_nMagicNumber);
   m_nBytesRead += fread(&m_nVersion, sizeof(m_nVersion), 1, m_pfileMSL) * sizeof(m_nVersion);
   m_nBytesRead += fread(&m_nSubVersion, sizeof(m_nSubVersion), 1, m_pfileMSL) * sizeof(m_nSubVersion);

   // scan info - .raa format
   m_nBytesRead += fread(&m_fAzStart, sizeof(m_fAzStart), 1, m_pfileMSL) * sizeof(m_fAzStart);
   m_nBytesRead += fread(&m_fAzEnd, sizeof(m_fAzEnd), 1, m_pfileMSL) * sizeof(m_fAzEnd);
   m_nBytesRead += fread(&m_nPulsesPerCrossTrack, sizeof(m_nPulsesPerCrossTrack), 1, m_pfileMSL) * sizeof(m_nPulsesPerCrossTrack);
   m_nBytesRead += fread(&m_nPulsesPerLOS, sizeof(m_nPulsesPerLOS), 1, m_pfileMSL) * sizeof(m_nPulsesPerLOS);
   m_nBytesRead += fread(&m_nScanLineCount1, sizeof(m_nScanLineCount1), 1, m_pfileMSL) * sizeof(m_nScanLineCount1);
   m_nBytesRead += fread(&m_nScanLineCount2, sizeof(m_nScanLineCount2), 1, m_pfileMSL) * sizeof(m_nScanLineCount2);

   m_nPointsPerLos = m_nPulsesPerLOS;
   m_nLosPerScanLine = m_nPulsesPerCrossTrack;

   m_pktScanLine.SetConfiguration(m_nLosPerScanLine, m_nPointsPerLos);
}


/************************************************************************************
/*** CRaaToCsvDlg::ReadLaserData
/***
*************************************************************************************/
bool CRaaToCsvDlg::ReadLaserData()
{
   char pch[10];
   float fAngle;

   // first pulse ID and timestamp
   m_nBytesRead += fread(&m_nRecordID, sizeof(m_nRecordID), 1, m_pfileMSL) * sizeof(m_nRecordID);

   int nHead = m_nRecordID == 0x3D53 ? 1 : 2;

   if ( m_nRecordID == 0x3D53 )
   {
      m_ctlAzRotationA.GetWindowTextA(pch, 10);
      fAngle = (float) atof(pch);
      m_fAzRotation = fAngle;

      m_ctlElRotationA.GetWindowTextA(pch, 10);
      fAngle = (float) atof(pch);
      m_fElRotation = fAngle;
   }
   else
   {
      m_ctlAzRotationB.GetWindowTextA(pch, 10);
      fAngle = (float) atof(pch);
      m_fAzRotation = fAngle;

      m_ctlElRotationB.GetWindowTextA(pch, 10);
      fAngle = (float) atof(pch);
      m_fElRotation = fAngle;
   }

   if ( !feof(m_pfileMSL) )
   {
      m_nBytesRead += fread(&m_sTimeStamp.tm_year, sizeof(m_sTimeStamp.tm_year), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_year);
      m_nBytesRead += fread(&m_sTimeStamp.tm_mon, sizeof(m_sTimeStamp.tm_mon), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_mon);
      m_nBytesRead += fread(&m_sTimeStamp.tm_mday, sizeof(m_sTimeStamp.tm_mday), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_mday);
      m_nBytesRead += fread(&m_sTimeStamp.tm_yday, sizeof(m_sTimeStamp.tm_yday), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_yday);
      m_nBytesRead += fread(&m_sTimeStamp.tm_hour, sizeof(m_sTimeStamp.tm_hour), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_hour);
      m_nBytesRead += fread(&m_sTimeStamp.tm_min, sizeof(m_sTimeStamp.tm_min), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_min);
      m_nBytesRead += fread(&m_sTimeStamp.tm_sec, sizeof(m_sTimeStamp.tm_sec), 1, m_pfileMSL) * sizeof(m_sTimeStamp.tm_sec);
      m_nBytesRead += fread(&m_sTimeStamp.m_nanoseconds, sizeof(m_sTimeStamp.m_nanoseconds), 1, m_pfileMSL) * sizeof(m_sTimeStamp.m_nanoseconds);

      m_pktScanLine.SetTimeStamp(m_sTimeStamp);

      m_nBytesRead += fread(&m_nPulseCountThisScanLine, sizeof(m_nPulseCountThisScanLine), 1, m_pfileMSL) * sizeof(m_nPulseCountThisScanLine);

      // laser pulse data
      for ( UINT32 nLos = 0; nLos < m_nPulseCountThisScanLine; nLos++ )
      {  
         m_nBytesRead += fread(&m_fCrossTrackAz, sizeof(m_fCrossTrackAz), 1, m_pfileMSL) * sizeof(m_fCrossTrackAz);
         m_nBytesRead += fread(&m_fForwardTrackEl, sizeof(m_fForwardTrackEl), 1, m_pfileMSL) * sizeof(m_fForwardTrackEl);
         m_nBytesRead += fread(&m_fCrossTrackAzOffset, sizeof(m_fCrossTrackAzOffset), 1, m_pfileMSL) * sizeof(m_fCrossTrackAzOffset);
         m_nBytesRead += fread(&m_fForwardTrackElOffset, sizeof(m_fForwardTrackElOffset), 1, m_pfileMSL) * sizeof(m_fForwardTrackElOffset);
         m_nBytesRead += fread(&m_fTimeOffset, sizeof(m_fTimeOffset), 1, m_pfileMSL) * sizeof(m_fTimeOffset);                        /*** rwm - pulse time offset (sec)?? ***/

         for ( UINT32 nPoint = 0; nPoint < m_nPointsPerLos; nPoint++ )
            m_nBytesRead += fread(&m_pfRange[nPoint], sizeof(float), 1, m_pfileMSL) * sizeof(float);

         for ( UINT32 nPoint = 0; nPoint < m_nPointsPerLos; nPoint++ )
            m_nBytesRead += fread(&m_pnIntensity[nPoint], sizeof(UINT16), 1, m_pfileMSL) * sizeof(UINT16);

         m_pktScanLine.SetLos(nHead, nLos, m_fCrossTrackAz, m_fForwardTrackEl, m_pfRange, m_pnIntensity, 
                              m_fTimeOffset, &m_fCrossTrackAzOffset, &m_fForwardTrackElOffset);
      }
   }

   return feof(m_pfileMSL) ? false : true;
}






































/************************************************************************************
/*** CRaaToCsvDlg::ConversionThreadMSL
/***
************************************************************************************* /
void CRaaToCsvDlg::ConversionThreadMSL()
{
   UINT32               nPointsPerLos, nLosPerScanLine, nDataElementCount, nLidarNumber, nLos, nPoint;
   WSScanLineDataPacket scanLineData;
   StructTimeStamp      sTimeStamp;
   float                fAz;
   float                pfRange[5];
   UINT16               pnIntensity[5];
   float                pfTimeOffset[5];
   char                 pchScanLine[500];
   char                 pchDataPoints[500];

	while ( true )
	{
      if ( m_bConvertFile )
      {
         strcpy_s(m_pch, 500, "Points Per LOS, LOS Per Scan Line, Data Element Count\n");
         fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);
         m_nBytesRead += fread(&nPointsPerLos, sizeof(nPointsPerLos), 1, m_pfileMSL);
         m_nBytesRead += fread(&nLosPerScanLine, sizeof(nLosPerScanLine), 1, m_pfileMSL);
         m_nBytesRead += fread(&nDataElementCount, sizeof(nDataElementCount), 1, m_pfileMSL);
         sprintf_s(m_pch, 500, "%d, %d, %d\n", nPointsPerLos, nLosPerScanLine, nDataElementCount);
         fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

         scanLineData.SetConfiguration(nLosPerScanLine, nPointsPerLos); 

         if ( nPointsPerLos == 1 )
            strcpy_s(m_pch, 500, "LOS #, Time, Az, Range 1, Intensity 1, Time Offset 1\n");
         else if ( nPointsPerLos == 2 )
            strcpy_s(m_pch, 500, "LOS #, Time, Az, Range 1, Range 2, Intensity 1, Intensity 2, Time Offset 1, Time Offset 2\n");
         else if ( nPointsPerLos == 3 )
            strcpy_s(m_pch, 500, "LOS #, Time, Az, Range 1, Range 2, Range 3, Intensity 1, Intensity 2, Intensity 3, Time Offset 1, Time Offset 2, Time Offset 3\n");
         else if ( nPointsPerLos == 4 )
            strcpy_s(m_pch, 500, "LOS #, Time, Az, Range 1, Range 2, Range 3, Range 4, Intensity 1, Intensity 2, Intensity 3, Intensity 4, Time Offset 1, Time Offset 2, Time Offset 3, Time Offset 4\n");
         else if ( nPointsPerLos == 5 )
            strcpy_s(m_pch, 500, "LOS #, Time, Az, Range 1, Range 2, Range 3, Range 4, Range 5, Intensity 1, Intensity 2, Intensity 3, Intensity 4, Intensity 5, Time Offset 1, Time Offset 2, Time Offset 3, Time Offset 4, Time Offset 5\n");

         fwrite(m_pch, 1, strlen(m_pch), m_pfileCSV);

         while ( !feof(m_pfileMSL) && m_bConvertFile )
         {
            m_nBytesRead += fread(&nLidarNumber, sizeof(nLidarNumber), 1, m_pfileMSL);
            m_nBytesRead += fread(scanLineData.Data(), 1, scanLineData.DataSize(), m_pfileMSL);

            for ( nLos = 0; nLos < nLosPerScanLine; nLos++ )
            {
               scanLineData.SingleDataPoint(nLos, 0, &sTimeStamp, &fAz, pfRange, pnIntensity, pfTimeOffset);
               sprintf_s(pchScanLine, 500, "%d, %02d:%02d:%02d.%09d, %1.3f, ", 
                  nLos+1, sTimeStamp.tm_hour, sTimeStamp.tm_min, sTimeStamp.tm_sec, sTimeStamp.m_nanoseconds, fAz);

               for ( nPoint = 0; nPoint < nPointsPerLos; nPoint++ )
                  scanLineData.SingleDataPoint(nLos, nPoint, &sTimeStamp, &fAz, &pfRange[nPoint], &pnIntensity[nPoint], &pfTimeOffset[nPoint]);

               if ( nPointsPerLos == 1 )
                  sprintf_s(pchDataPoints, 500, "%f, %d, %f\n", 
                     pfRange[0], pfRange[1], pnIntensity[0], pfTimeOffset[0]);
               else if ( nPointsPerLos == 2 )
                  sprintf_s(pchDataPoints, 500, "%f, %f, %d, %d, %f, %f\n", 
                     pfRange[0], pfRange[1], pnIntensity[0], pnIntensity[1], pfTimeOffset[0], pfTimeOffset[1]);
               else if ( nPointsPerLos == 3 )
                  sprintf_s(pchDataPoints, 500, "%f, %f, %f, %d, %d, %d, %f, %f, %f\n", 
                     pfRange[0], pfRange[1], pfRange[2], pnIntensity[0], pnIntensity[1], pnIntensity[2], 
                     pfTimeOffset[0], pfTimeOffset[1], pfTimeOffset[2]);
               else if ( nPointsPerLos == 4 )
                  sprintf_s(pchDataPoints, 500, "%f, %f, %f, %f, %d, %d, %d, %d, %f, %f, %f, %f\n", 
                     pfRange[0], pfRange[1], pfRange[2], pfRange[3], pnIntensity[0], pnIntensity[1], pnIntensity[2], pnIntensity[3], 
                     pfTimeOffset[0], pfTimeOffset[1], pfTimeOffset[2], pfTimeOffset[3]);
               else if ( nPointsPerLos == 5 )
                  sprintf_s(pchDataPoints, 500, "%f, %f, %f, %f, %f, %d, %d, %d, %d, %d, %f, %f, %f, %f, %f\n", 
                     pfRange[0], pfRange[1], pfRange[2], pfRange[3], pfRange[4], 
                     pnIntensity[0], pnIntensity[1], pnIntensity[2], pnIntensity[3], pnIntensity[4], 
                     pfTimeOffset[0], pfTimeOffset[1], pfTimeOffset[2], pfTimeOffset[3], pfTimeOffset[4]);

               strcat_s(pchScanLine, 500, pchDataPoints);
               fwrite(pchScanLine, 1, strlen(pchScanLine), m_pfileCSV);
            }
         }

         GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("File Convertion Complete!");
      }
      else
      {
         if ( m_pfileMSL )
         {
            fclose(m_pfileMSL);
            m_pfileMSL = 0;
         }
         if ( m_pfileCSV )
         {
            fclose(m_pfileCSV);
            m_pfileCSV = 0;
         }

         m_strCsvFileName = m_strMslFileName = "";

         if ( m_bInitialized )
         {
            GetDlgItem(IDC_STATIC_COMPLETE)->SetWindowText("");
            GetDlgItem(IDC_STATIC_MSL_FILE)->SetWindowText(m_strMslFileName);
            GetDlgItem(IDC_STATIC_CSV_FILE)->SetWindowText(m_strCsvFileName);

            m_nBytesRead = 0;
         }
      }

		Sleep(1000);
	}
}
*/
