예제 #1
0
void AssignmentFour::DistributionSeed() {
	viewer->clear();

	if (DrawField) {
		DrawVectorFieldHelper();
	}

	Vector4f color = makeVector4f(0.8f, 0.2f, 0.0f, 0.40f);

	vector<Vector2f> points = magnitudeDistribution(NumStreamLines);

	for (size_t i = 0; i < points.size(); ++i) {
		float32 x = points[i][0];
		float32 y = points[i][1];
		vector<Vector2f> path = Integrator(RKStep, &AssignmentFour::RK4, x, y);
		DrawStreamline(path, color);

		output << "x: " << x << "\ty:" << y << "\n";
	}

	//viewer->refresh();
}
예제 #2
0
void iterativeSolvers_unitTest() {
   // small matrix test
   {
      Vector4f test = makeVector4f(1.0f, 3.14f, 2.0f, 2.71f);
      Matrix4f mat = makeRotX4f(0.32f) * makeRotY4f(-0.39f) * makeRotZ4f(0.76f);
      mat += mat.transpose();
      mat += IDENTITY4F*5;
      Vector4f rhs = mat * test;
      Matrix4f invMat = invertMatrix(mat);
      Vector4f directFloat = invMat * rhs;

      DVectorD testD(4); for (card32 i=0; i<4; i++) testD[i] = test[i];
      DVectorD rhsD(4); for (card32 i=0; i<4; i++) rhsD[i] = rhs[i];
      SparseMatrixD matS(4);
      for (card32 r=0; r<4; r++) {
         for (card32 c=0; c<4; c++) {
            double v = mat[c][r];
            if (v != 0) {
               matS[r].setEntry(c, v);
            }
         }
      }

      output << "Matrix:\n" << mat.toString() << "\n";
      output << "true solution: " << test.toString() << "\n";
      output << "right hand side: " << rhs.toString() << "\n";
      output << "direct float prec. solution: " << directFloat.toString() << "\n\n";

      output << "Matrix:\n" << matS.toString() << "\n";
      output << "true solution: " << testD.toString() << "\n";
      output << "right hand side: " << rhsD.toString() << "\n\n";

      DVectorD x = nullDVector<double>(4);

	  card32 numIterations = 1000;
      gaussSeidelSolve(matS, x, rhsD, numIterations, 1E-20, 1E-5, false);
      output << "Gauss-Seidel solution: " << x.toString() << "\n\n";

	  numIterations = 1000;
      x = nullDVector<double>(4);
      steepestDescentSolve(matS, x, rhsD, numIterations, 1E-5, false);
      output << "Steepest-Descent solution: " << x.toString() << "\n\n";

	  numIterations = 1000;
      x = nullDVector<double>(4);
      conjugateGradientsSolve(matS, x, rhsD, numIterations, 1E-5, true);
      output << "CG solution: " << x.toString() << "\n\n";
   }

   // large matrix test
   {
      SparseMatrixD mat(MDIM*MDIM);
      for (int y=0; y<MDIM; y++) {
         for (int x=0; x<MDIM; x++) {
            addEntry(mat, x,y, x,y,  -4, MDIM);
            addEntry(mat, x,y, x+1,y, 1, MDIM);
            addEntry(mat, x,y, x-1,y, 1, MDIM);
            addEntry(mat, x,y, x,y+1, 1, MDIM);
            addEntry(mat, x,y, x,y-1, 1, MDIM);
         }
      }

      Timer T; card32 vt;

      DVectorD x = nullDVector<double>(MDIM*MDIM);
      DVectorD b = scalarDVector<double>(MDIM*MDIM, 1);
      DVectorD gs, sd, cg;


      x = nullDVector<double>(MDIM*MDIM);
      T.getDeltaValue();
	  card32 numIterations = 100000;
      conjugateGradientsSolve(mat, x, b, numIterations, 1E-7, false);
      vt = T.getDeltaValue();
      output << "CG time: " << vt << "\n\n";
      output << "Large sytem CG solution (LAPL(f) == 1):\n";
      for (int y=0; y<MDIM; y++) {
			for (int xp=0; xp<MDIM; xp++) {
            output << x[xp +y*MDIM] << "\t";
         }
         output.cr();
      }
      output.cr();
      cg = x;

      x = nullDVector<double>(MDIM*MDIM);
      T.getDeltaValue();
	  numIterations = 100000;
      gaussSeidelSolve(mat, x, b, numIterations, 1E-20, 1E-7, false);
      vt = T.getDeltaValue();
      output << "GS time: " << vt << "\n\n";
      output << "Large sytem Gauss-Seidel solution (LAPL(f) == 1):\n";
      for (int y=0; y<MDIM; y++) {
         for (int xp=0; xp<MDIM; xp++) {
           output << x[xp +y*MDIM] << "\t";
         }
        output.cr();
      }
      output.cr();

      gs = x;

      x = nullDVector<double>(MDIM*MDIM);
      T.getDeltaValue();
	  numIterations = 100000;
      steepestDescentSolve(mat, x, b, numIterations, 1E-7, false);
      vt = T.getDeltaValue();
      output << "SD time: " << vt << "\n\n";
      output << "Large sytem steepest descent solution (LAPL(f) == 1):\n";
      for (int y=0; y<MDIM; y++) {
         for (int xp=0; xp<MDIM; xp++) {
            output << (long double)x[xp +y*MDIM] << "\t";
         }
         output.cr();
      }
      output.cr();

      sd = x;

      x = nullDVector<double>(MDIM*MDIM);

      output << "|gs-sd|_2 " << (long double)norm(gs-sd) << "\n";
      output << "|gs-cg|_2 " << (long double)norm(gs-cg) << "\n";

      vector< DVectorD > eigenVects;
      vector< double > eigenvalues;
      DVectorD eigenvector;
      double eigenvalue;
      for (int i=0; i<10; i++) {
         powerIteration(mat, eigenVects, eigenvector, eigenvalue, 1.0001, 1000, false);
         eigenVects.push_back(eigenvector);
         eigenvalues.push_back(eigenvalue);
      }
      for (int i=0; i<10; i++) {
         output << i << " largest of large sytem eigenvector (LAPL(f) == 1):\n";
         for (int y=0; y<MDIM; y++) {
            for (int xp=0; xp<MDIM; xp++) {
               output << eigenVects[i][xp +y*MDIM] << "\t";
            }
            output.cr();
         }
         output.cr();
      }
      output << "eigenvalue:\n";
      for (int i=0; i<10; i++) {
         output << eigenvalues[i] << "\n";
      }

      T.getDeltaValue();

      eigenVects.clear();
      for (int i=0; i<10; i++) {
         GaussSeidelSolver<double> linSolve;
         inversePowerIteration(mat, eigenVects, eigenvector, eigenvalue, &linSolve, 1.0001, 1000, false);
         eigenvalues.push_back(eigenvalue);
         eigenVects.push_back(eigenvector);
      }

      output << "GS-PowerIt time: " << T.getDeltaValue() << "\n\n";

      eigenVects.clear();
      for (int i=0; i<10; i++) {
         CGSolver<double> linSolve;
         inversePowerIteration(mat, eigenVects, eigenvector, eigenvalue, &linSolve, 1.0001, 1000, false);
         eigenvalues.push_back(eigenvalue);
         eigenVects.push_back(eigenvector);
      }

      output << "CG-PowerIt time: " << T.getDeltaValue() << "\n\n";

      eigenVects.clear();
      for (int i=0; i<10; i++) {
         SteepestDescentSolver<double> linSolve;
         inversePowerIteration(mat, eigenVects, eigenvector, eigenvalue, &linSolve, 1.0001, 1000, false);
         eigenvalues.push_back(eigenvalue);
         eigenVects.push_back(eigenvector);
      }

      output << "Steepest descent-PowerIt time: " << T.getDeltaValue() << "\n\n";

      for (int i=0; i<10; i++) {
         output << i << " smallest of large sytem eigenvector (LAPL(f) == 1):\n";
         for (int y=0; y<MDIM; y++) {
            for (int xp=0; xp<MDIM; xp++) {
               output << eigenVects[i][xp +y*MDIM] << "\t";
            }
            output.cr();
         }
         output.cr();
      }
      output << "eigenvalues:\n";
      for (int i=0; i<10; i++) {
         output << eigenvalues[i] << "\n";
      }
        
   }
   {
      Timer T;
      output << "cg scaling test\n";
      for (unsigned i=1; i<21; i++) {
         const int size = i * 10;
         SparseMatrixD mat(size*size);
         for (int y=0; y<size; y++) {
            for (int x=0; x<size; x++) {
               addEntry(mat, x,y, x,y,  -4, size);
               addEntry(mat, x,y, x+1,y, 1, size);
               addEntry(mat, x,y, x-1,y, 1, size);
               addEntry(mat, x,y, x,y+1, 1, size);
               addEntry(mat, x,y, x,y-1, 1, size);
            }
         }

         Timer T; card32 vt;

         DVectorD x = nullDVector<double>(size*size);
         DVectorD b = scalarDVector<double>(size*size, 1);

         T.getDeltaValue();
		 card32 numIterations = 100000;
         conjugateGradientsSolve(mat, x, b, numIterations, 1E-7, false);
         vt = T.getDeltaValue();

         output << i << "\t" << vt << "\n";
      }
   }
   {
      Timer T;
      output << "gs scaling test\n";
      for (unsigned i=1; i<21; i++) {
         const int size = i * 10;
         SparseMatrixD mat(size*size);
         for (int y=0; y<size; y++) {
            for (int x=0; x<size; x++) {
               addEntry(mat, x,y, x,y,  -4, size);
               addEntry(mat, x,y, x+1,y, 1, size);
               addEntry(mat, x,y, x-1,y, 1, size);
               addEntry(mat, x,y, x,y+1, 1, size);
               addEntry(mat, x,y, x,y-1, 1, size);
            }
         }

         Timer T; card32 vt;

         DVectorD x = nullDVector<double>(size*size);
         DVectorD b = scalarDVector<double>(size*size, 1);

         T.getDeltaValue();
		 card32 numIterations = 100000;
         gaussSeidelSolve(mat, x, b, numIterations, 1E-20, 1E-7, false);
         vt = T.getDeltaValue();

         output << i << "\t" << vt << "\n";
      }
   }
   {
      Timer T;
      output << "sd scaling test\n";
      for (unsigned i=1; i<21; i++) {
         const int size = i * 10;
         SparseMatrixD mat(size*size);
         for (int y=0; y<size; y++) {
            for (int x=0; x<size; x++) {
               addEntry(mat, x,y, x,y,  -4, size);
               addEntry(mat, x,y, x+1,y, 1, size);
               addEntry(mat, x,y, x-1,y, 1, size);
               addEntry(mat, x,y, x,y+1, 1, size);
               addEntry(mat, x,y, x,y-1, 1, size);
            }
         }

         Timer T; card32 vt;

         DVectorD x = nullDVector<double>(size*size);
         DVectorD b = scalarDVector<double>(size*size, 1);

         T.getDeltaValue();
		 card32 numIterations = 100000;
         steepestDescentSolve(mat, x, b, numIterations, 1E-7, false);
         vt = T.getDeltaValue();

         output << i << "\t" << vt << "\n";
      }
   }

}
예제 #3
0
void Experiment1_1::DrawParallelPlot2(float XSep)
{
    float XOff=2.0;                        //Offset between the scatter plot and the parallel plot
    //float XSep=5.0;                        //Separation between the axis of the parallel plot
    
    for(int i=0;i<(int)Data.size();i++)
    {
        viewer->addLine(makeVector2f(XOff+max_Data[0],Data[i][0]), makeVector2f(XOff+max_Data[0]+XSep,Data[i][1]),makeVector4f(Data[i][0]/DataColorRange[0], Data[i][1]/DataColorRange[1], 0.5 /*((float) i)/Data.size()*/ , 1)  );
    }
    //Axes
   
     viewer->addLine(makeVector2f(XOff+max_Data[0],min_Data[0]), makeVector2f(XOff+max_Data[0],max_Data[0]), makeVector4f(1,0,1,1), 3);
     viewer->addLine(makeVector2f(XOff+XSep+max_Data[0],min_Data[1]), makeVector2f(XOff+XSep+max_Data[0],max_Data[1]), makeVector4f(1,0,1,1), 3);

    // display changes
    viewer->refresh();
}
예제 #4
0
void Experiment1_1::DrawScatterPlot()
{
    max_Data = makeVector2f(Data[0][0], Data[0][1]);
    min_Data = makeVector2f(Data[0][0], Data[0][1]);
    for(int i=0;i<(int)Data.size();i++)
    {
        if(i>0)
        {
          if (Data[i][0] > max_Data [0])
          {
            max_Data[0]=Data[i][0];
          }
          if (Data[i][1] > max_Data [1])
          {
            max_Data[1]=Data[i][1];
          }
          if (Data[i][0] < min_Data [0])
          {
            min_Data[0]=Data[i][0];
          }
          if (Data[i][1] < min_Data [1])
          {
            min_Data[1]=Data[i][1];
          }

        }
    }
    DataColorRange = makeVector2f(max_Data[0]-min_Data[0], max_Data[1]-min_Data[1]);
    if (max_Data[0]<0)
        max_Data[0]=0;
    if (max_Data[1]<0)
        max_Data[1]=0;
    if (min_Data[0]>0)
        min_Data[0]=0;
    if (min_Data[1]>0)
        min_Data[1]=0;

    for(int i=0;i<(int)Data.size();i++)
    {
        Point2D NewPoint(Data[i][0], Data[i][1]);
        NewPoint.color = makeVector4f(Data[i][0]/DataColorRange[0], Data[i][1]/DataColorRange[1], 0.5 /*((float) i)/Data.size()*/, 1);
        viewer->addPoint(NewPoint);
    }
    //Axes
    Point2D Origin(0, 0);
    Origin.color = makeVector4f(1,1,1,1);
    Origin.size = 10;
    const int idOrigin = viewer->addPoint(Origin);

    Point2D XNeg(min_Data[0], 0);
    Point2D XPos(max_Data[0], 0);
    XNeg.color = makeVector4f(1,0,0,1);
    XPos.color = makeVector4f(1,0,0,1);
    XNeg.size = 10;
    XPos.size = 10;
    const int idXNeg = viewer->addPoint(XNeg);
    const int idXPos = viewer->addPoint(XPos);

    Point2D YNeg(0, min_Data[1]);
    Point2D YPos(0, max_Data[1]);
    YPos.color = makeVector4f(0,1,0,1);
    YNeg.color = makeVector4f(0,1,0,1);
    YPos.size = 10;
    YNeg.size = 10;
    const int idYPos = viewer->addPoint(YNeg);
    const int idYNeg = viewer->addPoint(YPos);

    //X-Axis
    Line Axis;
    Axis.vertices[0] = idXNeg;
    Axis.vertices[1] = idXPos;
    Axis.color = makeVector4f(1,1,1,1);
    Axis.thickness = 3;
    viewer->addLine(Axis);

    //Y-Axis
    Axis.vertices[0] = idYNeg;
    Axis.vertices[1] = idYPos;
    viewer->addLine(Axis);

    // display changes
    viewer->refresh();
}
예제 #5
0
void GMExperiment6_1::displayBezierSpline()
{
    //Trying a new way of computing inflection points
    //First look for long straight bits on the curve and add
    //one of the end points to the list of knots
    float inflection_thresh = 1.5f;
    int32 inflection_filter = 4;
    Vector2i inflection_range;
    inflection_range[0] = -1; inflection_range[1]= -1;
    vector<Vector2i> searchRanges;
    vector<int> inflection_idx;

    for(int i = 0; i < curvature.size(); ++i)
    {
        if(abs(curvature[i]) < inflection_thresh)
        { if(inflection_range[0]<0)
            { inflection_range[0]=i;
            }
        }
        else
        {
            if((inflection_range[0]>=0)) //Infection range was being observed
            {
                inflection_idx.push_back(inflection_range[0]);
                inflection_range[1]=i;
                //inflection_idx.push_back(inflection_range[1]);
                searchRanges.push_back(inflection_range);
                inflection_range[0]=-1;
                inflection_range[1]=-1;
            }
        }
    }


    //Now add endpoints to the vector and filter out any indices extremely close to each other
    //See if the endpoints already exist. If not, then push them onto the data structure
    if(inflection_idx.empty())
    {
        inflection_idx.push_back(0);
        inflection_idx.push_back(curvature.size()-1);
    }
    else
    {
        if(inflection_idx[0]!=0)
        {
            inflection_idx.insert( inflection_idx.begin(), 0);
        }
        if(inflection_idx[inflection_idx.size()-1] != curvature.size()-1)
        {
            inflection_idx.push_back(curvature.size()-1);
        }
    }

    qDebug()<<"Number of inflection range points "<<inflection_idx.size()<<"\n";

    //Then look for sign changes in the segments not spanned by the long straight curves
    //and add those and sort the vector
    if(!searchRanges.empty())
    {
        if(searchRanges[0][0]!=0)
        {
            searchRanges.insert(searchRanges.begin(),makeVector2i(0,0));
        }
        if(searchRanges[searchRanges.size()-1][1]!=curvature.size()-1)
        {
            searchRanges.push_back(makeVector2i(curvature.size()-1,curvature.size()-1));
        }

        for(int i=0; i<searchRanges.size()-1; i++)
        {
            bool old_sign = curvature[searchRanges[i][1]]>0;
            for(int j=searchRanges[i][1]+1; j<searchRanges[i+1][0]; j++)
            {
                bool new_sign = curvature[j]>0;
                if(new_sign!=old_sign)
                {
                    inflection_idx.push_back(j);
                }
                old_sign=new_sign;
            }
        }
#if 1
    for(int i=0; i<inflection_idx.size()-1; i++)
    {
       if(i < inflection_idx.size()-2)
       {
           if(( inflection_idx[i+1]-inflection_idx[i]) < inflection_filter)
           {
            inflection_idx.erase(inflection_idx.begin()+i+1);
           }
       }
       else
       {
           if(( inflection_idx[i+1]-inflection_idx[i]) < inflection_filter)
           {
            inflection_idx.erase(inflection_idx.begin()+i);
           }
       }
    }
#endif
    }
    sort(inflection_idx.begin(),inflection_idx.end());
    vector<int> knots;
    knots = inflection_idx;
    //knots.push_back(inflection_idx[0]);
    //knots.push_back(inflection_idx[inflection_idx.size()-1]);

    //for(int i=1; i<inflection_idx.size()-1; i+=2)
    //{ knots.push_back(inflection_idx[i]);
    //}
    //Do the tangent check between inflection points and add to knots
    for(int j=0; j<inflection_idx.size()-1; j++)
    {
            tangent_check(inflection_idx[j],inflection_idx[j+1],knots,smoothData);
    }

    std::sort(knots.begin(), knots.end());

#if 1
    for(int i=0; i<knots.size()-1; i++)
    {
       if(i < knots.size()-2)
       {
           if(( knots[i+1]-knots[i]) < knot_filter)
           {
            knots.erase(knots.begin()+i+1);
           }
       }
       else
       {
           if(( knots[i+1]-knots[i]) < knot_filter)
           {
            knots.erase(knots.begin()+i);
           }
       }
    }
#endif
    output<<"Total Number of control points (knots):"<< knots.size()<<"\n";


    int start = 0;
    int end = knots.size()-1;

    if(segment_id != -1)

    {
        start = segment_id;
        end = segment_id+1;
    }

    for(int j = start; j < end; ++j)

    {
        int i_start = knots[j];
        int i_end = knots[j+1];

        auto p0 = smoothData[i_start];
        auto p3 = smoothData[i_end];

        // estimate derivatives
        vector<Vector2d> d(2);
        d[0] = to(firstDerivative(smoothData, i_start));
        d[0].normalize();
        d[1] = -to(firstDerivative(smoothData, i_end));
        d[1].normalize();

        vector<Vector2f> points;
        for(int k = knots[j]; k <= knots[j+1]; k++)
            points.push_back(smoothData[k]);



//        if(points.size() < 6)
//            continue;

        Vector2d s;
        if(least_squares)
        {
            s = leastSquaresEstimate(points, p0, p3, d[0], d[1]);
        }
        else
        {
            s[0] = sqrt((points[1]-points[0]).getSqrNorm());
            s[1] = sqrt((points[points.size()-1]-points[points.size()-2]).getSqrNorm());
        }

        auto ctrl = s2ctrl(to(p0), to(p3), d, s);

        if(gradient_descent)
        {
            auto new_s = gradientDescent(ctrl, d, points, num_iterations);
            ctrl = s2ctrl(to(p0), to(p3), d, new_s);
        }

        // display the curve!
        auto piece = renderCubicBezier(ctrl, std::max(points.size(), size_t(20)));
        displayCurve(viewer, piece, 2);

        // display control points
        int pt_indices[4];
        if(display_control_points)
        {
            for(int k = 0; k < 4; ++k)
            {
                Point2D pt;
                pt.position = to(ctrl[k]);

                bool is_knot = k == 0 || k == 3;
                pt.size = is_knot ? 8 : 6;
                pt.color = is_knot ? makeVector4f(0, 1.0, 0, 1) :
                                     makeVector4f(1, 0, 1, 1);
                pt_indices[k] = viewer->addPoint(pt);
            }
            Line l;
            l.thickness = 1;
            l.color = makeVector4f(1,1,1,1);
            l.vertices[0] = pt_indices[0];
            l.vertices[1] = pt_indices[1];
            viewer->addLine(l);
            l.vertices[0] = pt_indices[2];
            l.vertices[1] = pt_indices[3];
            viewer->addLine(l);
        }
    }


    viewer->refresh();
}
예제 #6
0
static void displayCurve(GLGeometryViewer *viewer, const vector<Vector2f> &vec,
                         float thickness = 1, Vector4f colour = makeVector4f(0, 1, 1, 1))
{
    for(int k = 0; k < vec.size()-1; ++k)
        viewer->addLine(vec[k], vec[k+1], colour, thickness);
}
예제 #7
0
void GMExperiment6_1::displayRawData()
{
    displayData(rawData, makeVector4f(1.0, 0, 0, 1));
}
예제 #8
0
void Experiment2D22::drawPlot() {
	int rows = scaledData.size();
	int cols = scaledData[0].size();

	for (int i = 0;i < rows;i++)
	{
		for (int j = 0;j < cols-1;j++) {
			viewer->addLine(makeVector2f(j*3,scaledData[i][j]),makeVector2f((j+1)*3,scaledData[i][j+1]), makeVector4f(1, 0, 0, 0.5));
		}
	}
}
예제 #9
0
void Experiment3_1::DrawRegularMesh()
{
    viewer->clear();

    //Load scalar field
    ScalarField2 field;
    if (!field.load(scalar_filename))
    {
        output << "Error loading field file " << scalar_filename << "\n";
        return;
    }


    //Get the minimum/maximum value in that field
    float32 min = std::numeric_limits<float32>::max();
    float32 max = -std::numeric_limits<float32>::max();
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i< field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i,j);
            min = val < min ? val : min;
            max = val > max ? val : max;
        }
    }

  //Plot the grid
  //Traverse one dimension first and then the other dimension
   for(size_t j=0; j<field.dims()[1]; j++)
    {
        viewer->addLine(field.nodePosition(0,j), field.nodePosition(field.dims()[0]-1,j), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }
   for(size_t i=0; i<field.dims()[0]; i++)
    {
        viewer->addLine(field.nodePosition(i,0), field.nodePosition(i,field.dims()[1]-1), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }

  //Optionally overlay data on the grid
  if (grid_w_data == true )
  {
    //Draw a point for each grid vertex.
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i<field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i, j);
            const float32 c = (val - min) / (max - min);

            Point2D p;
            p.position  = field.nodePosition(i, j);
            p.size = 5;
            //Use a grayscale depending on the actual value
            p.color[0] = c; p.color[1] = c; p.color[2] = c;
            viewer->addPoint(p);
        }
    }
  }



    viewer->refresh();
}
예제 #10
0
void Experiment3_1::DrawIsoContour_Asymp()
{
    viewer->clear();

    //Load scalar field
    ScalarField2 field;
    if (!field.load(scalar_filename))
    {
        output << "Error loading field file " << scalar_filename << "\n";
        return;
    }


    //Get the minimum/maximum value in that field
    float32 min = std::numeric_limits<float32>::max();
    float32 max = -std::numeric_limits<float32>::max();
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i< field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i,j);
            min = val < min ? val : min;
            max = val > max ? val : max;
        }
    }

  //Plot the grid
  //Traverse one dimension first and then the other dimension
   for(size_t j=0; j<field.dims()[1]; j++)
    {
        viewer->addLine(field.nodePosition(0,j), field.nodePosition(field.dims()[0]-1,j), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }
   for(size_t i=0; i<field.dims()[0]; i++)
    {
        viewer->addLine(field.nodePosition(i,0), field.nodePosition(i,field.dims()[1]-1), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }

  //Optionally overlay data on the grid
  if (grid_w_data == true )
  {
    //Draw a point for each grid vertex.
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i<field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i, j);
            const float32 c = (val - min) / (max - min);

            Point2D p;
            p.position  = field.nodePosition(i, j);
            p.size = 5;
            //Use a grayscale depending on the actual value
            p.color[0] = c; p.color[1] = c; p.color[2] = c;
            viewer->addPoint(p);
        }
    }
  }



    viewer->refresh();



  //Plot the Iso Contour
  //Traverse the cells
   for(size_t i=0; i<field.dims()[0]-1; i++)
    {
      for(size_t j=0; j<field.dims()[1]-1; j++)
       {
          
         //Compute Max and Min values in each cell
         float32 fval[4];
         fval[0]= field.nodeScalar(i,j);
         fval[1]= field.nodeScalar(i,j+1);
         fval[2]= field.nodeScalar(i+1,j+1);
         fval[3]= field.nodeScalar(i+1,j);

         vector <Vector2f> Pos;
         Pos.resize(4);
         Pos[0]=field.nodePosition(i,j);
         Pos[1]=field.nodePosition(i,j+1);
         Pos[2]=field.nodePosition(i+1,j+1);
         Pos[3]=field.nodePosition(i+1,j);

         //output << "** "<< Pos[0][0] << " " << Pos[0][1] <<"\n";
         //output << field.nodePosition(i,j)[0] << " "<< field.nodePosition(i,j)[1] << "\n" ;

         
         float32 maxf, minf;
         maxf=fmax(fval[0],fval[1]);
         maxf=fmax(maxf,fval[2]);
         maxf=fmax(maxf,fval[3]);
         minf=fmin(fval[0],fval[1]);
         minf=fmin(minf,fval[2]);
         minf=fmin(minf,fval[3]);


         //Check if the iso contour passes the grid
         if((iso_c < minf)  || (iso_c > maxf))
           continue;
         else   //We plot the iso contour
         {
            
              float32 EdgeChar[3][4];

             //Now figure out the signs for the four nodes
               bool sign[4]= {0,0,0,0};
               for(int k=0; k<4; k++)
               {
                 if(fval[k]>=iso_c)
                  sign[k] = 1;
               }

               //Traverse the nodes clockwise and see if the edge carries a crossing point
               for(int k=0; k<4; k++)
               {
                  if( sign[k] ^ sign[(k+1)%4] )
                  {
                    EdgeChar[2][k] = 1;
                    float32 x,y;
                    x = ( (Pos[(k+1)%4][0] - Pos[k][0])*iso_c + Pos[k][0] * fval[(k+1)%4] -  Pos[(k+1)%4][0] * fval[k] ) / ( fval[(k+1)%4] - fval[k] ) ;
                    y = ( (Pos[(k+1)%4][1] - Pos[k][1])*iso_c + Pos[k][1] * fval[(k+1)%4] -  Pos[(k+1)%4][1] * fval[k] ) / ( fval[(k+1)%4] - fval[k] ) ;
                    EdgeChar[0][k] = x;
                    EdgeChar[1][k] = y;

                  }
                  else
                    EdgeChar[2][k] = 0;

                } 
   
                //Count the number of edges that have a valid crossing point. It should be either 2 or 4 
               int EdgeCount=0; 
               for(int k=0; k<4; k++)
               {
                  if(EdgeChar[2][k]==1)
                  EdgeCount++;
               }
               
               if(EdgeCount == 2)
               {
                  //Simply plot the contour
                  vector <Vector2f> LineEnd;
                  LineEnd.clear();
                  LineEnd.resize(2);
                  int index=0;

                  for(int k=0; k<4; k++)
                  {
                    if(EdgeChar[2][k]==1)
                    {
                      LineEnd[index]= makeVector2f(EdgeChar[0][k], EdgeChar[1][k]) ;
                      index++;
                    }
                  }
                  viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(0.5,0.5,0.5,iso_alpha), 2);
                  viewer->refresh();
                  
                  
               }
               else   //Cell has the contour intersecting at 4 points
               {
                 //There is an ambiguity to be resolved
                 float32 fmid= (fval[3]*fval[1] - fval[2]*fval[0]) / ( fval[3]+fval[1] -fval[2] - fval[0] ) ;
                
                  vector <Vector2f> LineEnd;
                  LineEnd.clear();
                  LineEnd.resize(4);

                  for(int k=0; k<4; k++)
                  {
                      LineEnd[k]= makeVector2f(EdgeChar[0][k], EdgeChar[1][k]) ;
                  }


		 if(fval[1] < iso_c)
		 {
                    if(iso_c > fmid)  //Connect 3 to 0 and 1 to 2
                    {
                              viewer->addLine(LineEnd[3], LineEnd[0], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[1], LineEnd[2], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->refresh();
                    }
                    else            //Connect 0 to 1  and 2 to 3    
                    {
                              viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[2], LineEnd[3], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->refresh();
                    }

		 }
		 else
		 {
                    if(iso_c > fmid)  //Connect 0 to 1  and 2 to 3
                    {
                              viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[2], LineEnd[3], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                                viewer->refresh();

                    }
                    else                //Connect 3 to 0 and 1 to 2
                    {
                                            
                              viewer->addLine(LineEnd[3], LineEnd[0], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[1], LineEnd[2], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                               viewer->refresh();

                    }
		 }
         
                 
               
               }
               
          }

           
    }

  }
}