void trimesh_t::remove_splinters() { list<trimesh_node_t*>::iterator triangle_iterator; int edge, dummy, i, j=0, k = 0; vertex_t new_verticies[3]; cout << "starting to desplinter.\n"; for (triangle_iterator = triangles.begin(); triangle_iterator != triangles.end(); triangle_iterator++) { // Copy verticies into a local list for (i=0; i<3; i++) new_verticies[i] = *(*triangle_iterator)->verticies[i]; // Do ratio test if (!ratio_test(new_verticies, &dummy)) { // If this triangle fails the test, search edge neighbors // for one that passes j++; for(edge = 0; edge < 3; edge++) { if ((*triangle_iterator)->repair_triangles((*triangle_iterator), (*triangle_iterator)->neighbors[edge]) == 0) { k++; break; } } // Combine and split these triangles into two non-degenerate triangles } } cout << "try to desplinter " << j << "triangles, suceeded on " << k << "triangles \n"; }
int solver2( int m, /* number of constraints */ int N, /* number of variables */ int nz, /* number of nonzeros in sparse constraint matrix */ int *ia, /* array row indices */ int *ka, /* array of indices into ia and a */ double *a, /* array of nonzeros in the constraint matrix */ double *b, /* right-hand side */ double *c, /* objective coefficients */ double *c2, /* objective coefficients */ double f, /* objective function shift */ int *basics, int *nonbasics, int *basicflag, int *freevars, int d1, int d2, double **BETAhat ) { double *x_B; /* primal basics */ double *y_N; /* dual nonbasics */ double *xbar_B; /* primal basic perturbation */ double *ybar_N; /* dual nonbasic perturbation */ double *dy_N; /* dual basics step direction - values (sparse) */ int *idy_N; /* dual basics step direction - row indices */ int ndy_N; /* number of nonz in dy_N */ double *dx_B; /* primal basics step direction - values (sparse) */ int *idx_B; /* primal basics step direction - row indices */ int ndx_B; /* number of nonz in dx_B */ double *at; /* sparse data structure for A^T */ int *iat; int *kat; int col_in; /* entering column; index in 'nonbasics' */ int col_out; /* leaving column; index in 'basics' */ int iter = 0; /* number of iterations */ int i,j,k,n,v=0, j1,j2,ii; double s, t, sbar, tbar, mu=HUGE_VAL, old_mu, primal_obj; double *vec; int *ivec; int nvec; int status=0; int from_scratch; /******************************************************************* * For convenience, we put... *******************************************************************/ int n0 = d1*d2; n = N-m; /******************************************************************* * Read in the Data and initialize the common memory sites. *******************************************************************/ CALLOC( x_B, m, double ); CALLOC( xbar_B, m, double ); CALLOC( dx_B, m, double ); CALLOC( y_N, n, double ); CALLOC( ybar_N, n, double ); CALLOC( dy_N, n, double ); CALLOC( vec, N, double ); CALLOC( idx_B, m, int ); CALLOC( idy_N, n, int ); CALLOC( ivec, N, int ); CALLOC( at, nz, double ); CALLOC( iat, nz, int ); CALLOC( kat, m+1, int ); /**************************************************************** * Initialization. * ****************************************************************/ atnum(m,N,ka,ia,a,kat,iat,at); lufac( m, ka, ia, a, basics, 0); for (j=0; j<n; j++) { y_N[j] = 0; } nvec = 0; for (i=0; i<m; i++) { if (c[basics[i]] != 0.0) { vec[nvec] = c[basics[i]]; ivec[nvec] = i; nvec++; } } btsolve( m, vec, ivec, &nvec ); Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N ); for (k=0; k<ndy_N; k++) { y_N[idy_N[k]] = dy_N[k]; } for (j=0; j<n; j++) { y_N[j] -= c[nonbasics[j]]; } for (j=0; j<n; j++) { ybar_N[j] = 0; } nvec = 0; for (i=0; i<m; i++) { if (c2[basics[i]] != 0.0) { vec[nvec] = c2[basics[i]]; ivec[nvec] = i; nvec++; } } btsolve( m, vec, ivec, &nvec ); Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N ); for (k=0; k<ndy_N; k++) { ybar_N[idy_N[k]] = dy_N[k]; } for (j=0; j<n; j++) { ybar_N[j] -= c2[nonbasics[j]]; if (ybar_N[j] < 0) printf("error: ybar_N[%d] = %e \n", j, ybar_N[j]); } for (i=0; i<m; i++) { x_B[i] = 0; xbar_B[i] = 0; } nvec = 0; for (i=0; i<m; i++) { if ( b[i] != 0.0 ) { vec[nvec] = b[i]; ivec[nvec] = i; nvec++; } } bsolve( m, vec, ivec, &nvec ); for (i=0; i<nvec; i++) { x_B[ivec[i]] = vec[i]; if (vec[i] < 0) printf("error: x_B[%d] = %e \n", i, vec[i]); } /* printf ("m = %d,n = %d,nz = %d\n",m,N,nz); printf( "---------------------------------------------------------------------------\n" " | Primal | | arithmetic \n" " Iter | Obj Value | mu | nonz(L) nonz(U) operations \n" "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" );*/ /**************************************************************** * Main loop * ****************************************************************/ for (iter=0; iter<MAX_ITER; iter++) { /************************************************************* * STEP 1: Find mu * *************************************************************/ old_mu = mu; mu = -HUGE_VAL; col_in = -1; for (j=0; j<n; j++) { if (ybar_N[j] > EPS2) { if ( mu < -y_N[j]/ybar_N[j] ) { mu = -y_N[j]/ybar_N[j]; col_in = j; } } } col_out = -1; for (i=0; i<m; i++) { if (freevars[basics[i]] == 0) { if (xbar_B[i] > EPS2) { if ( mu < -x_B[i]/xbar_B[i] ) { mu = -x_B[i]/xbar_B[i]; col_out = i; col_in = -1; } } } } /************************************************************* * STEP 0: Record current portfolio * *************************************************************/ primal_obj = sdotprod(c,x_B,basics,m) + f; if ( mu <= EPS3 || primal_obj > -EPS0) { /* OPTIMAL */ for (j1=0; j1<d1; j1++) { for (j2=0; j2<d2; j2++) { BETAhat[j1][j2] = 0; } } for (i=0; i<m; i++) { if (basics[i] < n0 && x_B[i] > EPS0) { ii = basics[i]; j1 = ii%d1; j2 = ii/d1; BETAhat[j1][j2] = x_B[i]; } else if (basics[i] < 2*n0 && x_B[i] > EPS0) { ii = basics[i]-n0; j1 = ii%d1; j2 = ii/d1; BETAhat[j1][j2] = -x_B[i]; } } for (j1=0; j1<d1; j1++) { for (j2=0; j2<d2; j2++) { if (ABS(BETAhat[j1][j2]) > 1e-5) { } } } status = 0; break; } if ( col_out >= 0 ) { /************************************************************* * -1 T * * STEP 2: Compute dy = -(B N) e * * N i * * where i = col_out * *************************************************************/ vec[0] = -1.0; ivec[0] = col_out; nvec = 1; btsolve( m, vec, ivec, &nvec ); Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N ); /************************************************************* * STEP 3: Ratio test to find entering column * *************************************************************/ col_in = ratio_test2( dy_N, idy_N, ndy_N, y_N, ybar_N, mu ); if (col_in == -1) { /* INFEASIBLE*/ status = 2; printf("infeasible \n"); break; } /************************************************************* * -1 * * STEP 4: Compute dx = B N e * * B j * * * *************************************************************/ j = nonbasics[col_in]; for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) { dx_B[i] = a[k]; idx_B[i] = ia[k]; } ndx_B = i; bsolve( m, dx_B, idx_B, &ndx_B ); } else { /************************************************************* * -1 * * STEP 2: Compute dx = B N e * * B j * *************************************************************/ j = nonbasics[col_in]; for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) { dx_B[i] = a[k]; idx_B[i] = ia[k]; } ndx_B = i; bsolve( m, dx_B, idx_B, &ndx_B ); /************************************************************* * STEP 3: Ratio test to find leaving column * *************************************************************/ col_out = ratio_test( dx_B, idx_B, ndx_B, x_B, xbar_B, basics, freevars, mu ); if (col_out == -1) { /* UNBOUNDED */ status = 1; printf("unbounded \n"); break; } /************************************************************* * -1 T * * STEP 4: Compute dy = -(B N) e * * N i * * * *************************************************************/ vec[0] = -1.0; ivec[0] = col_out; nvec = 1; btsolve( m, vec, ivec, &nvec ); Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N ); } /************************************************************* * * * STEP 5: Put t = x /dx * * i i * * _ _ * * t = x /dx * * i i * * s = y /dy * * j j * * _ _ * * s = y /dy * * j j * *************************************************************/ for (k=0; k<ndx_B; k++) if (idx_B[k] == col_out) break; t = x_B[col_out]/dx_B[k]; tbar = xbar_B[col_out]/dx_B[k]; for (k=0; k<ndy_N; k++) if (idy_N[k] == col_in) break; s = y_N[col_in]/dy_N[k]; sbar = ybar_N[col_in]/dy_N[k]; /************************************************************* * _ _ _ * * STEP 7: Set y = y - s dy y = y - s dy * * N N N N N N * * _ _ * * y = s y = s * * i i * * _ _ _ * * x = x - t dx x = x - t dx * * B B B B B B * * _ _ * * x = t x = t * * j j * *************************************************************/ for (k=0; k<ndy_N; k++) { j = idy_N[k]; y_N[j] -= s *dy_N[k]; ybar_N[j] -= sbar*dy_N[k]; } y_N[col_in] = s; ybar_N[col_in] = sbar; for (k=0; k<ndx_B; k++) { i = idx_B[k]; x_B[i] -= t *dx_B[k]; xbar_B[i] -= tbar*dx_B[k]; } x_B[col_out] = t; xbar_B[col_out] = tbar; /************************************************************* * STEP 8: Update basis * *************************************************************/ i = basics[col_out]; j = nonbasics[col_in]; basics[col_out] = j; nonbasics[col_in] = i; basicflag[i] = -col_in-1; basicflag[j] = col_out; /************************************************************* * STEP 9: Refactor basis and print statistics * *************************************************************/ from_scratch = refactor( m, ka, ia, a, basics, col_out, v); if (from_scratch) { primal_obj = sdotprod(c,x_B,basics,m) + f; /* printf("%8d %14.7e %9.2e \n", iter, high(primal_obj), high(mu)); fflush(stdout);*/ } } primal_obj = sdotprod(c,x_B,basics,m) + f; /**************************************************************** * Transcribe solution to x vector and dual solution to y * ****************************************************************/ /**************************************************************** * Split out slack variables and shift dual variables. ****************************************************************/ /**************************************************************** * Free work space * ****************************************************************/ Nt_times_y(-1, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N); FREE(at); FREE(iat); FREE(xbar_B); FREE(kat); FREE(ybar_N); lu_clo(); btsolve(0, vec, ivec, &nvec); bsolve(0, vec, ivec, &nvec); FREE( vec ); FREE( ivec ); FREE( x_B ); FREE( y_N ); FREE( dx_B ); FREE(idx_B ); FREE( dy_N ); FREE(idy_N ); FREE( nonbasics ); FREE( basics ); return status; } /* End of solver */
// Takes two edge-neighbor triangles, joins them into a quadrilateral, // and then splits them the opposite way. This is used to repair degenerate // triangles and to remove very small sliver triangles. int trimesh_node_t::repair_triangles(trimesh_node_t* triangle_a, trimesh_node_t* triangle_b) { int i,j, edge_a = -1, edge_b = -1, dummy; vertex_t* quad_verticies[4]; trimesh_node_t* quad_neighbors[4]; trimesh_node_t* old_quad_neighbor[4]; trimesh_node_t* new_quad_neighbor[4]; vertex_t verticies_a[3]; vertex_t verticies_b[3]; vector_t normal_a, normal_b; int vertex_a[3]; int vertex_b[3]; // Get the common edge for (i=0; i<3; i++) { if ((triangle_a->neighbors[i]) == triangle_b) edge_a = i; if ((triangle_b->neighbors[i]) == triangle_a) edge_b = i; } // If these triangles are not edge neighbors, return without doing anything if ((edge_a == -1) || (edge_b == -1)) return(1); // The verticies for quadrilateral, in order, are: // opposite vertex of a from edge // next vertex of a // opposite vertex of b from edge // next vetex of a vertex_a[0] = opposite_vertex_from_edge(edge_a); vertex_a[1] = next_vertex(vertex_a[0]); vertex_a[2] = next_vertex(vertex_a[1]); vertex_b[0] = opposite_vertex_from_edge(edge_b); vertex_b[1] = next_vertex(vertex_b[0]); vertex_b[2] = next_vertex(vertex_b[1]); quad_verticies[0] = triangle_a->verticies[vertex_a[0]]; quad_verticies[1] = triangle_a->verticies[vertex_a[1]]; quad_verticies[2] = triangle_b->verticies[vertex_b[0]]; quad_verticies[3] = triangle_b->verticies[vertex_b[1]]; // The edge neighbors for the quadrilateral come from calling // get edge on the vertex number list... quad_neighbors[0] = triangle_a->neighbors[get_edge_number(vertex_a[0], vertex_a[1])]; quad_neighbors[1] = triangle_b->neighbors[get_edge_number(vertex_b[2], vertex_b[0])]; quad_neighbors[2] = triangle_b->neighbors[get_edge_number(vertex_b[0], vertex_b[1])]; quad_neighbors[3] = triangle_a->neighbors[get_edge_number(vertex_a[2], vertex_a[0])]; // Test resultant triangles to make sure they both pass the ratio test, and their // normal angle is not too different. If not, do not do this. (This catches the case of // non-convex quadrilaterals) verticies_a[0] = *quad_verticies[0]; verticies_a[1] = *quad_verticies[1]; verticies_a[2] = *quad_verticies[2]; verticies_b[0] = *quad_verticies[2]; verticies_b[1] = *quad_verticies[3]; verticies_b[2] = *quad_verticies[0]; if (ratio_test(verticies_a, &dummy) && ratio_test(verticies_b, &dummy)) { normal_a = normalize(cross(sub(verticies_a[1],verticies_a[0]), sub(verticies_a[2], verticies_a[0]))); normal_b = normalize(cross(sub(verticies_b[1],verticies_b[0]), sub(verticies_b[2], verticies_b[0]))); // If triangles have the same normal to within 90 degrees... if (dot(normal_a, normal_b) > 0) { // Write them out. old_quad_neighbor[0] = triangle_a; old_quad_neighbor[1] = triangle_b; old_quad_neighbor[2] = triangle_b; old_quad_neighbor[3] = triangle_a; // Now split the quadrilateral into two triangles, overwriting the old triangles // Update Verticies triangle_a->verticies[0] = quad_verticies[0]; triangle_a->verticies[1] = quad_verticies[1]; triangle_a->verticies[2] = quad_verticies[2]; triangle_b->verticies[0] = quad_verticies[2]; triangle_b->verticies[1] = quad_verticies[3]; triangle_b->verticies[2] = quad_verticies[0]; // Update Neighbors triangle_a->neighbors[0] = quad_neighbors[0]; triangle_a->neighbors[1] = quad_neighbors[1]; triangle_a->neighbors[2] = triangle_b; triangle_b->neighbors[0] = quad_neighbors[2]; triangle_b->neighbors[1] = quad_neighbors[3]; triangle_b->neighbors[2] = triangle_a; // Update our neigbors as to their new neighbors new_quad_neighbor[0] = triangle_a; new_quad_neighbor[1] = triangle_a; new_quad_neighbor[2] = triangle_b; new_quad_neighbor[3] = triangle_b; for (j=0; j<4; j++) { for(i=0; i<3; i++) { if (quad_neighbors[j]->neighbors[i] == old_quad_neighbor[j]) { quad_neighbors[j]->neighbors[i] = new_quad_neighbor[j]; break; } } } return(0); } else { return(1); } } else { return(1); } }