double CEnvironmentData::xGetUnitlessUnitSquareResolution()
{
	if(IsDataLoaded() == FALSE || m_dimensionType == ENVDAT_4D)
		return -1.0;

	return GetXUnitlessResolution() * GetYUnitlessResolution();
}
bool CDX9TextureObject::ReadyData()
{
	// if our data is loaded, we are ready
	if (IsDataLoaded())
		return true;

	// try to get the data loaded
	LOADFILEEXTPARAMS lfep;
	lfep.fileName = const_cast<TCHAR*>((const TCHAR*)GetName()->GetString());
	lfep.bInternalLoad = true;
	static DWORD msgHash_LoadFileByExtension = CHashString(_T("LoadFileByExtension")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_LoadFileByExtension, sizeof(LOADFILEEXTPARAMS), &lfep);				

	// return whether our data was loaded
	return IsDataLoaded();
}
double CEnvironmentData::GetYUnitlessResolution()
{
	if(IsDataLoaded() == FALSE || m_dimensionType == ENVDAT_4D)
		return -1.0;

	// The following assumes regular spacing in the environment file
	return  m_fY[1] - m_fY[0];
}
double CEnvironmentData::SetConstantValue(double Value)
{
	if(IsDataLoaded() == TRUE)
		ClearData();
	m_noDataLoadedValue = Value;

	//_ASSERT(0);
	m_bathyConstantSet = TRUE;
	return m_noDataLoadedValue;
}
// Lat is X
// Lon is Y
BOOL CEnvironmentData::CheckMetersPerCoord()
{
	int x,y;
	double deltaLat, deltaLon;
	double maxLatDelta, minLatDelta;
	double maxLonDelta, minLonDelta;

	if(IsDataLoaded() == FALSE)
		return TRUE;

	maxLatDelta = minLatDelta = fabs(m_staticLib.MetersBetweenCoordinates(m_fX[0], m_fY[0], m_fX[1], m_fY[0]));
	maxLonDelta = minLonDelta = fabs(m_staticLib.MetersBetweenCoordinates(m_fX[0], m_fY[0], m_fX[0], m_fY[1]));


	// Check each Lon for every Lat
	for(x=0; x<m_nXlen-1; x++)
	{
		for(y=0; y<m_nYlen-1; y++)
		{
			// Very Lat, keep lon constant
			deltaLat = fabs(m_staticLib.MetersBetweenCoordinates(m_fX[x], m_fY[y], m_fX[x+1], m_fY[y]));
			if(maxLatDelta < deltaLat)
				maxLatDelta = deltaLat;
			if(minLatDelta > deltaLat)
				minLatDelta = deltaLat;


			// Very Lon, keep lat constant
			deltaLon = fabs(m_staticLib.MetersBetweenCoordinates(m_fX[x], m_fY[y], m_fX[x], m_fY[y+1]));
			if(maxLonDelta < deltaLon)
				maxLonDelta = deltaLon;
			if(minLonDelta > deltaLon)
				minLonDelta = deltaLon;
		}
	}
	return TRUE;
}
ENVMINMAX CEnvironmentData::GetExtremes()
{
	ENVMINMAX mm;

	memset(&mm, 0, sizeof(ENVMINMAX));

	if(IsDataLoaded() == FALSE)
	{
		mm.xMax = 5000000000;
		mm.xMin = -5000000000;
		mm.yMax = 5000000000;
		mm.yMin = -5000000000;
		mm.v1Max = 5000000000;
		mm.v1Min = -5000000000;
		mm.v2Max = 5000000000;
		mm.v2Min = -5000000000;
		return mm;
	}

	mm.xMin = m_minX;
	mm.xMax = m_maxX;

	mm.yMin = m_minY;
	mm.yMax = m_maxY;

	mm.zMin = m_minZ;
	mm.zMax = m_maxZ;

	mm.v1Min = m_minV1;
	mm.v1Max = m_maxV1;

	mm.v2Min = m_minV2;
	mm.v2Max = m_maxV2;

	return mm;
}
double CEnvironmentData::
GetValueAtCoordinate(double X, double Y, double Z, ENVDATA_INDEX *Sector, double *SecondValue)
{
	int x1, x2, y1, y2, z1 = -1, z2 = -1;
	int i1, i2, i3, i4;
	double t,u;
	double val = 0;

	if(IsDataLoaded() == FALSE)
		return m_noDataLoadedValue;

	// Check that the Sector param passed in was initialized or that it has at the very
	// least reasonable values.  The values in Sector (x, y, and z) are only locations to
	// begin searching.  If set to zero, it searches at the begining of that dimension.
	// This is in place to speed up the retrieval of environmental data.
	if(Sector->x < 0)
		Sector->x = 0;
	if(Sector->x >= m_nXlen)
		Sector->x = m_nXlen-1;

	if(Sector->y < 0)
		Sector->y = 0;
	if(Sector->y >= m_nYlen)
		Sector->y = m_nYlen-1;

	if(GetNumDimensions() == 2 || Sector->z < 0)
		Sector->z = 0;
	else if(Sector->z >= m_nZlen)
		Sector->z = m_nZlen-1;

	//------------------------------------------------------------------------------------//
	// Seach the X dimension
	//************************************************************************************//
	// Begin the search starting near the last sector
	//************************************************************************************//
	x1 = FindDimensionIndex(X, Sector->x, m_fX, m_nXlen);
	y1 = FindDimensionIndex(Y, Sector->y, m_fY, m_nYlen);

	//------------------------------------------------------------------------------------//
	// Seach the Z dimension (if 3-D data)
	// Test boundary cases.
	if(m_dimensionType == ENVDAT_4D)
		z1 = FindDimensionIndex(Z, Sector->z, m_fZ, m_nZlen);

	x2 = Sector->x = x1;
	y2 = Sector->y = y1;
	z2 = Sector->z = z1;

	if(x2+1 < m_nXlen)
		x2++;
	if(y2+1 < m_nYlen)
		y2++;
	if(z2+1 < m_nZlen)
		z2++;

	switch(m_dimensionType)
	{
	case ENVDAT_3Dx2V:
		_ASSERT(m_fV2 != NULL);
		// No break.  Fall through to ENVDAT_3D

	case ENVDAT_3D:
		// Do bilinear interpolation
		t = (Y - m_fY[y1])/(m_fY[y2] - m_fY[y1]);
		u = (X - m_fX[x1])/(m_fX[x2] - m_fX[x1]);
		i1 = x1 * m_nYlen + y1;
		i2 = x1 * m_nYlen + y2;
		i3 = x2 * m_nYlen + y1;
		i4 = x2 * m_nYlen + y2;

		_ASSERT(i1 < m_nVlen);
		_ASSERT(i2 < m_nVlen);
		_ASSERT(i3 < m_nVlen);
		_ASSERT(i4 < m_nVlen);


		if(m_fV1[i1] == m_fV1[i2] && m_fV1[i1] == m_fV1[i3] && m_fV1[i1] == m_fV1[i4])
		{
			val = m_fV1[i1];

			if(m_dimensionType == ENVDAT_3Dx2V && SecondValue != NULL && m_fV2 != NULL)
				*SecondValue = m_fV2[i1];
		}
		else
		{
			val =
				(1-t) * (1-u) * m_fV1[i1] +
				( t ) * (1-u) * m_fV1[i2] +
				(1-t) * ( u ) * m_fV1[i3] +
				( t ) * ( u ) * m_fV1[i4];

			if(m_dimensionType == ENVDAT_3Dx2V && SecondValue != NULL && m_fV2 != NULL)
			{
				*SecondValue =
					(1-t) * (1-u) * m_fV2[i1] +
					( t ) * (1-u) * m_fV2[i2] +
					(1-t) * ( u ) * m_fV2[i3] +
					( t ) * ( u ) * m_fV2[i4];
			}
		}
		break;

	case ENVDAT_4D:
		// Do Trilinear interpolation
		double xf, yf, zf;
		double i1, i2, j1, j2, w1, w2;
		int x1Index, x2Index, y1Index, y2Index;

		x1Index = x1*m_nYlen*m_nZlen;
		x2Index = x2*m_nYlen*m_nZlen;
		y1Index = y1*m_nZlen;
		y2Index = y2*m_nZlen;

		xf = X - floor(X);
		yf = Y - floor(Y);
		zf = Z - floor(Z);

		_ASSERT(x1Index + y1Index + z1 < m_nVlen);
		_ASSERT(x1Index + y1Index + z2 < m_nVlen);
		_ASSERT(x1Index + y2Index + z1 < m_nVlen);
		_ASSERT(x1Index + y2Index + z2 < m_nVlen);


		_ASSERT(x2Index + y1Index + z1 < m_nVlen);
		_ASSERT(x2Index + y1Index + z2 < m_nVlen);
		_ASSERT(x2Index + y2Index + z1 < m_nVlen);
		_ASSERT(x2Index + y2Index + z2 < m_nVlen);


		i1 = m_fV1[x1Index + y1Index + z1]*(1-zf) + m_fV1[x1Index + y1Index + z2]*zf;
		i2 = m_fV1[x1Index + y2Index + z1]*(1-zf) + m_fV1[x1Index + y2Index + z2]*zf;

		j1 = m_fV1[x2Index + y1Index + z1]*(1-zf) + m_fV1[x2Index + y1Index + z2]*zf;
		j2 = m_fV1[x2Index + y2Index + z1]*(1-zf) + m_fV1[x2Index + y2Index + z2]*zf;

		w1 = i1*(1-yf) + i2*yf;
		w2 = j1*(1-yf) + j2*yf;

		val = w1*(1-xf) + w2*xf;
		break;
	}
	return val;
}
double CEnvironmentData::
GetValueAtCoordinateSansExtrapolation(double X, double Y, double Z, ENVDATA_INDEX *Sector, double *SecondValue)
{
	int x1, x2, y1, y2, z1 = -1, z2 = -1;
	int i1, i2, i3, i4;
	double val = 0;

	if(IsDataLoaded() == FALSE)
		return m_noDataLoadedValue;

	// Check that the Sector param passed in was initialized or that it has at the very
	// least reasonable values.  The values in Sector (x, y, and z) are only locations to
	// begin searching.  If set to zero, it searches at the begining of that dimension.
	// This is in place to speed up the retrieval of environmental data.
	if(Sector->x < 0)
		Sector->x = 0;
	if(Sector->x >= m_nXlen)
		Sector->x = m_nXlen-1;

	if(Sector->y < 0)
		Sector->y = 0;
	if(Sector->y >= m_nYlen)
		Sector->y = m_nYlen-1;

	if(GetNumDimensions() == 2 || Sector->z < 0)
		Sector->z = 0;
	else if(Sector->z >= m_nZlen)
		Sector->z = m_nZlen-1;

	//------------------------------------------------------------------------------------//
	// Seach the X dimension
	//************************************************************************************//
	// Begin the search starting near the last sector
	//************************************************************************************//
	x1 = FindDimensionIndexSansInterpolation(X, m_fX, m_nXlen);

	y1 = FindDimensionIndexSansInterpolation(Y, m_fY, m_nYlen);

	//------------------------------------------------------------------------------------//
	// Seach the Z dimension (if 3-D data)
	// Test boundary cases.
	if(m_dimensionType == ENVDAT_4D)
	{
		// Not immplemented.
		_ASSERT(FALSE);
		z1 = FindDimensionIndex(Z, Sector->z, m_fZ, m_nZlen);
	}

	x2 = Sector->x = x1;
	y2 = Sector->y = y1;
	z2 = Sector->z = z1;

	if(x2+1 < m_nXlen)
		x2++;
	if(y2+1 < m_nYlen)
		y2++;
	if(z2+1 < m_nZlen)
		z2++;

	switch(m_dimensionType)
	{
	case ENVDAT_3Dx2V:
		_ASSERT(m_fV2 != NULL);
		// No break.  Fall through to ENVDAT_3D

	case ENVDAT_3D:
		i1 = x1 * m_nYlen + y1;
		i2 = x1 * m_nYlen + y2;
		i3 = x2 * m_nYlen + y1;
		i4 = x2 * m_nYlen + y2;

		_ASSERT(i1 < m_nVlen);
		_ASSERT(i2 < m_nVlen);
		_ASSERT(i3 < m_nVlen);
		_ASSERT(i4 < m_nVlen);


		// This needs an improvement... specifically, if the indices are invalied (that's why
		// they'd be -1) there needs to be a return type that indicates this.
		if(x1 == -1 || y1 == -1)
			val = 0;
		else
			val = m_fV1[i1];

		if(m_dimensionType == ENVDAT_3Dx2V && SecondValue != NULL && m_fV2 != NULL)
		{
			if(x1 == -1 || y1 == -1)
				*SecondValue = 0;
			else
				*SecondValue = m_fV2[i1];
		}
		break;

	case ENVDAT_4D:
		// Do Trilinear interpolation
		// Not immplemented.
		_ASSERT(FALSE);
		val = 0;
		if(SecondValue != NULL)
			*SecondValue = 0;
	}
	return val;
}
double CEnvironmentData::CalculateUnitlessSurfaceAreaAtPlane(double Xi, double Yi, double Xf, double Yf, double Zplane)
{
	int xIndexStart, xIndexEnd, yIndexStart, yIndexEnd, i, j;
	double v00, v01, v10, v11 = 0;
	int cnt;
	//double squareArea=0;
	double surfaceArea = 0.0;
	double totalSquares = m_nYlen * m_nXlen;

	if(IsDataLoaded() == FALSE || m_dimensionType == ENVDAT_4D)
		return -1.0;

	if(Xf < Xi)
	{
		v00 = Xf;
		Xf = Xi;
		Xi = v00;
	}
	if(Yf < Yi)
	{
		v00 = Yf;
		Yf = Yi;
		Yi = v00;
	}


	// The following assumes regular spacing in the environment file
//	squareArea =  /*x*/ (m_fX[1] - m_fX[0]) * /*y*/ (m_fY[1] - m_fY[0]);

	//------------------------------------------------------------------------------------//
	// Find the x and y indexes for the given initial and final coordinates.
	//---------------------------------------------------------------------/
	xIndexStart = FindDimensionIndex(Xi, 0, m_fX, m_nXlen);
	yIndexStart = FindDimensionIndex(Yi, 0, m_fY, m_nYlen);
	xIndexEnd = FindDimensionIndex(Xf, 0, m_fX, m_nXlen);
	yIndexEnd = FindDimensionIndex(Yf, 0, m_fY, m_nYlen);

	// Look into reasoning for having to do this...
	if(xIndexStart == m_nXlen-2)
		xIndexStart += 2;
	if(xIndexEnd == m_nXlen-2)
		xIndexEnd += 2;
	if(yIndexStart == m_nYlen-2)
		yIndexStart += 2;
	if(yIndexEnd == m_nYlen-2)
		yIndexEnd += 2;


	for(i=xIndexStart; i<xIndexEnd-1; i++)
	{
		for(j=yIndexStart; j<yIndexEnd-1; j++)
		{
			cnt = 0;

			_ASSERT((i+0) * m_nYlen + (j+0) < m_nVlen);
			_ASSERT((i+0) * m_nYlen + (j+1) < m_nVlen);
			_ASSERT((i+1) * m_nYlen + (j+0) < m_nVlen);
			_ASSERT((i+1) * m_nYlen + (j+1) < m_nVlen);

			v00 = m_fV1[(i) * m_nYlen + (j)];
			if(v00 >= Zplane)
				cnt++;

			v01 = m_fV1[(i) * m_nYlen + (j+1)];
			if(v01 >= Zplane)
				cnt++;

			v10 = m_fV1[(i+1) * m_nYlen + (j)];
			if(v10 >= Zplane)
				cnt++;


			v11 = m_fV1[(i+1) * m_nYlen + (j+1)];
			if(v11 >= Zplane)
				cnt++;

			if(cnt == 3)
				surfaceArea += 0.5;// * squareArea;
			else if(cnt == 4)
				surfaceArea += 1;//squareArea;
		}
	}
	surfaceArea = surfaceArea/totalSquares;
	return surfaceArea;
}