/* Compute and insert migration along directed edge (may fork child) */ static MIGRATION * create_migration(RBFNODE *from_rbf, RBFNODE *to_rbf) { const double end_thresh = 5e-6; PRICEMAT pmtx; MIGRATION *newmig; double *src_rem, *dst_rem; double total_rem = 1., move_amt; int i, j; /* check if exists already */ for (newmig = from_rbf->ejl; newmig != NULL; newmig = nextedge(from_rbf,newmig)) if (newmig->rbfv[1] == to_rbf) return(NULL); /* else allocate */ #ifdef DEBUG fprintf(stderr, "Building path from (theta,phi) (%.0f,%.0f) ", get_theta180(from_rbf->invec), get_phi360(from_rbf->invec)); fprintf(stderr, "to (%.0f,%.0f) with %d x %d matrix\n", get_theta180(to_rbf->invec), get_phi360(to_rbf->invec), from_rbf->nrbf, to_rbf->nrbf); #endif newmig = new_migration(from_rbf, to_rbf); if (run_subprocess()) return(newmig); /* child continues */ price_routes(&pmtx, from_rbf, to_rbf); src_rem = (double *)malloc(sizeof(double)*from_rbf->nrbf); dst_rem = (double *)malloc(sizeof(double)*to_rbf->nrbf); if ((src_rem == NULL) | (dst_rem == NULL)) { fprintf(stderr, "%s: Out of memory in create_migration()\n", progname); exit(1); } /* starting quantities */ memset(newmig->mtx, 0, sizeof(float)*from_rbf->nrbf*to_rbf->nrbf); for (i = from_rbf->nrbf; i--; ) src_rem[i] = rbf_volume(&from_rbf->rbfa[i]) / from_rbf->vtotal; for (j = to_rbf->nrbf; j--; ) dst_rem[j] = rbf_volume(&to_rbf->rbfa[j]) / to_rbf->vtotal; do { /* move a bit at a time */ move_amt = migration_step(newmig, src_rem, dst_rem, &pmtx); total_rem -= move_amt; } while ((total_rem > end_thresh) & (move_amt > 0)); for (i = from_rbf->nrbf; i--; ) { /* normalize final matrix */ double nf = rbf_volume(&from_rbf->rbfa[i]); if (nf <= FTINY) continue; nf = from_rbf->vtotal / nf; for (j = to_rbf->nrbf; j--; ) mtx_coef(newmig,i,j) *= nf; /* row now sums to 1.0 */ } end_subprocess(); /* exit here if subprocess */ free_routes(&pmtx); /* free working arrays */ free(src_rem); free(dst_rem); return(newmig); }
/* Find vertices completing triangles on either side of the given edge */ int get_triangles(RBFNODE *rbfv[2], const MIGRATION *mig) { const MIGRATION *ej1, *ej2; RBFNODE *tv; rbfv[0] = rbfv[1] = NULL; if (mig == NULL) return(0); for (ej1 = mig->rbfv[0]->ejl; ej1 != NULL; ej1 = nextedge(mig->rbfv[0],ej1)) { if (ej1 == mig) continue; tv = opp_rbf(mig->rbfv[0],ej1); for (ej2 = tv->ejl; ej2 != NULL; ej2 = nextedge(tv,ej2)) if (opp_rbf(tv,ej2) == mig->rbfv[1]) { rbfv[is_rev_tri(mig->rbfv[0]->invec, mig->rbfv[1]->invec, tv->invec)] = tv; break; } } return((rbfv[0] != NULL) + (rbfv[1] != NULL)); }
/* Compute and insert migration along directed edge (may fork child) */ static MIGRATION * create_migration(RBFNODE *from_rbf, RBFNODE *to_rbf) { MIGRATION *newmig; int i, j; /* check if exists already */ for (newmig = from_rbf->ejl; newmig != NULL; newmig = nextedge(from_rbf,newmig)) if (newmig->rbfv[1] == to_rbf) return(NULL); /* else allocate */ #ifdef DEBUG fprintf(stderr, "Building path from (theta,phi) (%.1f,%.1f) ", get_theta180(from_rbf->invec), get_phi360(from_rbf->invec)); fprintf(stderr, "to (%.1f,%.1f) with %d x %d matrix\n", get_theta180(to_rbf->invec), get_phi360(to_rbf->invec), from_rbf->nrbf, to_rbf->nrbf); #endif newmig = new_migration(from_rbf, to_rbf); if (run_subprocess()) return(newmig); /* child continues */ /* compute transport plan */ compute_nDSFs(from_rbf, to_rbf); plan_transport(newmig); for (i = from_rbf->nrbf; i--; ) { /* normalize final matrix */ double nf = rbf_volume(&from_rbf->rbfa[i]); if (nf <= FTINY) continue; nf = from_rbf->vtotal / nf; for (j = to_rbf->nrbf; j--; ) mtx_coef(newmig,i,j) *= nf; /* row now sums to 1.0 */ } end_subprocess(); /* exit here if subprocess */ return(newmig); }
/* Check if prospective vertex would create overlapping triangle */ static int overlaps_tri(const RBFNODE *bv0, const RBFNODE *bv1, const RBFNODE *pv) { const MIGRATION *ej; RBFNODE *vother[2]; int im_rev; /* find shared edge in mesh */ for (ej = pv->ejl; ej != NULL; ej = nextedge(pv,ej)) { const RBFNODE *tv = opp_rbf(pv,ej); if (tv == bv0) { im_rev = is_rev_tri(ej->rbfv[0]->invec, ej->rbfv[1]->invec, bv1->invec); break; } if (tv == bv1) { im_rev = is_rev_tri(ej->rbfv[0]->invec, ej->rbfv[1]->invec, bv0->invec); break; } } if (!get_triangles(vother, ej)) /* triangle on same side? */ return(0); return(vother[im_rev] != NULL); }
void impCubeTables::makeTriStripPatterns(){ int i, j, k; int currentvertex; int currentedge; bool vertices[8]; // true if on low side of gradient (outside of surface) bool edges[12]; bool edgesdone[12]; int edgelist[7]; // final list of egdes used in a triangle strip int edgecount; // Set cubetable values to zero // A zero will indicate that there are no more triangle strips to build for(i=0; i<256; i++){ for(j=0; j<17; j++){ triStripPatterns[i][j] = 0; } } // For each vertex combination for(i=0; i<256; i++){ // identify the vertices on the low side of the gradient int andbit; for(j=0; j<8; j++){ andbit = 1; for(k=0; k<j; k++) andbit *= 2; if(i & andbit) vertices[j] = 1; else vertices[j] = 0; } // Identify the edges that cross threshold value // These are edges that connect 1 turned-on and 1 turned-off vertex for(j=0; j<12; j++){ if((vertices[ec[j][0]] + vertices[ec[j][1]]) == 1) edges[j] = 1; else edges[j] = 0; edgesdone[j] = 0; // no edges have been used yet } // Construct lists of edges that form triangle strips // try starting from each edge (no need to try last 2 edges) for(j=0; j<10; j++){ currentedge = j; edgecount = 0; // if this edge contains a surface vertex and hasn't been used while(edges[currentedge] && !edgesdone[currentedge]){ // add edge to list edgelist[edgecount] = currentedge; edgecount ++; edgesdone[currentedge] = 1; // find that edge's vertex on low side of gradient if(vertices[ec[currentedge][0]]) currentvertex = ec[currentedge][0]; else currentvertex = ec[currentedge][1]; // move along gradiant boundary to find next edge currentedge = nextedge(currentvertex, currentedge); while(!edges[currentedge]){ if(currentvertex != ec[currentedge][0]) currentvertex = ec[currentedge][0]; else currentvertex = ec[currentedge][1]; currentedge = nextedge(currentvertex, currentedge); } } // if a surface has been created add it to the table // and start over to try to make another surface if(edgecount) addtotable(i, edgecount, edgelist); } } }