/* basis.c */ #include #include #include "Boolean.h" #include "basis.h" #include "element.h" #include "cubature.h" #include "error.h" BASIS basis[NR_ELEMENT_TYPES][NR_APPROX_TYPES]; static int inited = FALSE; BASIS dummyBasis = { "dummy basis", 0, NULL, NULL }; static double c(double u, double v) { return 1; } static double (*f[1])(double, double) = { c }; BASIS clusterBasis = { "cluster basis", 1, f, f }; struct APPROXDESC approxdesc[NR_APPROX_TYPES] = { {"constant" , 1}, {"linear" , 3}, {"bilinear" , 4}, {"quadratic" , 6}, {"cubic" , 10} }; static BASIS MakeBasis(ELEMENT_TYPE et, APPROX_TYPE at) { BASIS basis = quadBasis; char desc[100], *elem=NULL; switch (et) { case ET_TRIANGLE: basis = triBasis; elem="triangles"; break; case ET_QUAD: basis = quadBasis; elem = "quadrilaterals"; break; default: Fatal(-1, "MakeBasis", "Invalid element type %d", et); } basis.size = approxdesc[at].basis_size; sprintf(desc, "%s orthonormal basis for %s", approxdesc[at].name, elem); basis.description = strdup(desc); return basis; } void PrintBasis(BASIS *basis) { int i; double u=0.5, v=0.5; fprintf(stderr, "%s, size=%d, samples at (%g,%g): ", basis->description, basis->size, u, v); for (i=0; isize; i++) fprintf(stderr, "%g ", basis->function[i](u,v)); fprintf(stderr, "\n"); } #ifdef DEBUG static void PlotBasis(BASIS *basis, int tri) { FILE *fp = stdout; int i,j,k; for (i=0; i<=20; i++) { double u = (double)i/20.; for (j=0; j<=20; j++) { double v = (double)j/20.; fprintf(fp, "%g %g ", u, v); for (k=0; ksize; k++) { if (tri!=3 || u+v<=1+EPSILON) fprintf(fp, "%g ", basis->function[k](u,v)); else fprintf(fp, "%g ", 0.); } fprintf(fp, "\n"); } fprintf(fp, "\n"); } } static void PlotBases(void) { PlotBasis(&triBasis, 3); } #endif /* Computes the filter coefficients for push-pull operations between a * parent and child with given basis and nr of basis functions. 'upxfm' is * the transform to be used to find the point on the parent corresponding * to a given point on the child. 'cr' is the cubature rule to be used * for computing the coefficients. The order should be at least the highest * product of the order of a parent and a child basis function. The filter * coefficients are filled in in the table 'filter'. The filter coefficients are: * * H_{\alpha\,\beta} = int _S phi_\alpha(u',v') phi_\beta(u,v) du dv * * with S the domain on which the basis functions are defined (unit square or * standard triangle), and (u',v') the result of "up-transforming" (u,v). */ static void ComputeFilterCoefficients(BASIS *parent_basis, int parent_size, BASIS *child_basis, int child_size, TRANSFORM2D *upxfm, CUBARULE *cr, FILTER *filter) { int a, b, k; double x; for (a=0; anrnodes; k++) { POINT2D up; up.u = cr->u[k]; up.v = cr->v[k]; TRANSFORM_POINT_2D((*upxfm), up, up); x += cr->w[k] * parent_basis->function[a](up.u, up.v) * child_basis->function[b](cr->u[k], cr->v[k]); } (*filter)[a][b] = x; } } } /* Computes the push-pull filter coefficients for regular subdivision for * elements with given basis and uptransform. The cubature rule 'cr' is used * to compute the coefficients. The coefficients are filled in the * basis->regular_filter table. */ static void ComputeRegularFilterCoefficients(BASIS *basis, TRANSFORM2D *upxfm, CUBARULE *cr) { int s; for (s=0; s<4; s++) { ComputeFilterCoefficients(basis, basis->size, basis, basis->size, &upxfm[s], cr, &(*basis->regular_filter)[s]); } } #ifdef TEST /* This routine should print a unit matrix of size 'size' */ static void TestRegularFilterCoefficients(BASIS *basis, int size) { int a1, a2, b, s; double x; fprintf(stderr, "basis '%s', size %d:\n", basis->description, size); for (a1=0; a1regular_filter)[s][a1][b] * (*basis->regular_filter)[s][a2][b]; } } fprintf(stderr, "%+.3f ", x/4.); } fprintf(stderr, "\n"); } } #endif /* TEST */ void InitBasis(void) { int et, at; if (inited) return; ComputeRegularFilterCoefficients(&triBasis, triupxfm, &CRT8); ComputeRegularFilterCoefficients(&quadBasis, quadupxfm, &CRQ8); #ifdef TEST { int size; for (size=1; size<=triBasis.size; size++) TestRegularFilterCoefficients(&triBasis, size); for (size=1; size<=quadBasis.size; size++) TestRegularFilterCoefficients(&quadBasis, size); } #endif /*TEST*/ for (et=0; etsize; i++) { double s = basis->function[i](u,v); COLORADDSCALED(res, s, rad[i], res); } return res; } /* these routine filter the source coefficients down/up and add * the result to the destination coefficients. */ void FilterColorDown(COLOR *parent, FILTER *h, COLOR *child, int n) { int a, b; for (b=0; b