void CSpline::CSplineInit(int x[], int y[], int n, int grain, float tension) { int i,np; np = n; QPoint jd[100]; QPoint *knots; allCount = 0; lengthList[0] = 0; for(i=1;i<=np;i++) { jd[i].setX(x[i-1]); jd[i].setY(y[i-1]); } jd[0].setX(x[0]); jd[0].setY(y[0]); jd[np+1].setX(x[np-1]); jd[np+1].setY(y[np-1]); np=np+2; // for(i=0;i<=np;i++) // { // jd[i].setX(x[i-1]); // jd[i].setY(y[i-1]); // } knots = jd; CubicSpline(np,knots,grain,tension); }
// [TODO] Comment/Cleanup void CubicSpline::CalculateCubicSpline(uint32 n, Array<TransferControlPoint> &v, Array<CubicSpline> &cubic) { if (n) { // From: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-102-transfer-functions.html float *gamma = new float[n + 1]; float *delta = new float[n + 1]; float *D = new float[n + 1]; // We need to solve the equation // * taken from: http://mathworld.wolfram.com/CubicSpline.html // [2 1 ] [D[0]] [3(v[1] - v[0]) ] // |1 4 1 | |D[1]| |3(v[2] - v[0]) | // | 1 4 1 | | . | = | . | // | ..... | | . | | . | // | 1 4 1| | . | |3(v[n] - v[n-2])| // [ 1 2] [D[n]] [3(v[n] - v[n-1])] // by converting the matrix to upper triangular. // The D[i] are the derivatives at the control points. // This builds the coefficients of the left matrix gamma[0] = 1.0f / 2.0f; for (uint32 i=1; i<n; i++) gamma[i] = 1.0f / ((4 * 1.0f) - gamma[i - 1]); gamma[n] = 1.0f / ((2 * 1.0f) - gamma[n - 1]); delta[0] = 3 * (v[1].GetValue() - v[0].GetValue()) * gamma[0]; for (uint32 i=1; i<n; i++) delta[i] = (3 * (v[i + 1].GetValue() - v[i - 1].GetValue()) - delta[i - 1]) * gamma[i]; delta[n] = (3 * (v[n].GetValue() - v[n - 1].GetValue()) - delta[n - 1]) * gamma[n]; D[n] = delta[n]; for (int i=n-1; i>= 0; i--) D[i] = delta[i] - gamma[i] * D[i + 1]; // Now compute the coefficients of the cubics cubic.Clear(); for (uint32 i=0; i<n; i++) cubic.Add(CubicSpline(v[i].GetValue(), D[i], 3*(v[i + 1].GetValue() - v[i].GetValue()) - 2*D[i] - D[i + 1], 2*(v[i].GetValue() - v[i + 1].GetValue()) + D[i] + D[i + 1])); delete [] gamma; delete [] delta; delete [] D; } }
RealModel::RealModel(Config cfg) { /* Read prior power spectrum from file */ if(!cfg_has_key(cfg, "pkfile")) { fprintf(stderr, "RealModel: must set config option 'pkfile'\n"); return; } const char* pkfile = cfg_get(cfg, "pkfile"); pk = CubicSpline(pkfile); /* Determine bands */ Band b; if(cfg_has_key(cfg, "bands")) { /* Read bands directly */ vector<double> kvals(100); cfg_get_array_double(cfg, "bands", 100, &kvals[0]); if((kvals.size() % 2) != 0) { fprintf(stderr, "RealModel: odd number of kvals\n"); kvals.pop_back(); } for(int n = 0; n < (int)kvals.size()/2; n++) { b.min = kvals[2*n]; b.max = kvals[2*n+1]; bands.push_back(b); } Nbands = bands.size(); } else if(cfg_has_keys(cfg, "Nbands,kmin,kmax")) { /* Use regularly spaced bands */ Nbands = cfg_get_int(cfg, "Nbands"); double kmin = cfg_get_double(cfg, "kmin"); double kmax = cfg_get_double(cfg, "kmax"); /* (Assume linearly spaced bands for now) */ for(int n = 0; n < Nbands; n++) { b.min = kmin + n*(kmax - kmin)/Nbands; b.max = kmin + (n+1)*(kmax - kmin)/Nbands; bands.push_back(b); } } else { fprintf(stderr, "RealModel: k-bands not specified in configuration\n"); return; } }
/* * OpenGL (GLUT) calls this routine to display the scene */ void display() { int k,i; Point S[NMAX]; // Erase the window and the depth buffer glClear(GL_COLOR_BUFFER_BIT); // Enable vertex generation glEnable(GL_MAP1_VERTEX_3); // Draw and label points glColor3f(1,1,1); glPointSize(5); glBegin(GL_POINTS); for (k=0;k<n;k++) glVertex2f(P[k].x,P[k].y); glEnd(); for (k=0;k<n;k++) { glRasterPos2d(P[k].x,P[k].y); Print("P%d",k); } // Draw curve when we have enough points switch (mode) { // Continuous Bezier case 0: for (k=0;k<n-3;k+=3) { glColor3f(1,1,0); glMap1d(GL_MAP1_VERTEX_3,0.0,1.0,3,4,(void*)(P+k)); glMapGrid1f(m,0.0,1.0); glEvalMesh1(GL_LINE,0,m); } break; // Smooth Bezier case 1: // First four if (n>=4) { glColor3f(1,1,0); glMap1d(GL_MAP1_VERTEX_3,0.0,1.0,3,4,(void*)P); glMapGrid1f(m,0.0,1.0); glEvalMesh1(GL_LINE,0,m); } // Subsequent triples for (k=3;k<n-2;k+=2) { Point r[4]; // P0, P2 and P3 are specified points r[0] = P[k]; r[2] = P[k+1]; r[3] = P[k+2]; // P1 is computed by reflecting P2 from previous segment r[1].x = 2*P[k].x-P[k-1].x; r[1].y = 2*P[k].y-P[k-1].y; r[1].z = 2*P[k].z-P[k-1].z; // Draw curve glColor3f(1,1,0); glMap1d(GL_MAP1_VERTEX_3,0.0,1.0,3,4,(void*)r); glMapGrid1f(m,0.0,1.0); glEvalMesh1(GL_LINE,0,m); // Draw reflected point in red glColor3f(1,0,0); glBegin(GL_POINTS); glVertex2f(r[1].x,r[1].y); glEnd(); glRasterPos2d(r[1].x,r[1].y);Print("R%d",k-1); } break; // Interpolate 4 at a time case 2: for (k=0;k<n-3;k+=3) { Point r[4]; // Transform 4 data points to 4 control points Pmult(Mi,P+k,r); // Draw curve glColor3f(1,1,0); glMap1d(GL_MAP1_VERTEX_3,0.0,1.0,3,4,(void*)r); glMapGrid1f(m,0.0,1.0); glEvalMesh1(GL_LINE,0,m); // Draw control points glColor3f(1,0,0); glBegin(GL_POINTS); glVertex2f(r[1].x,r[1].y); glVertex2f(r[2].x,r[2].y); glEnd(); glRasterPos2d(r[1].x,r[1].y);Print("R%d",k+1); glRasterPos2d(r[2].x,r[2].y);Print("R%d",k+2); } break; // B Spline 4 at a time case 3: for (k=0;k<n-3;k++) { int j; Point r[4]; // Transform 4 data points to 4 control points (note increment is 1) Pmult(Ms,P+k,r); // Draw curve glColor3f(1,1,0); glMap1d(GL_MAP1_VERTEX_3,0.0,1.0,3,4,(void*)r); glMapGrid1f(m,0.0,1.0); glEvalMesh1(GL_LINE,0,m); // Draw control points glColor3f(1,0,0); glBegin(GL_POINTS); for (j=0;j<4;j++) glVertex2f(r[j].x,r[j].y); glEnd(); } break; // Cubic Natural Spline case 4: // Calculate (x,y,z) splines CubicSpline((void*)P,(void*)S,0,n); CubicSpline((void*)P,(void*)S,1,n); CubicSpline((void*)P,(void*)S,2,n); // Draw entire curve glColor3f(1,1,0); glBegin(GL_LINE_STRIP); for (k=0;k<n-1;k++) { // Cardinal point glVertex2d(P[k].x,P[k].y); // Increment between k and k+1 for (i=1;i<m;i++) { double f = (double)i/m; double g = 1-f; double f2 = (f*f*f-f)/6; double g2 = (g*g*g-g)/6; double x = f*P[k+1].x + g*P[k].x + f2*S[k+1].x + g2*S[k].x; double y = f*P[k+1].y + g*P[k].y + f2*S[k+1].y + g2*S[k].y; double z = f*P[k+1].z + g*P[k].z + f2*S[k+1].z + g2*S[k].z; glVertex3d(x,y,z); } } // Last cardinal point glVertex2d(P[n-1].x,P[n-1].y); glEnd(); break; default: break; } // Display parameters glColor3f(1,1,1); glWindowPos2i(5,5); Print(text[mode]); if (n<NMAX) Print(" Click to add point\n"); else Print(" Click to start new curve\n"); // Render the scene and make it visible ErrCheck("display"); glFlush(); glutSwapBuffers(); }