void _lucIsosurfaceCrossSection_Draw( void* drawingObject, lucDatabase* database, void* _context )
{
   lucIsosurfaceCrossSection* self = (lucIsosurfaceCrossSection*)drawingObject;
   lucIsosurface*             isosurf = self->isosurface;
   double                     minIsovalue     = self->minIsovalue;
   double                     maxIsovalue     = self->maxIsovalue;
   lucColourMap*              colourMap       = self->colourMap;
   int                        i, j, k;
   double                     isovalue;
   Index                      triangle_I;

   /* Custom max, min, use global min/max if equal (defaults to both zero) */
   if (minIsovalue == maxIsovalue)
   {
      //minIsovalue = FieldVariable_GetMinGlobalFieldMagnitude(self->fieldVariable);
      //maxIsovalue = FieldVariable_GetMaxGlobalFieldMagnitude(self->fieldVariable);
   }

   if (colourMap)
      lucColourMap_SetMinMax(colourMap, minIsovalue, maxIsovalue);

   /* Copy object id */
   isosurf->id = self->id; 

   if (self->rank == 0)
   {
      /* Calculate a value we can use to offset each surface section slightly
       *  so they appear in the same position but don't actually overlap */
      Coord min, max;
      float shift = 0;
      float range = 0;
      int d;
      Mesh_GetGlobalCoordRange(self->mesh, min, max );
      for (d=0; d<3; d++)
         range += (max[d] - min[d]) / 5000.0;
      range /= 3.0;

      /* Allocate Memory */
      Vertex** points = Memory_Alloc_2DArray( Vertex , 8, 1, "array for marching squares");

      /* Draw isovalues at each interval from min to max */
      for ( isovalue = minIsovalue ; isovalue <= maxIsovalue ; isovalue += self->interval )
      {
         float nshift[3] = {shift * self->normal[0], shift * self->normal[1], shift * self->normal[2]};
         shift += range;

         isosurf->triangleCount = 0;   /* Reset */
         isosurf->colourMap = NULL;

         if ( colourMap )
            lucColourMap_GetColourFromValue(colourMap, isovalue, &isosurf->colour, self->opacity);

         /* Run marching rectangles for this isovalue */
         isosurf->isovalue = isovalue;
         for ( i = 0 ; i < self->resolutionA-1 ; i++ )
         {
            for ( j = 0 ; j < self->resolutionB-1 ; j++ )
            {
               /* Copy vertex */
               for (k = 0; k<3; k++)
               {
                  points[LEFT_BOTTOM]->pos[k] = self->vertices[i][j][k] + nshift[k];
                  points[RIGHT_BOTTOM]->pos[k] = self->vertices[i+1][j][k] + nshift[k];
                  points[LEFT_TOP]->pos[k] = self->vertices[i][j+1][k] + nshift[k];
                  points[RIGHT_TOP]->pos[k] = self->vertices[i+1][j+1][k] + nshift[k];
               }
               /* Copy value */
               points[LEFT_BOTTOM]->value = self->values[i][j][0];
               points[RIGHT_BOTTOM]->value = self->values[i+1][j][0];
               points[LEFT_TOP]->value = self->values[i][j+1][0];
               points[RIGHT_TOP]->value = self->values[i+1][j+1][0];

               /* Interpolate mid-points and create triangles */
               lucIsosurface_WallElement( isosurf, points );
            }
         }

         /* Draw the surface section */
         isosurf->colourMap = self->colourMap;
         _lucIsosurface_Draw(self->isosurface, database, _context );

         /* Export colour values */
         if (self->colourMap)
         {
            float iso = isovalue;
            for ( triangle_I = 0 ; triangle_I < isosurf->triangleCount ; triangle_I++)
               for (i=0; i<3; i++)
                  lucDatabase_AddValues(database, 1, lucTriangleType, lucColourValueData, self->colourMap, &iso);
         }

      }

      Memory_Free( points );
   }

   /* Free memory */
   lucCrossSection_FreeSampleData(self);
}
void ComplexVectorMathSuite_TestComplexVectorMathOperations( ComplexVectorMathSuiteData* data ) {
   unsigned procToWatch;
   Stream*  stream = Journal_Register( Info_Type, (Name)"VectorMathOperationsStream" );
   char     expected_file[PCU_PATH_MAX];

   procToWatch = data->nProcs >=2 ? 1 : 0;

   if (data->rank == procToWatch ) {
      #define STG_COMPLEXVECTOR_TOL 1e-16;
      
      Cmplx  i[] = {{1.00000000, 0.000000000},{0.00000000, 0.000000000},{0.000000000, 0.00000000}};
      Cmplx  j[] = {{0.00000000, 0.00000000},{1.0000000, 0.00000000},{0.00000000, 0.0000000}};
      Cmplx  k[] = {{0.00000000, 0.000000000},{0.00000000, 0.000000000},{1.000000000, 0.000000000}};
      Cmplx  A[] = {{7.4, 1.0}, {  2, 0.0}, {  5, 1.0}, { 1, 0.0}, {  3, 2.0}, {  -42, 0.0}};
      Cmplx  B[] = {{  4, 2.0}, {2.3, 0.0}, {5.8, 0.0}, { 6, 0.0}, {-12, 0.0}, {39289, 0.0}};
      Cmplx  C[] = {{23, 0.0}, {  5, 0.0}, {-14, 0.0}, {32, 0.0}, {-21, 1.0}, {   78, 0.0}};
      Cmplx  D[] = {{23, 0.0}, {  5, 0.0}, {-14, 0.0}, {32, 0.0}, {-21, 0.0}, {   78, 0.0}};
      double angle;
      Cmplx  **matrix;
      Cmplx  vector[6], differenceVector[6];
      Cmplx  *coordList[4];
      int    d;
      double realVector[3], tolerance;
      Cmplx  dotProductResult;
      Cmplx  value;
      
      Stream_RedirectFile( stream, "testComplexVectorMathOperations.dat" );

      tolerance = STG_COMPLEXVECTOR_TOL;
      
      coordList[0] = A;
      coordList[1] = B;
      coordList[2] = C;
      coordList[3] = D;
      Journal_Printf( stream, "****************************\n");
      Journal_Printf(stream, "Vectors - A, B, C, and D\n");
      
      StGermain_PrintNamedComplexVector( stream, A, 6 );
      StGermain_PrintNamedComplexVector( stream, B, 6 );
      StGermain_PrintNamedComplexVector( stream, C, 6 );
      StGermain_PrintNamedComplexVector( stream, D, 6 );

      /* Check Rotation functions */
      Journal_Printf( stream, "\n****************************\n");

      StGermain_PrintNamedComplexVector( stream, i, 3 );
      StGermain_PrintNamedComplexVector( stream, j, 3 );
      StGermain_PrintNamedComplexVector( stream, k, 3 );
      
      angle = M_PI / 2.0;
      
      Journal_Printf(stream, "Axis Rotation\n");            
      StGermain_RotateCoordinateAxisComplex( k, I_AXIS, angle, vector ) ;
      Journal_Printf( stream, "K Rotated %g radians around I axis - \n", angle);
      Cmplx_Subtract(vector[0], j[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], j[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], j[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, j, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, j, 3);
      }
      
      Journal_Printf(stream, "Angle Rotation\n");      
      StGermain_RotateComplexVector(k, angle,0.0, 0.0, vector);
      Journal_Printf( stream, "K Rotated %g radians around I axis - \n", angle); 
      Cmplx_Subtract(vector[0], j[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], j[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], j[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, j, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, j, 3);
      }
      
      Journal_Printf(stream, "Axis Rotation\n");      
      StGermain_RotateCoordinateAxisComplex( i, J_AXIS, angle, vector );
      Journal_Printf( stream, "I Rotated %g radians around J axis - \n", angle); 
      Cmplx_Subtract(vector[0], k[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], k[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], k[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, k, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, k, 3);
      }
      
      Journal_Printf(stream, "Angle Rotation\n");
      StGermain_RotateComplexVector(i, 0.0, angle, 0.0, vector );
      Journal_Printf( stream, "I Rotated %g radians around J axis - \n", angle); 
      Cmplx_Subtract(vector[0], k[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], k[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], k[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, k, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, k, 3);
      }
      
      Journal_Printf(stream, "Axis Rotation\n");      
      StGermain_RotateCoordinateAxisComplex( j, K_AXIS, angle, vector );
      Journal_Printf( stream, "J Rotated %g radians around K axis - \n", angle); 
      Cmplx_Subtract(vector[0], i[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], i[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], i[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, i, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, i, 3);
      }

      Journal_Printf(stream, "Angle Rotation\n");
      StGermain_RotateComplexVector( j, 0.0, 0.0, angle, vector );
      Journal_Printf( stream, "J Rotated %g radians around K axis - \n", angle); 
      Cmplx_Subtract(vector[0], i[0], differenceVector[0]);
      Cmplx_Subtract(vector[1], i[1], differenceVector[1]);
      Cmplx_Subtract(vector[2], i[2], differenceVector[2]);
      
      if ( (Cmplx_Modulus(differenceVector[0]) < tolerance) && (Cmplx_Modulus(differenceVector[1]) < tolerance) &&
          (Cmplx_Modulus(differenceVector[2]) < tolerance) ) {
         Journal_Printf( stream, "Answer within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, i, 3);
      }
      else {
         Journal_Printf( stream, "Answer not within tolerance %g of expected result: ", tolerance);
         StGermain_PrintNamedComplexVector( stream, i, 3);
      }

      angle = M_PI / 4.0;

      StGermain_RotateComplexVector(i, 0.0, angle, angle, vector );
      Journal_Printf( stream, "I Rotated %g radians around J axis "
      "and %2g radians around K axis: \n", angle, angle);
      StGermain_PrintNamedComplexVector( stream, vector, 3 );

      StGermain_RotateComplexVector(j, angle, 0.0, angle, vector );
      Journal_Printf( stream, "J Rotated %g radians around I axis "
      "and %g radians around K axis: \n", angle, angle); 
      StGermain_PrintNamedComplexVector( stream, vector, 3 );

      StGermain_RotateComplexVector(k, angle, angle, 0.0, vector );
      Journal_Printf( stream, "K Rotated %g radians around I axis "
      "and %g radians around J axis: \n", angle, angle); 
      StGermain_PrintNamedComplexVector( stream, vector, 3 );

      /* Check addition function */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "vector = A + B\n");
      for ( d = 0 ; d <= 6 ; d++ ) {
         StGermain_ComplexVectorAddition( vector, A, B, d );
         StGermain_PrintNamedComplexVector( stream, vector, d );
      }

      /* Check subtraction function */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "vector = A - B\n");
      for ( d = 0 ; d <= 6 ; d++ ) {
         StGermain_ComplexVectorSubtraction( vector, A, B, d );
         StGermain_PrintNamedComplexVector( stream, vector, d );
      }
   
      /* Check Magnitude Function */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check Magnitude Function\n");
      for ( d = 0 ; d <= 6 ; d++ ) {
         Journal_Printf( stream, "dim = %d magnitude A = %2.3f\n", d, StGermain_ComplexVectorMagnitude( A, d ) );
         Journal_Printf( stream, "dim = %d magnitude B = %2.3f\n", d, StGermain_ComplexVectorMagnitude( B, d ) );
      }

      /* Check Dot Product */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check Dot Product Function\n");
      Journal_Printf( stream, "value = A . B \n");
      
      for (d = 0; d <=6; d++) {
      StGermain_ComplexVectorDotProduct(A, B, d, dotProductResult);         
      Journal_Printf( stream, "dim = %d dot product = %2.3f + %2.3f i\n",
         d, dotProductResult[0], dotProductResult[1] );
      }

      /* Check Cross Product */
      /* Tested against http://www.engplanet.com/redirect.html?3859 */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check Cross Product Function\n");
      Journal_Printf( stream, " A x B in 3-D\n");
      StGermain_ComplexVectorCrossProduct( vector, A, B );
      StGermain_PrintNamedComplexVector( stream, vector, 3 );

      /* Checking centroid function */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Checking centroid function\n");
      for ( d = 0 ; d <= 6 ; d++ ) {
         StGermain_ComplexTriangleCentroid( vector, A, B, C, d );
         StGermain_PrintNamedComplexVector( stream, vector, d );
      }

      /* Check Normalisation Function */
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check Normalisation Function\n");
      
      Journal_Printf( stream, "2-D\n\n");
      d = 2;
      StGermain_PrintNamedComplexVector( stream, A, d );
      StGermain_ComplexVectorNormalise( A, d );
      StGermain_PrintNamedComplexVector( stream, A, d);
      Journal_Printf( stream, "mag = %2.3f\n", StGermain_ComplexVectorMagnitude( A, d ) );

      Journal_Printf( stream, "3-D\n\n");
      d = 3;
      StGermain_PrintNamedComplexVector( stream, B, d );
      StGermain_ComplexVectorNormalise( B, d );
      StGermain_PrintNamedComplexVector( stream, B, d);
      Journal_Printf( stream, "mag = %2.3f\n", StGermain_ComplexVectorMagnitude( B, d ) );

      Journal_Printf( stream, "5-D\n\n");
      d = 5;
      StGermain_PrintNamedComplexVector( stream, C, d );
      StGermain_ComplexVectorNormalise( C, d );
      StGermain_PrintNamedComplexVector( stream, C, d);
      Journal_Printf( stream, "mag = %2.3f\n", StGermain_ComplexVectorMagnitude( C, d ) );

      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check StGermain_ComplexVectorCrossProductMagnitude\n");
      A[0][REAL_PART] = 1.0; A[0][IMAG_PART] = 1.0; 
      A[1][REAL_PART] = 2.0; A[1][IMAG_PART] = 0.0;
      A[2][REAL_PART] = 3.0; A[2][IMAG_PART] = 0.0;
      B[0][REAL_PART] = 4.0; B[0][IMAG_PART] = 0.0;
      B[1][REAL_PART] = 5.0; B[1][IMAG_PART] = 0.0;
      B[2][REAL_PART] = 6.0; B[2][IMAG_PART] = 3.0;
      StGermain_PrintNamedComplexVector( stream, A, 3);
      StGermain_PrintNamedComplexVector( stream, B, 3);
      
      StGermain_ComplexVectorCrossProductMagnitude(A, B, 2, value ) ;
      Journal_Printf( stream, "mag = %2.3g + %2.3g i (2D)\n", value[REAL_PART], value[IMAG_PART] );
      
      StGermain_ComplexVectorCrossProductMagnitude(A, B, 3, value ) ;
      Journal_Printf( stream, "mag = %2.3g + %2.3g i (3D)\n", value[REAL_PART], value[IMAG_PART] );

      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check StGermain_ComplexScalarTripleProduct \n");
      
      matrix = Memory_Alloc_2DArray( Cmplx, 3, 3, (Name)"matrix"  );
      
      matrix[0][0][REAL_PART] = 1.0;  matrix[0][0][IMAG_PART] = 1.0;
      matrix[0][1][REAL_PART] = 2.0;  matrix[0][1][IMAG_PART] = 0.0; 
      matrix[0][2][REAL_PART] = 3.0;  matrix[0][2][IMAG_PART] = 2.0;
      matrix[1][0][REAL_PART] = 4.0;  matrix[1][0][IMAG_PART] = 0.0;
      matrix[1][1][REAL_PART] = 5.0;  matrix[1][1][IMAG_PART] = 3.0; 
      matrix[1][2][REAL_PART] = 6.0;  matrix[1][2][IMAG_PART] = 0.0;
      matrix[2][0][REAL_PART] = 7.0;  matrix[2][0][IMAG_PART] = 1.0;
      matrix[2][1][REAL_PART] = 8.0;  matrix[2][1][IMAG_PART] = 0.0;
      matrix[2][2][REAL_PART] = 11.0; matrix[2][2][IMAG_PART] = 1.0;
      StGermain_PrintNamedComplexVector( stream, matrix[0], 3);
      StGermain_PrintNamedComplexVector( stream, matrix[1], 3);
      StGermain_PrintNamedComplexVector( stream, matrix[2], 3);

      StGermain_ComplexScalarTripleProduct( matrix[0], matrix[1], matrix[2], value );
      Journal_Printf( stream, "scalar triple product: ");
      Journal_PrintCmplx( stream, value );
      
      StGermain_ComplexScalarTripleProduct( matrix[2], matrix[0], matrix[1], value );
      Journal_Printf( stream, "scalar triple product: ");
      Journal_PrintCmplx( stream, value );
      StGermain_ComplexScalarTripleProduct( matrix[1], matrix[2], matrix[0], value );
      Journal_Printf( stream, "scalar triple product: ");
      Journal_PrintCmplx( stream, value );
      
      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check Vector_ToComplexVector function \n");
      
      realVector[0] = 1.0; realVector[1] = 2.0; realVector[2] = 3.0;
      
      StGermain_PrintNamedVector(stream, realVector, 3);
      Vector_ToComplexVector(realVector, 3, matrix[0]) ;
      StGermain_PrintNamedComplexVector( stream, matrix[0], 3);

      Journal_Printf( stream, "\n****************************\n");
      Journal_Printf( stream, "Check ComplexVector_ToVector function \n");   
      
      matrix[0][0][REAL_PART] = 5.0; matrix[0][0][IMAG_PART] = 0.0;
      matrix[0][1][REAL_PART] = 6.0; matrix[0][1][IMAG_PART] = 0.0; 
      matrix[0][2][REAL_PART] = 7.0; matrix[0][2][IMAG_PART] = 0.0;
      
      StGermain_PrintNamedComplexVector( stream, matrix[0], 3);
      ComplexVector_ToVector(matrix[0], 3, realVector) ;
      StGermain_PrintNamedVector(stream, realVector, 3);

      pcu_filename_expected( "testComplexVectorMathOperations.expected", expected_file );
      pcu_check_fileEq( "testComplexVectorMathOperations.dat", expected_file );
      remove( "testComplexVectorMathOperations.dat" );

      Memory_Free( matrix );
      Stream_CloseAndFreeFile( stream );
   }
}