// WedgeDisplay.cpp: implementation of the CWedgeDisplay class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "WedgeDisplay.h"



#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define RECTANGULAR_OFFSET 0.1f

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CWedgeDisplay, CWnd);

CWedgeDisplay::CWedgeDisplay()
{
  m_pModifiedTexture   = new BYTE[TWIDTH*THEIGHT*4];
  memset(m_pModifiedTexture, 255, TWIDTH*THEIGHT*4);
  m_pPalette = new BYTE[256*4];
  memset(m_pPalette, 255, 256*4);

  ZeroMemory(&m_stWedgeInfo, sizeof(WEDGEINFO));

  m_fX               = 0.0;
  m_fY               = -0.5;
  m_fZ               = -0.9999;
  //m_cContrast        = SCROLLCONTRASTHALF;
  //m_cBrightness      = SCROLLBRIGHTHALF;
  m_bFlip            = FALSE;
  m_bRectangular     = FALSE;
  m_bStave			 = FALSE;
  m_dwHeight         = 0;
  m_dwWidth          = 0;
  m_dwSelectedBeam   = 1;
  m_bAScan           = TRUE;
  m_bFreeze          = FALSE;
  m_bBathy			 = FALSE;
  m_bLMouseDown      = FALSE;
  m_dwPalette        = 0;
  m_pCtrlDlg         = NULL;
  m_bHardwarePalette = FALSE;
  //m_dFirstBeam       = 2.614014527;
  //m_dLastBeam        = 0.5275781264;
//  m_dLastBeam        = 2.614014527;
//  m_dFirstBeam       = 0.5275781264;
  m_dMinCoord        = 0.0;
  m_dMaxCoord        = 0.0;
  m_bInitWedge       = FALSE;
  m_dSoundVelocity   = 1500.0;
  m_bFLS             = TRUE;
  m_bGridLines       = TRUE;
  m_dwVertices       = 0;
  m_dSamples		 = 0;
  m_bReceivedData    = FALSE;

  m_dwUniformSpacing = 0;
  m_dwNonUniformStart= 0;

  m_eLabelType		 = RANGE;

  AdjustPalette(m_cBrightness, m_cContrast);
}

CWedgeDisplay::~CWedgeDisplay()
{
  if(m_pModifiedTexture)
    delete m_pModifiedTexture;

  if(m_pPalette)
    delete m_pPalette;

  m_pModifiedTexture = m_pPalette = NULL;
}

BEGIN_MESSAGE_MAP(CWedgeDisplay, CWnd)
	//{{AFX_MSG_MAP(COpenGLBase)
  ON_WM_PAINT()
  ON_WM_ERASEBKGND()
  ON_WM_SIZE()
  ON_WM_KEYDOWN()
  ON_WM_MOUSEMOVE()
  ON_WM_LBUTTONDOWN()
  ON_WM_RBUTTONDOWN()
  ON_WM_TIMER()
 	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CWedgeDisplay::OnTimer(UINT uId)
{
  if(uId == 3)
  {
    Render(TRUE);
  }
}

void CWedgeDisplay::OnLButtonDown( UINT nFlags, CPoint point)
{
  //disabled beam selection for DVU
  return;

  if(!m_bGridLines)
	  return;

  double angle_offset, true_angle, range;
  DWORD inside;
  GLint viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];
  GLdouble wx, wy, wz;

  if(!m_bInit || !m_bReceivedData)
    return;

  m_lastPoint = point;
  m_flags	  = nFlags;

  SetCurrentContext();

  glLoadIdentity();			
  //glTranslated(m_fX, m_fY, m_fZ);

  glGetIntegerv(GL_VIEWPORT, viewport);
  glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
  
  gluUnProject(point.x, viewport[3] - 1 - point.y, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
 
  true_angle = atan2(wy, wx);
  if(true_angle < 0.0)
    true_angle = 2*PI + true_angle;

  range = sqrt(wx * wx + wy * wy); //m_stWedgeInfo.range;

  if(!m_bRectangular && !m_bStave)
  {
    inside = CheckInsideSector(true_angle);
    if(range < 1.001 && inside)
    {
      if(m_stWedgeInfo.first_beam > m_stWedgeInfo.last_beam)
        angle_offset     = m_stWedgeInfo.first_beam - true_angle;
      else
      {
        if(true_angle > m_stWedgeInfo.last_beam)
          angle_offset     = m_stWedgeInfo.first_beam + (2*PI - true_angle);
        else
          angle_offset     = m_stWedgeInfo.first_beam - true_angle;
      }

	  m_bLMouseDown    = TRUE;
      
	  m_dwSelectedBeam = (DWORD)floor(((angle_offset / m_stWedgeInfo.swath) * (m_stWedgeInfo.beams -1 )) + 0.5);     
	  
	  //Need to add handling for non-uniform spacing
	 

	  if(m_bFlip)
		  m_dwSelectedBeam = m_stWedgeInfo.beams - m_dwSelectedBeam;
	  		
	  //m_pParentWnd->SendMessage(WM_7KUISELECTEDBEAM, m_dwSelectedBeam);
	  
	  TRACE("SELECTED BEAM = %d\r\n", m_dwSelectedBeam);

	  //Calculate bottom detect and notify A-SCAN
	  if(!m_bFLS)
	  {
		  double inv_range = 1.0 / m_stWedgeInfo.range;
		  m_dLastRange = m_fBathyRanges[m_dwSelectedBeam] * m_dSoundVelocity * 0.5;
		  //m_pParentWnd->SendMessage(WM_7KUIBATHYRANGE, (UINT)m_dLastRange);
	  }
	  //update noise values
	  //double noise = ((BYTE)rand())/2;
	  //((C7kWedgeControlDlg*)m_pCtrlDlg)->SetSelectedBeamNoise(noise/100);

	  Render(TRUE);
    }
    else
    {
      m_bLMouseDown    = FALSE;
      Render(TRUE);
    }
  }
  else
  {
    double x;
  
    if(m_stWedgeInfo.swath < 180.1)
      x = cos((90.0 - m_stWedgeInfo.swath * 0.5 * R2D) * D2R);
    else // swath > 180
      x = 1.0;
  
    if(wx > (-x) && wx < (x - 0.000) && wy < (m_dMaxCoord - RECTANGULAR_OFFSET) && wy > (m_dMinCoord + RECTANGULAR_OFFSET))
    {
      m_bLMouseDown    = TRUE;
      
  	  m_dwSelectedBeam = (DWORD)floor((m_dwWidth)  * ((x + wx) / (x*2.0)) + 0.5);
	  
	  if(m_bFlip)
		 m_dwSelectedBeam =  m_stWedgeInfo.beams -  m_dwSelectedBeam;
		  
//	  m_pParentWnd->SendMessage(WM_7KUISELECTEDBEAM, m_dwSelectedBeam);

  	  TRACE("SELECTED BEAM = %d\r\n", m_dwSelectedBeam);

	   //Calculate bottom detect and notify A-SCAN
	  double inv_range = 1.0 / m_stWedgeInfo.range;
	  m_dLastRange = m_fBathyRanges[m_dwSelectedBeam] * m_dSoundVelocity * 0.5;
	  //m_pParentWnd->SendMessage(WM_7KUIBATHYRANGE, (UINT)m_dLastRange);

	  //update noise values
	  double noise = ((BYTE)rand())/10;
	  //((C7kWedgeControlDlg*)m_pCtrlDlg)->SetSelectedBeamNoise(noise/100);
    }
    else
    {
      m_bLMouseDown    = FALSE;
    }
	
  }

  Render(TRUE);

}


