Bounds Bounds::map(Transform t) const { Interval x { xmin, xmax }; Interval y { ymin, ymax }; Interval z { zmin, zmax }; Interval x_out = x; Interval y_out = y; Interval z_out = z; if (t.x_reverse.length()) { MathTree* tree = parse(t.x_reverse.c_str()); if (tree == NULL) { throw fab::ParseError(); } x_out = eval_i(tree, x, y, z); free_tree(tree); } if (t.y_reverse.length()) { MathTree* tree = parse(t.y_reverse.c_str()); if (tree == NULL) { throw fab::ParseError(); } y_out = eval_i(tree, x, y, z); free_tree(tree); } if (t.z_reverse.length()) { MathTree* tree = parse(t.z_reverse.c_str()); if (tree == NULL) { throw fab::ParseError(); } z_out = eval_i(tree, x, y, z); free_tree(tree); } return Bounds(x_out.lower, y_out.lower, z_out.lower, x_out.upper, y_out.upper, z_out.upper); }
//"normalize" normalizes the PP-Rep, i.e. changes break point data //and pp-coefficients so as that length of first derivatives // from left and right at each break point are the same. MGPPRep& MGPPRep::normalize(){ if(m_nbreak<=2) return *this; MGNDDArray bp(break_point()); size_t i,j,k; double len1,len2,len; MGVector v1, v2; v1=eval_i(0,bp(1),1); len1=v1.len(); //len1 is length of 1st derivatives at break_point(1) of the 1st span. if(!MGRZero(len1)){ //Length of 1st deriv at the end of 1st span is set to unit. break_point(0)=bp(0)*len1; break_point(1)=bp(1)*len1; len=1./len1; for(i=1; i<m_order; i++){ for(k=0; k<m_sdim; k++) coef(i,0,k)=coef(i,0,k)*len; len /=len1; } } for(j=1; j<m_nbreak-1; j++){ //Change the length of the next span(len2) so as to be the same as //previous span's end point(len1). v1=eval_i(j-1,break_point(j),1); len1=v1.len(); v2=coef(1,j); len2=v2.len(); if(!MGRZero(len2)){ len1=len1/len2; len=len1; for(i=1; i<m_order; i++){ for(k=0; k<m_sdim; k++) coef(i,j,k)=coef(i,j,k)*len; len *=len1; } len=bp(j+1)-bp(j); len=len/len1; break_point(j+1)=break_point(j)+len; } } return *this; }
void render8(MathTree* tree, Region region, uint8_t** img, volatile int* halt, void (*callback)()) { // Special interrupt system, set asynchronously by on high if (*halt) return; // Render pixel-by-pixel if we're below a certain size. if (region.voxels > 0 && region.voxels < MIN_VOLUME) { if (callback) (*callback)(); region8(tree, region, img); return; } // Pre-emptively halt evaluation if all the points in this // region are already light. uint8_t L = region.L[region.nk] >> 8; bool cull = true; for (int row = region.jmin; cull && row < region.jmin + region.nj; ++row) { for (int col = region.imin; cull && col < region.imin + region.ni; ++col) { if (L > img[row][col]) { cull = false; break; } } } if (cull) return; Interval X = {region.X[0], region.X[region.ni]}, Y = {region.Y[0], region.Y[region.nj]}, Z = {region.Z[0], region.Z[region.nk]}; Interval result = eval_i(tree, X, Y, Z); // If we're inside the object, fill with color. if (result.upper < 0) { for (int row = region.jmin; row < region.jmin + region.nj; ++row) { for (int col = region.imin; col < region.imin + region.ni; ++col) { if (L > img[row][col]) img[row][col] = L; } } } // In unambiguous cases, return immediately if (result.upper < 0 || result.lower >= 0) return; #if PRUNE disable_nodes(tree); disable_nodes_binary(tree); #endif // Subdivide and recurse if we're not at voxel size. if (region.ni*region.nj*region.nk > 1) { Region A, B; bisect(region, &A, &B); render8(tree, B, img, halt, callback); render8(tree, A, img, halt, callback); } #if PRUNE enable_nodes(tree); #endif }