/*ScianIsoCalcDelta.h
  Eric Pepke
  23 March 1993

  Very evil include "macro" for calculating deltas in isosurfaces.  Delta is
  not an accurate reflection of the gradient, but is the gradient normalized
  to length one.  Since we're normalizing after the average, who cares?

Requires

	HEREC		coordinates here
	HEREV		value here
	FIELDHERE	field here
	coord		coordinates field number
	fieldNum	data field number

Optional
	NEXTFIELD	field in +z
	PREVFIELD	field in -z
	PLUSIC		coordinates in plus i
	MINUSIC		coordinates in minus i
	PLUSJC		coordinates in plus j
	MINUSJC		coordinates in minus j
	PLUSKC		coordinates in plus k
	MINUSKC		coordinates in minus k
*/

{
    register long localOffset;
    register real ds;		/*Change in scalar field*/
    register real r;		/*Length of vector, squared*/
    register real w;		/*Weight of vector*/
    register real tx, ty, tz;	/*Total delta*/
    register real dx, dy, dz;	/*Delta*/

    localOffset = index[0] * dims[1] + index[1];

    if (deltas[localOffset * 3] == missingData)
    {
	tx = 0.0;
	ty = 0.0;
	tz = 0.0;

	/*Minus i direction*/
	if (index[0] > 0)
	{
	    localOffset -= dims[1];
	    --index[0];
#ifdef MINUSIC
	    dx = MINUSIC[0] - HEREC[0]; 
	    dy = MINUSIC[1] - HEREC[1]; 
	    dz = MINUSIC[2] - HEREC[2]; 
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif
	    ds = FIELDHERE[localOffset] - HEREV;

	    ++index[0];
	    localOffset += dims[1];

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Plus i direction*/
	if (index[0] < dims[0] - 1)
	{
	    localOffset += dims[1];
	    ++index[0];
#ifdef PLUSIC
	    dx = PLUSIC[0] - HEREC[0]; 
	    dy = PLUSIC[1] - HEREC[1]; 
	    dz = PLUSIC[2] - HEREC[2]; 
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif
	    ds = FIELDHERE[localOffset] - HEREV;

	    --index[0];
	    localOffset -= dims[1];

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Minus j direction*/
	if (index[1] > 0)
	{
	    --localOffset;
	    --index[1];
#ifdef MINUSJC
	    dx = MINUSJC[0] - HEREC[0]; 
	    dy = MINUSJC[1] - HEREC[1]; 
	    dz = MINUSJC[2] - HEREC[2]; 
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif
	    ds = FIELDHERE[localOffset] - HEREV;

	    ++index[1];
	    ++localOffset;

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Plus j direction*/
	if (index[1] < dims[1] - 1)
	{
	    ++localOffset;
	    ++index[1];
#ifdef PLUSJC
	    dx = PLUSJC[0] - HEREC[0]; 
	    dy = PLUSJC[1] - HEREC[1]; 
	    dz = PLUSJC[2] - HEREC[2]; 
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif
	    ds = FIELDHERE[localOffset] - HEREV;

	    --index[1];
	    --localOffset;

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Minus k direction*/
	if (index[2] > 0)
	{
	    --index[2];

#ifdef MINUSKC
	    dx = MINUSKC[0] - HEREC[0];
	    dy = MINUSKC[1] - HEREC[1];
	    dz = MINUSKC[2] - HEREC[2];
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif


#ifdef PREVFIELD
	    ds = PREVFIELD[localOffset] - HEREV;
#else
	    ds = SelectFieldScalar(fieldNum, index) - HEREV;
#endif
	    ++index[2];

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Plus k direction*/
	if (index[2] < dims[2] - 1)
	{
	    ++index[2];
#ifdef PLUSKC
	    dx = PLUSKC[0] - HEREC[0]; 
	    dy = PLUSKC[1] - HEREC[1]; 
	    dz = PLUSKC[2] - HEREC[2]; 
#else
	    dx = SelectFieldComponent(coord, 0, index) - HEREC[0];
	    dy = SelectFieldComponent(coord, 1, index) - HEREC[1];
	    dz = SelectFieldComponent(coord, 2, index) - HEREC[2];
#endif

#ifdef NEXTFIELD
	    ds = NEXTFIELD[localOffset] - HEREV;
#else
	    ds = SelectFieldScalar(fieldNum, index) - HEREV;
#endif

	    --index[2];

	    /*Weigh in component*/
	    r = (dx * dx + dy * dy + dz * dz);
	    if (r > 0.0)
	    {
		w = ds / r;
		tx += dx * w;
		ty += dy * w;
		tz += dz * w;
	    }
	}

	/*Put it all together*/
	{
	    real r;
	    r = sqrt(tx * tx + ty * ty + tz * tz);
	    if (r > 0.0)
	    {
		r = 1.0 / r;
		tx *= r;
		ty *= r;
		tz *= r;
	    }
	    deltas[localOffset * 3] = tx;
	    deltas[localOffset * 3 + 1] = ty;
	    deltas[localOffset * 3 + 2] = tz;
	}
    }
}