void CWedgeDisplay::OnRButtonDown(UINT nFlags, CPoint point) 
{

	Render(TRUE);
	
	//CPropertyPage::OnRButtonDown(nFlags, point);
}

void CWedgeDisplay::OnMouseMove(UINT nFlags, CPoint point)
{
  char text[64], text2[64];
  double range, true_angle, display_angle;
  GLint viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];
  GLdouble wx, wy, wz;
  DWORD inside = 0;

  double r = 0,b = 0;

  if(!m_bInit || !m_bReceivedData)
    return;

  SetCurrentContext();

  glLoadIdentity();			

  glGetIntegerv(GL_VIEWPORT, viewport);
  glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
  
  gluUnProject(point.x, viewport[3] - 1 - point.y, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);

  true_angle = atan2(wy, wx);
  if(true_angle < 0.0)
    true_angle = 2*PI + true_angle;
      
  range = sqrt(wx * wx + wy * wy);

  if(!m_bRectangular)
  {
    inside = CheckInsideSector(true_angle);

    if(range < 1.0001 && inside)
    {
	  display_angle = (true_angle - PI/2);
      if(display_angle > PI)
          display_angle = display_angle - 2*PI;
  	  
	  b = display_angle * R2D * -1.0;
	  
	  if( b == 180)
		  b = 0;
	  else if(b<0)
	  {
		b += 180;
		b *= -1;
	  }
	  else
	  {
		b -= 180;
		b *= -1;
	  }
	  
	  r = range * m_stWedgeInfo.range;
      
	  if(m_bFLS)
      {
        display_angle = (true_angle - PI/2);
        if(display_angle > PI)
          display_angle = display_angle - 2*PI;
      
		b = display_angle * R2D * -1.0;
		r = range * m_stWedgeInfo.range;

        sprintf(text, "Bearing: %.2lf°", display_angle * R2D * -1.0);
        sprintf(text2, "Range: %.2lfm", range * m_stWedgeInfo.range);
      }
      else
      {
        sprintf(text, "Depth: %.2lfm", fabs(sin(true_angle) * range) * m_stWedgeInfo.range);
        sprintf(text2, "Across Track: %.2lfm", fabs(cos(true_angle) * range) * m_stWedgeInfo.range);
      }

      if(m_bFreeze)
        Render(TRUE);
    }
    else
    {
      if(m_bFLS)
      {
        sprintf(text, "Bearing: --");
        sprintf(text2, "Range: --");
      }
      else
      {
        sprintf(text, "Depth: -- m");
        sprintf(text2, "Across Track: -- m");
      }
    }

    
  }
  else
  {
    if(m_bFLS)
    {
      sprintf(text, "Bearing: -- ");
      sprintf(text2, "Range: -- m");
    }
    else
    {
      sprintf(text, "Depth: -- m");
      sprintf(text2, "Across Track: -- m");
    }
  }

  //if(m_pCtrlDlg)
  //{
   // ((C7kWedgeControlDlg*)m_pCtrlDlg)->SetWedgeMeasure1(text);
    //((C7kWedgeControlDlg*)m_pCtrlDlg)->SetWedgeMeasure2(text2);

	//if(!m_bFLS)
	//	((C7kWedgeControlDlg*)m_pCtrlDlg)->SetRangeBearing(r,b);
  //}

  CWnd::OnMouseMove(nFlags, point);
}

void CWedgeDisplay::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);
	
	ResizeGL(cx, cy);
}

BOOL CWedgeDisplay::OnEraseBkgnd(CDC* pDC) 
{
  Render(TRUE);	        			// Draw The Scene

  return TRUE;
}

void CWedgeDisplay::OnPaint() 
{
	CPaintDC dc(this);      // device context for painting

	Render(TRUE);	        			// Draw The Scene

}

DWORD CWedgeDisplay::Render(BOOL flag)
{
  if(!m_bInit)
    return 0;

  SetCurrentContext();
  
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();			
   
  glEnable(GL_LINE_SMOOTH);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
  //glRotated(m_stWedgeInfo.wedge_angle, 0.0, 0.0, 1.0);
  
  if(m_bInitWedge && m_bReceivedData)
  {
    try
    {
	  
      if(!m_bRectangular && m_dwWidth == m_stWedgeInfo.beams) // Sector display and not element data.
      {
        //glTranslated(0.0, 0.0, 0.5);
        if(!DrawWedge())
			TRACE("WEDGE DRAW FAILED\r\n");

        //glTranslated(0.0, 0.0, -0.3);
        if(m_bGridLines)
          GridLines(0);
        
		if(m_bBathy && !m_bFLS)
          DrawBathy();
      }
      else if(m_bRectangular)
      {
        //glTranslated(0.0, 0.0, 0.5);
        DrawRectangular();
        //glTranslated(0.0, 0.0, -0.3);
        if(m_bGridLines)
          GridLinesRectangular();
      }
	  

    }
    catch(...)
    {
      TRACE("OpenGL Rendering crashed.\n");
    }
  }

  gl_setcolor(GLWHITE);
  glDisable(GL_LINE_SMOOTH);
  glDisable(GL_BLEND);

  SwapBuffers(m_hDC); // Swap buffers for double buffering.

  return 1;
}

