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(); }
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"; } } }
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(); }
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(); }
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(); }
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); }
void GMExperiment6_1::displayRawData() { displayData(rawData, makeVector4f(1.0, 0, 0, 1)); }
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)); } } }
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(); }
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(); } } } } } } }