DWORD CWedgeDisplay::DrawWedge()
{
  DWORD n;
  double tx, precalc;
  double h = ((double)m_dwHeight) / THEIGHT;

  gl_setcolor(GLWHITE);

  glEnable(GL_TEXTURE_2D);

  glBegin(GL_TRIANGLE_STRIP);

  precalc = ((m_stWedgeInfo.beams-1) * (1.0/TWIDTH)) / (m_dwVertices-1); // Should be / (m_dwVertices - 1) but OpenGL rounds off strange.

  if(!m_bFLS)
  {
	if(m_bFlip)//here was !
	{
		for (n=0; n<m_dwVertices; n++)
		{
			tx = n * precalc + precalc * 1.5;
			glTexCoord2d(tx, 0.0); glVertex2d(0.0, 0.0);  
			glTexCoord2d(tx, h - 0.001);   glVertex2d(cos_array[n], sin_array[n]);
		}
	}
	else
	{
		double divie = (double)m_stWedgeInfo.beams / TWIDTH;

		for (n=0; n<m_dwVertices; n++)
		{
			tx = divie - n * precalc - precalc * 1.5;
			glTexCoord2d(tx, 0.0); glVertex2d(0.0, 0.0);  
			glTexCoord2d(tx, h - 0.001);   glVertex2d(cos_array[n], sin_array[n]);
		}
	}
  }
  else
  {
	if(!m_bFlip)//here was !
	{
		for (n=0; n<m_dwVertices; n++)
		{
			tx = n * precalc + precalc * 1.5;
			glTexCoord2d(tx, 0.0); glVertex2d(0.0, 0.0);  
			glTexCoord2d(tx, h - 0.001);   glVertex2d(cos_array[n], sin_array[n]);
		}
	}
	else
	{
		double divie = (double)m_stWedgeInfo.beams / TWIDTH;

		for (n=0; n<m_dwVertices; n++)
		{
			tx = divie - n * precalc - precalc * 1.5;
			glTexCoord2d(tx, 0.0); glVertex2d(0.0, 0.0);  
			glTexCoord2d(tx, h - 0.001);   glVertex2d(cos_array[n], sin_array[n]);
		}
	}

  }
  glEnd();

  glDisable(GL_TEXTURE_2D);

  gl_setcolor(GLWHITE);

  if(!m_bGridLines)
	  return 1;

  
  //set this up first!  so we can use the 
  char labels[32];
  
  // Draw beam selection in wedge.
  if(m_bAScan && m_bLMouseDown)
  {
	double xx,yy,w1;
    
    if(m_dwSelectedBeam > 0)
	{
	  xx = cos_array[(m_dwSelectedBeam-1)*TRIANGLES];
	  yy = sin_array[(m_dwSelectedBeam-1)*TRIANGLES];
      gl_line(0.0f, 0.0f, xx, yy);
	}
	if(m_dwSelectedBeam < (m_stWedgeInfo.beams - 2))
	{
	  xx = cos_array[(m_dwSelectedBeam+1)*TRIANGLES];
	  yy = sin_array[(m_dwSelectedBeam+1)*TRIANGLES];
	  gl_line(0.0f, 0.0f, xx, yy);
	}

	
	
	//get the width of three digits
	//because max beam count is within
	//three digits and we want to keep
	//things aligned
	char dig[3];
	sprintf(dig,"%d",3);
	w1 = glGetTextWidth(dig);

	//add the fudge values so the text doesn't hit the wedge
	if(xx > 0)
		xx += w1;
	else
		xx -= w1*3;
	
	if(yy>0)
		yy += w1;
	else
		yy -= w1*2.5;

	//setup beam label
	//Increment beam number by one because
	//its more logical for users to see 
	//beam number one than zero.  This is also
	//done in the ASCAN class
    sprintf(labels, "%d", m_dwSelectedBeam+1);
	//Draw the beam number next to the wedge
	glRasterPos2d(xx,yy);    
	glPrint(labels);	

  }


  return 1;
}

DWORD CWedgeDisplay::InitWedge()
{
  
  DWORD n, m, pos;
  double swath, angle;

  m_dwNonUniformStart = 0;

  if(m_stWedgeInfo.first_beam < m_stWedgeInfo.last_beam)
    swath = 2*PI - m_stWedgeInfo.last_beam + m_stWedgeInfo.first_beam;
  else
    swath = m_stWedgeInfo.first_beam - m_stWedgeInfo.last_beam;

  m_stWedgeInfo.swath = swath;
  if(m_dwUniformSpacing > 0) 
  {
		m_stWedgeInfo.beams = m_dwUniformSpacing;
		for(n = 0; n < m_stWedgeInfo.beams; n++)
		{
			if(m_stWedgeInfo.beam_positions[n] != 0)
			{
				m_dwNonUniformStart = n;
				break;
			}
		}
  }

  m_dwVertices = m_stWedgeInfo.beams + (m_stWedgeInfo.beams-1) * (TRIANGLES-1);
    
  for(n=m_dwNonUniformStart; n<m_stWedgeInfo.beams-1+m_dwNonUniformStart; n++)
  {
      pos = (n-m_dwNonUniformStart) * TRIANGLES;
      if(m_stWedgeInfo.beam_positions[n] < m_stWedgeInfo.beam_positions[n+1])
        angle = (m_stWedgeInfo.beam_positions[n] + (2 * PI - m_stWedgeInfo.beam_positions[n+1])) / TRIANGLES;
      else
        angle = (m_stWedgeInfo.beam_positions[n] - m_stWedgeInfo.beam_positions[n+1]) / TRIANGLES;

      for(m=0;m<TRIANGLES;m++) 
      {
        cos_array[pos + m] = cos(m_stWedgeInfo.beam_positions[n] - angle * m);
        sin_array[pos + m] = sin(m_stWedgeInfo.beam_positions[n] - angle * m);
      }
  }

  pos = (n-m_dwNonUniformStart) * TRIANGLES; 
  cos_array[pos] = cos(m_stWedgeInfo.beam_positions[n]);
  sin_array[pos] = sin(m_stWedgeInfo.beam_positions[n]);

  for(n=0;n<m_dwVertices;n++)
  {
    if(sin_array[n] > m_dMaxCoord)
      m_dMaxCoord = sin_array[n];

    if(sin_array[n] < m_dMinCoord)
      m_dMinCoord = sin_array[n];
  }

  m_bInitWedge = TRUE;
    
  return 1;
}

DWORD CWedgeDisplay::GridLines(DWORD dwState)
{
  char labels[256];
  double grid_offset, heading, label_heading, w, h, min = 0.0, max = 0.0;
  DWORD m, n;
 
  double label_value;

  double label_scale = 1.0;
  char label[25];  
  
  if(!m_stWedgeInfo.beams || m_stWedgeInfo.swath < 0.1)
    return 0;

  glEnable(GL_LINE_SMOOTH);
  glEnable(GL_BLEND);

  gl_setcolor(GLRED);

  h = glGetTextHeight();

  grid_offset = 1.0;
  gl_line(0.0, 0.0, cos_array[0], sin_array[0]);

  // Dotted center line
  if(m_dMinCoord < -0.95)
    min = -1.0;

  if(m_dMaxCoord > 0.95)
    max = 1.0;

  gl_dotted_line(0.0, min, 0.0, max);
  
  gl_line(0.0, 0.0, cos_array[(m_stWedgeInfo.beams-1)*TRIANGLES], sin_array[(m_stWedgeInfo.beams-1)*TRIANGLES]);

  //Setup the grid labels
  switch(m_eLabelType)	
  {
    case TIME:	  { label_value = m_dTime; sprintf(label, "s");break;}	
    case SAMPLES: { label_value = (double)m_dSamples; sprintf(label, "S");break;}
    case RANGE:	
    default :	  { label_value = m_stWedgeInfo.range;sprintf(label, "m");break;}
	
  }
  
  if(m_bFLS)
  {
    // Heading marks and labels.
    for(n=0;n<12;n++)
    {
      heading = n * 30.0 * D2R;

      if(CheckInsideSector(heading - 0.01) || CheckInsideSector(heading + 0.01))
      {
        label_heading = (heading - PI/2);
        if(label_heading > PI)
          label_heading = label_heading - 2*PI;
        label_heading *= -1.0;

        sprintf(labels, "%.0lf°", label_heading * R2D);

        gl_line(1.0f * cos(heading), 1.0f * sin(heading), 1.01f * cos(heading), 1.01f * sin(heading));
        if(label_heading > 0.01)
          glRasterPos2d(1.025 * cos(heading), 1.025 * sin(heading) - glGetTextHeight() * 0.3);
        else if(label_heading < -0.01)
        {
          w = glGetTextWidth(labels);
          glRasterPos2d(1.010 * cos(heading) - w, 1.025 * sin(heading) - glGetTextHeight() * 0.3);
        }
        else
        {
          w = glGetTextWidth(labels);
          glRasterPos2d(cos(heading) - w * 0.5, 1.025 * sin(heading) - glGetTextHeight() * 0.3);
        }

        glPrint(labels);
      }
    }

	//Draw the outer line
	for (n=0; n<m_stWedgeInfo.beams-1;n++)
	{
	  gl_line(grid_offset * cos_array[n*TRIANGLES], grid_offset * sin_array[n*TRIANGLES], grid_offset * cos_array[(n+1)*TRIANGLES], grid_offset * sin_array[(n+1)*TRIANGLES]);	
	}

	//These are short horizontal depth lines and labels
	double diviediv = ((double)abs((max-min)))/5;
	for(m=0;m<5;m++)
	{
		//Draw the horizontal lines here...
		if(m != 0 && m != 5)
		{
			gl_line(-.1, min + diviediv*m, .1, min + diviediv*m);
			
			if(m_eLabelType == TIME)
				sprintf(labels, "%.1f%s", grid_offset * label_value, label);
			else
				sprintf(labels, "%g%s", grid_offset * label_value, label);
			glRasterPos2d(.1, min + diviediv*m);
			glPrint(labels);

			
		}
		grid_offset -= .2;
		
	}
  }
  else
  {
	  // Grid lines
	  for(m=0;m<5;m++)
	  {

		for (n=0; n<m_stWedgeInfo.beams-1;n++)
		{
		  gl_line(grid_offset * cos_array[n*TRIANGLES], grid_offset * sin_array[n*TRIANGLES], grid_offset * cos_array[(n+1)*TRIANGLES], grid_offset * sin_array[(n+1)*TRIANGLES]);
		}

		
		if(m_eLabelType == TIME)
			sprintf(labels, "%.1f%s", grid_offset * label_value, label);
		else
			sprintf(labels, "%g%s", grid_offset * label_value, label);

		w = glGetTextWidth(labels);
		h = glGetTextHeight();

		if(m_stWedgeInfo.first_beam < PI)
		{
		  glRasterPos2d(grid_offset * cos(m_stWedgeInfo.first_beam) - w, grid_offset * sin(m_stWedgeInfo.first_beam) - h*1.25);
		  glPrint(labels);
		  glRasterPos2d(grid_offset * cos(m_stWedgeInfo.last_beam), grid_offset * sin(m_stWedgeInfo.last_beam) - h*1.25);
		  glPrint(labels);
		}
		else
		{
		  //glRasterPos2d(0.01, grid_offset - h);
		  //glPrint(labels);
      
		  glRasterPos2d(grid_offset * cos(m_stWedgeInfo.first_beam)+.01, grid_offset * sin(m_stWedgeInfo.first_beam)+.01);
		  glPrint(labels);
		  glRasterPos2d(grid_offset * cos(m_stWedgeInfo.last_beam) - w+.01, grid_offset * sin(m_stWedgeInfo.last_beam)+.01);
		  glPrint(labels);
      
		}
    
		grid_offset -= 0.20f;
	  }
  }
 
/*
  // TODO: REMOVE!!!
  double line_width;
  gl_setcolor(WHITE);
  glGetDoublev(GL_LINE_WIDTH, &line_width);
  glLineWidth(2.0);
  grid_offset = 0.3;
  for (n=0; n<m_stWedgeInfo.beams-1;n++)
  {
      gl_line(grid_offset * cos_array[n*TRIANGLES], grid_offset * sin_array[n*TRIANGLES], grid_offset * cos_array[(n+1)*TRIANGLES], grid_offset * sin_array[(n+1)*TRIANGLES]);
  }
  glLineWidth(line_width);
  gl_setcolor(YELLOW);
*/
  
 

  gl_setcolor(GLWHITE);
  glDisable(GL_LINE_SMOOTH);
  glDisable(GL_BLEND);

  return 1;
}

DWORD CWedgeDisplay::SetInfo(WEDGEINFO * stWedgeInfo,DWORD devID, WORD sysEnum )
{
  memcpy(&m_stWedgeInfo, stWedgeInfo, sizeof(WEDGEINFO));
  m_dwDeviceId = devID; 
  m_wEnumerator = sysEnum;
  m_bFLS = !stWedgeInfo->wedge_type;

  m_stWedgeInfo.height_pixels = limit(m_stWedgeInfo.height_pixels, 0, THEIGHT);

  return 1;
}

DWORD CWedgeDisplay::SetSampleCount( DWORD	samples )
{
	m_dSamples  = samples;

	Render(TRUE);

	return 1;
}


DWORD CWedgeDisplay::SetData(BYTE *pData, DWORD dwWidth, DWORD dwHeight)
{
  DWORD w,h;
  DWORD * dest, * src;
  DWORD width, i;

  SetCurrentContext();

  if(m_bFreeze || !dwWidth || !dwHeight)
    return 1;

  m_dwWidth  = dwWidth;
  m_dwHeight = dwHeight;

  if(m_dwUniformSpacing > 0)
  {
  	m_dwWidth = m_dwUniformSpacing;
  }

  if(m_bHardwarePalette)
  {
    width = (dwWidth + 3) & -4;
    for(i=0; i<dwHeight; i++)
      memcpy(&m_pModifiedTexture[width*i], &pData[i*dwWidth], dwWidth);

    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, dwHeight, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, m_pModifiedTexture);
  }
  else
  {
    width = (dwWidth + 3) & -4;
    dest = (DWORD*)m_pModifiedTexture;
    src  = (DWORD*)m_pPalette;

    for(h=0;h<m_dwHeight;h++)
      for(w=0;w<m_dwWidth;w++)
        dest[h*width + w] = src[pData[h*m_dwWidth + w]];
 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, dwHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_pModifiedTexture);
  }

  m_bReceivedData = TRUE;

  //double noise = ((BYTE)rand())/2;
  //  ((C7kWedgeControlDlg*)m_pCtrlDlg)->SetAverageNoise(noise/100);

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::DownloadTexture()
{
  if(!m_pModifiedTexture || !m_pPalette)
  {
    m_bInit = FALSE;
    return 0;
  }

  PFNGLCOLORTABLEEXTPROC pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");

  if(!pfnColorTableEXT)
  {
    m_bHardwarePalette = FALSE;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, TWIDTH, THEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pModifiedTexture);
  }
  else
  {
   
    m_bHardwarePalette = TRUE;
    glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, TWIDTH, THEIGHT, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, m_pModifiedTexture);
  }

  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

  if(m_bHardwarePalette)
    pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_pPalette);

  return 1;
}

void CWedgeDisplay::RampColor(int first, int last, int r1, int g1, int b1, int r2, int g2, int b2)
{
  double r=r1+0.5, g=g1+0.5, b=b1+0.5, dr, dg, db;
  int i;


  if (last != first)
  {
    dr = (double)(r2-r1)/(double)(last-first);
    dg = (double)(g2-g1)/(double)(last-first);
    db = (double)(b2-b1)/(double)(last-first);
  }
  else
    dr = dg = db = 0;
  for (i=first; i<=last; i++,r+=dr,g+=dg,b+=db)
  {
    m_pPalette[0 + i*4] = (BYTE)r;   /* pack RGBA into 32 bits for OpenGL */
    m_pPalette[1 + i*4] = (BYTE)g;
    m_pPalette[2 + i*4] = (BYTE)b;
    m_pPalette[3 + i*4] = 255;
  }
}

//
//	23 March 2004 - fixed brightness and contrast adjustment. This contrast method
//                  does not use blanking, it is slope applied to entire curve. PR
//
//	NOTE: We'll possibly need to change the contrast to a logrithmic application.
//
DWORD CWedgeDisplay::AdjustPalette(BYTE cBrightness, BYTE cContrast)
{
	BYTE brit[256];					// Line/curve to be adjusted
	BYTE tempPalette[256 * 4];		// temp palette to hold values while we apply brit and cont
	BYTE i; 
	double contSlope, temp;
	int britScaleVal =0, contScaleVal=0, j=0;

	// The sliders are set with range 0 - 100, did this this way as cBrightness and cContrast
	// come in as BYTEs. Subtract 50 to get a -50 to 50 range, where 0 means no change.
	// The sliders are set in C7kWedgeSettingsDlg::OnInitDialog()
	britScaleVal = (int)cBrightness;// - SCROLLBRIGHTHALF; // SCROLLBRIGHTHALF == 50
	contScaleVal = (int)cContrast;// - SCROLLCONTRASTHALF; // SCROLLCONTRASTHALF == 50

	// Get the slope for the contrast, no blanking for contrast with this method
	contSlope = 255.0 / (255.0 - contScaleVal);

	for(j = 0; j < 256; j++)
	{
		temp = (double)j * contSlope;   // apply contrast
		temp += (double)britScaleVal;	// apply brightness

		if(temp <= 0)					// change our double values to BYTEs
			brit[j] = 0;
		else if(temp >= 255.0)
			brit[j] = (BYTE)255;
		else
			brit[j] = (BYTE)temp;
	}

	// Set the palette
	switch(m_dwPalette)
	{
		case 0:  // Blue-yellow palette
			RampColor(  0, 32,    4,  4, 32,    4, 32, 64);  /* dark blues */
			RampColor( 32, 48,    4, 32, 64,   16, 48, 80);
			RampColor( 48,208,   16, 48, 80,  176,208, 80);
			RampColor(208,240,  176,208, 80,  240,240, 48);
			RampColor(240,255,  240,240, 48,  255,255, 48);  /* bright yellows */
			break;
    
		case 1:  // Gray scale
		{
			i=0;
			do
			{
				m_pPalette[0 + i*4] = i; //cont[i];
				m_pPalette[1 + i*4] = i; //cont[i];
				m_pPalette[2 + i*4] = i; //cont[i];
				i++;
			} while(i);
			break;
		}
		case 2:
			RampColor(   0,  63,   0,  0,  64,    0,   0,255);
			RampColor(  64, 127,   0,  0, 255,    0, 255,255);
			RampColor( 128, 191,   0,255, 255,  255, 255,  0);
			RampColor( 192, 255, 255,255,   0,  255,   0,  0);
			break;

		case 3:
			{
			int r1 = 0;
		    int g1 = 0;
			int b1 = 0;
			//Semi-Rust
			int r2 = 161;
			int g2 = 45;
			int b2 = 4;
			//Yellow
			int r3 = 255;
			int g3 = 255;
			int b3 = 0;

			float rstep1 = (float)(r2-r1) / (float)(127-1);	
			float gstep1 = (float)(g2-g1) / (float)(127-1);	
			float bstep1 = (float)(b2-b1) / (float)(127-1);
		 
			float rstep2 = (float)(r3-r2) / (float)(128-1);	
			float gstep2 = (float)(g3-g2) / (float)(128-1);	
			float bstep2 = (float)(b3-b2) / (float)(128-1);	
		   
			for(int ii=0;ii<128;ii++)
			{   		
				m_pPalette[ii*4+0]  = (UCHAR)((float)r1 + (float)ii * rstep1);
				m_pPalette[ii*4+1]  = (UCHAR)((float)g1 + (float)ii * gstep1);
				m_pPalette[ii*4+2]  = (UCHAR)((float)b1 + (float)ii * bstep1);
				m_pPalette[ii*4+3]  = 255;
			}
		
			for(int jj=0;jj<128;jj++)
			{   
			
				m_pPalette[ii*4+0]	  = (UCHAR)((float)r2 + (float)jj * rstep2);
				m_pPalette[ii*4+1] = (UCHAR)((float)g2 + (float)jj * gstep2);
				m_pPalette[ii*4+2]  = (UCHAR)((float)b2 + (float)jj * bstep2);
				m_pPalette[ii*4+3]	= 255;
				ii++;
			}	
			break;
			}
		case 4: 
			{	//This should be reserved for the STAVE Display ONLY
				RampColor(   0, 51,  255,   0,   0,  255, 175,   0);  /* red -> orange    */
				RampColor(  51,102,  255, 175,   0,  255, 246,  80);  /* orange to yellow */
				RampColor( 102,153,  255, 246,   0,    0, 255,  15);  /* yellow to green  */
				RampColor( 153,204,    0, 255,  15,    0, 192, 255);  /* green to blue    */
				RampColor( 204,255,    0, 192, 255,   18,  23, 205);  /* bright yellows   */
				break;	
			}
		default:
			i=0;
			do
			{
				m_pPalette[0 + i*4] = i; //cont[i];
				m_pPalette[1 + i*4] = i; //cont[i];
				m_pPalette[2 + i*4] = i; //cont[i];
				i++;
			} while(i);
		break;
	}

	memcpy(tempPalette, m_pPalette, 256 * 4); // Use a temp palette as the order matters when we 
											  // decrease the brit or cont, else you end up w/ all dark
	for(i = 0; i < 256; i++)
	{
		m_pPalette[0 + i*4] = tempPalette[0 + brit[i]*4];
		m_pPalette[1 + i*4] = tempPalette[1 + brit[i]*4];
		m_pPalette[2 + i*4] = tempPalette[2 + brit[i]*4];
		if(i == 255) // need break as i is BYTE, otherwise loop is starting over with i==0
			break;	 // we end up in infinite loop.  
	}

	return 1;
}

DWORD CWedgeDisplay::ApplyPalette()
{
  PFNGLCOLORTABLEEXTPROC pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");

  if(m_bHardwarePalette)
    if(pfnColorTableEXT)
      if(m_pPalette)
        pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_pPalette);

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetContrast(BYTE cContrast)
{
  m_cContrast = cContrast;

  AdjustPalette(m_cBrightness, m_cContrast);

  ApplyPalette();

  return 1;
}

DWORD CWedgeDisplay::SetBrightness(BYTE cBrightness)
{
  m_cBrightness = cBrightness;

  AdjustPalette(m_cBrightness, m_cContrast);

  ApplyPalette();

  return 1;
}

DWORD CWedgeDisplay::SetFlip(BOOL bFlip)
{
  m_bFlip = bFlip;  

  //if(m_bFlip)
//	  m_pParentWnd->SendMessage(WM_7KUISELECTEDBEAM, m_stWedgeInfo.beams - m_dwSelectedBeam);
  //else
//	  m_pParentWnd->SendMessage(WM_7KUISELECTEDBEAM, m_dwSelectedBeam);

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetAScan(BOOL bAScan)
{
  m_bAScan = bAScan;

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetFreeze(BOOL bFreeze)
{
  m_bFreeze = bFreeze;

  return 1;
}


DWORD CWedgeDisplay::DrawRectangular()
{
  DWORD n;
  double tx, precalc, x;
  double h = (double)m_dwHeight / THEIGHT ;

  if(!m_stWedgeInfo.beams)
    return 0;
  
  gl_setcolor(GLWHITE);
  glEnable(GL_TEXTURE_2D);
  glBegin(GL_TRIANGLE_STRIP);

  float beam_scale;
  float label_scale = 1;
  char label[32];

  if(m_stWedgeInfo.swath*R2D < 180.1)
   x = cos((90.0 - m_stWedgeInfo.swath * 0.5 * R2D) * D2R);
  else
    x = 1.0f;
    
  //beam scale determines the width of the resuting image on the screen
  beam_scale = (float) ((x*2.0f) / (m_dwWidth-1));
  precalc    = 1.0/(TWIDTH-1);
  
  if(m_bFlip)
  {
	for (n=0; n<m_dwWidth; n++)
	{
	  tx = n * precalc;
	  glTexCoord2d(tx, h-0.02); glVertex2d(-x + (n * beam_scale), m_dMaxCoord - 0.10);  
	  glTexCoord2d(tx, 0.0);   glVertex2d(-x + (n * beam_scale), m_dMinCoord + 0.10);
	}
  }
  else
  {
	for (n=0; n<m_dwWidth; n++)
	{
	  tx = n * precalc;
	  glTexCoord2d(tx, h-0.02); glVertex2d(x - (n * beam_scale), m_dMaxCoord - 0.10);  
	  glTexCoord2d(tx, 0.0);   glVertex2d(x - (n * beam_scale), m_dMinCoord + 0.10);
	}
  }


  glEnd();
  glDisable(GL_TEXTURE_2D);

  if(!m_bGridLines)
	  return 1;

  double cx1; 
  
  //Draw in the Beam Select Marker
  if(m_bAScan && m_bLMouseDown)
  {
	gl_setcolor(GLWHITE);

	if(m_dwSelectedBeam >= 0)
	{
	  if(!m_bFLS)
	  {	  
		  cx1 = (-1.0f+((m_stWedgeInfo.beams - m_dwSelectedBeam)*beam_scale)+.03);
	  	  gl_line(cx1, -0.1f, cx1,-.9f);
		  gl_line(cx1+beam_scale, -0.1f, cx1+beam_scale,-.9f);
	  }
	  else
	  {
		  cx1 = (-.87f+((m_dwSelectedBeam)*beam_scale));
	  	  gl_line(cx1, 0.1f, cx1,.9f);
		  gl_line(cx1+beam_scale, 0.1f, cx1+beam_scale,.9f);
	  }
	}
  

	gl_setcolor(GLWHITE);

	
	if(!m_bStave)
	{
		
		//Again, we add one to the displayed 
		//beam number so that beam zero is 
		//beam one
		sprintf(label, "%d", m_dwSelectedBeam + 1);
		
		//Need to account for the flipping issues
		//when in FLS mode
		if(m_bFLS)
			glRasterPos2d(cx1+beam_scale,.92);
		else
			glRasterPos2d(cx1+beam_scale,-0.08);
				
		glPrint(label);
	}
	/*else
	{
		if(m_bFlip)
			sprintf(label, "%d", m_dwSelectedBeam * 289/m_stWedgeInfo.beams);
		else
			sprintf(label, "%d", (m_stWedgeInfo.beams - m_dwSelectedBeam) * 289/m_stWedgeInfo.beams);
		
		if(m_bFLS)
			glRasterPos2d(cx1+beam_scale,1.0);
		else
			glRasterPos2d(cx1+beam_scale,-0.08);
		
		glPrint(label);

	}
	*/
  }
  return 1;
}

DWORD CWedgeDisplay::GridLinesRectangular()
{
	//return 1;
  double x, h;
//  char labels[32];

  if(!m_stWedgeInfo.beams)
    return 0;

  glEnable(GL_LINE_SMOOTH);
  glEnable(GL_BLEND);
  gl_setcolor(GLRED);

  if(m_stWedgeInfo.swath < 180.1)
    x = cos((90.0 - m_stWedgeInfo.swath * 0.5 * R2D) * D2R);
  else // swath > 180
    x = 1.0;
  
  gl_line(-x, m_dMinCoord + RECTANGULAR_OFFSET, x, m_dMinCoord + RECTANGULAR_OFFSET);
  gl_line(x, m_dMinCoord + RECTANGULAR_OFFSET, x, m_dMaxCoord - RECTANGULAR_OFFSET);
  gl_line(x, m_dMaxCoord - RECTANGULAR_OFFSET, -x, m_dMaxCoord - RECTANGULAR_OFFSET);
  gl_line(-x, m_dMaxCoord - RECTANGULAR_OFFSET, -x, m_dMinCoord + RECTANGULAR_OFFSET);

  h = glGetTextHeight();

  double label_value;

  double label_scale = 1.0;
  char label[25];

  //Draw Y Axis labels
  //draw the labels
  char		labels[5];
  switch(m_eLabelType)
  {
  case TIME:	{ label_value = m_dTime; sprintf(labels, "s");break;}	
  case SAMPLES: { label_value = (double)m_dSamples; sprintf(labels, "S");break;}
  case RANGE:	
  default :		{ label_value = m_stWedgeInfo.range;sprintf(labels, "m");break;}
  
  }
  
  for(int i=0;i<YAXIS_DIV;i++)
  {
    sprintf(label, "%.0lf%s", label_value * label_scale, labels);
    glRasterPos2f(float(x+.005f), (float)m_dMaxCoord - (float)RECTANGULAR_OFFSET - i*(((float)m_dMaxCoord - (float)m_dMinCoord - (float)RECTANGULAR_OFFSET/2.0f)/YAXIS_DIV)/*0.198f*/ - glGetTextHeight() * 0.5f);
    glPrint(label);
    label_scale = label_scale - .2f;
	if(label_scale < 0)
		label_scale = 0;
  } 
 
  if(m_bStave)
	  label_value = 287;
  else
	  label_value = m_stWedgeInfo.beams;

  label_scale = 1.0;
  /*
  for( i=0;i<XAXIS_DIV;i++)
  {
	sprintf(label, "%.0lf", label_value - label_value * label_scale);
	glRasterPos2f(0, -1.0f);
	glPrint(label);
	label_scale -= 0.111f;
  } 
*/

  double inc = (label_value/10.0f);
  if(!m_bFlip)
  {
	  for(i=0;i<=XAXIS_DIV;i++)
	  {
		sprintf(label, "%d", abs((int)floor(label_value+.5)) );
		//glRasterPos2f(float(-x + i*0.21f) - glGetTextWidth(label) * 0.5f, (float)m_dMinCoord + RECTANGULAR_OFFSET -.03f);
		glRasterPos2f(float(x - i*((x*2)/XAXIS_DIV))- glGetTextWidth(label), (float)m_dMinCoord + RECTANGULAR_OFFSET -.03f);
		glPrint(label);
		label_value = label_value - inc;
		if(label_value < 1)
			label_value = 1;
		//label_scale -= label_scale/XAXIS_DIV;
	  }
  }
  else
  {
	  for(i=0;i<=XAXIS_DIV;i++)
	  {
		sprintf(label, "%d", abs((int)floor(label_value)));
		glRasterPos2f(float(-x + i*((x*2)/XAXIS_DIV))- glGetTextWidth(label), (float)m_dMinCoord + RECTANGULAR_OFFSET -.03f);
		glPrint(label);
		label_value -= inc;
		if(label_value < 1)
			label_value = 1;
	  }
  }
  
  /*
  sprintf(labels, "%.0lfm", m_stWedgeInfo.range);
  w = glGetTextWidth(labels);
  glRasterPos2d(-x + w * 1.25, m_dMaxCoord - RECTANGULAR_OFFSET + 0.02 );
  glPrint(labels);
  glRasterPos2d(+x - w * 0.25, m_dMaxCoord - RECTANGULAR_OFFSET + 0.02);
  glPrint(labels);

  sprintf(labels, "0m");
  w = glGetTextWidth(labels);
  glRasterPos2d(-x + w * 1.25 + .04, m_dMinCoord + RECTANGULAR_OFFSET -.03);
  glPrint(labels);
  glRasterPos2d(+x - w * 0.25, m_dMinCoord + RECTANGULAR_OFFSET - .03);
  glPrint(labels);
  */

  glDisable(GL_LINE_SMOOTH);
  glDisable(GL_BLEND);

  return 1;
}

DWORD CWedgeDisplay::SetRectangular(BOOL bRectangular)
{
  m_bRectangular = bRectangular;

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetStave(	BOOL bStaveOn )
{
  if(bStaveOn)
  {
//      m_pParentWnd->SendMessage(WM_7KSTAVEON, 1);
  }
  else
  {
   //   m_pParentWnd->SendMessage(WM_7KSTAVEON, 0);
  }

  m_bStave = bStaveOn;

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetParent(CWnd * pParentWnd, CWnd * pCtrlDlg)
{
  m_pParentWnd = pParentWnd;
  m_pCtrlDlg   = pCtrlDlg;

  return 1;
}

DWORD CWedgeDisplay::SetRange(double dRange)
{
  m_stWedgeInfo.range = dRange;
  
  //OnLButtonDown(m_flags, m_lastPoint);

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetTime( double dTime )
{
	m_dTime = dTime;

	Render(TRUE);

	return 1;
}

//
//	dwUniformSpacing == zero if we have uniform spacing
//
DWORD CWedgeDisplay::SetWedgeGeometry(DWORD dwBeams, double dFirstBeam, double dLastBeam, float * pAllBeams, DWORD dwUniformSpacing)
{
  m_stWedgeInfo.beams      = dwBeams;
  m_stWedgeInfo.first_beam = dFirstBeam;
  m_stWedgeInfo.last_beam  = dLastBeam;

  m_dwUniformSpacing = dwUniformSpacing;

  memcpy(m_stWedgeInfo.beam_positions, pAllBeams, dwBeams * 4);
  
  InitWedge();

  return 1;
}

DWORD CWedgeDisplay::SetPalette(DWORD dwPalette)
{
  m_dwPalette = dwPalette;
  AdjustPalette(m_cBrightness, m_cContrast);
  ApplyPalette();

  return 1;
} 

DWORD CWedgeDisplay::SetOrtho()
{
  double ratio, height, aspect, half_width, current_ratio; 

  height = fabs(m_dMaxCoord) + fabs(m_dMinCoord);
  ratio  = 0.5 * height;

  if(m_stWedgeInfo.swath < PI)
    half_width = cos((90.0 - m_stWedgeInfo.swath * 0.5 * R2D) * D2R) + .15;
  else
    half_width = 1.0f + .2f;
  
  current_ratio = (double)m_x / m_y;
  
  aspect        = half_width*2.0 / height;
    
  // Calculate The Aspect Ratio Of The Window
  if(aspect < current_ratio)
    glOrtho(-ratio*current_ratio, ratio*current_ratio , m_dMinCoord, m_dMaxCoord, 0.0, -1.0);
  else
    glOrtho(-half_width, half_width, m_dMinCoord + (1.0/aspect - (double)m_y/m_x), m_dMaxCoord - (1.0/aspect - (double)m_y/m_x), 0.0, -1.0);

  return 1;
}


DWORD CWedgeDisplay::ResizeGL(int x, int y)
{
  //if(m_bRectangular)
  //	  m_x -= m_x*.1;

  m_y = y = y ? y : 1;
  m_x = x = x ? x : 1;
  
  if(!m_bInit)
    return 0;
  
  wglMakeCurrent(m_hDC, m_hRC);

  glViewport(0, 0, x, y);

  glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();							          // Reset The Projection Matrix

//remove this?
  SetOrtho();  

	glMatrixMode(GL_MODELVIEW);						  // Select The Modelview Matrix
  
  Render(TRUE);				                        // Draw The Scene

  return 1;
}

//glOrtho(-ratio*y/x, ratio*x/y, m_dMinCoord, m_dMaxCoord, 0.0, 1.0);

DWORD CWedgeDisplay::SetCurrentContext()
{
  if(!wglMakeCurrent(m_hDC, m_hRC))
  {
    TRACE("wglMakeCurrent failed, %u\n", GetLastError());
    return 0;
  }

  glViewport(0, 0, m_x, m_y);

  glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();							          // Reset The Projection Matrix
  
  SetOrtho();

	glMatrixMode(GL_MODELVIEW);						  // Select The Modelview Matrix

  return 1;
}

DWORD CWedgeDisplay::CheckInsideSector(double dAngle)
{
  if(m_stWedgeInfo.last_beam > m_stWedgeInfo.first_beam)
  {
    if(dAngle > m_stWedgeInfo.last_beam)
    {
      return 1;
    }

    if(dAngle < m_stWedgeInfo.first_beam)
    {
      return 1;
    }
  }
  else
  {
    if(dAngle < m_stWedgeInfo.first_beam && dAngle > m_stWedgeInfo.last_beam)
    {
      return 1;
    }
  }

  return 0;
}

DWORD CWedgeDisplay::SetBathyData(BYTE *pData, double dSoundVelocity)
{
  if(m_stWedgeInfo.beams == 0)
	  return 0;

  memcpy(m_fBathyRanges, pData, m_stWedgeInfo.beams*4);

  m_dSoundVelocity = dSoundVelocity;

  double inv_range = 1.0 / m_stWedgeInfo.range;
  m_dLastRange = m_fBathyRanges[m_dwSelectedBeam] * m_dSoundVelocity * 0.5;

  return 1;
}

DWORD CWedgeDisplay::DrawBathy()
{
  if(m_stWedgeInfo.beams == 0)
	return 0;
  
  DWORD i;
  double range, inv_range;

  inv_range = 1.0 / m_stWedgeInfo.range;

  gl_setcolor(GLGREEN);
  glPointSize(3.0);
  
  if( !m_bFlip)
  {
	for(i=0;i<=m_stWedgeInfo.beams;i++)
	{
			// check to see if the displayed value will exceed the wedge range
			if((m_fBathyRanges[m_stWedgeInfo.beams-i] * m_dSoundVelocity * 0.5) < m_stWedgeInfo.range)
			{
				range = m_fBathyRanges[m_stWedgeInfo.beams-i] * m_dSoundVelocity * inv_range * 0.5;

				//if((m_fBathyRanges[i] * m_dSoundVelocity * 0.5))

				gl_putpixel(range * cos(m_stWedgeInfo.beam_positions[i-1]), range * sin(m_stWedgeInfo.beam_positions[i-1]));
			}
	}
  }
  else
  {
	  for(i=0;i<m_stWedgeInfo.beams;i++)
	  {	
			// check to see if the displayed value will exceed the wedge range
			if((m_fBathyRanges[i] * m_dSoundVelocity * 0.5) < m_stWedgeInfo.range)
			{
				range = m_fBathyRanges[i] * m_dSoundVelocity * inv_range * 0.5;

				//if((m_fBathyRanges[i] * m_dSoundVelocity * 0.5))

				gl_putpixel(range * cos(m_stWedgeInfo.beam_positions[i]), range * sin(m_stWedgeInfo.beam_positions[i]));
			}
	  }

  }
    

  glPointSize(1.0);


  return 1;
}

DWORD CWedgeDisplay::SetFLS(BOOL bFLS)
{
  m_bFLS = bFLS;
  
  return 1;
}

DWORD CWedgeDisplay::SetLabels( UINT labeltype )
{

	m_eLabelType = (LABELS)labeltype;

	Render(TRUE);

	return 1;

}

DWORD CWedgeDisplay::ToggleGridLines()
{
  m_bGridLines = !m_bGridLines;

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::SetGridLines(BOOL bGridLines)
{
  m_bGridLines = bGridLines;

  Render(TRUE);

  return 1;
}

DWORD CWedgeDisplay::BathyPoints(BOOL bOn)
{
	m_bBathy = bOn;

	Render(TRUE);

	return 1;
}


void CWedgeDisplay::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{	
	CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}