PolygonalMesh* Polygonizer::computeSurfaceNerLinear(float epsilon, float tau) { bool ***isIn = new bool**[dimZ+1]; float ***value = new float**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ isIn[i] = new bool*[dimY+1]; value[i] = new float*[dimY+1]; for(int j=0; j<dimY+1; j++){ isIn[i][j] = new bool[dimX+1]; value[i][j] = new float[dimX+1]; for(int k=0; k<dimX+1; k++){ isIn[i][j][k] = false; value[i][j][k] = 0; } } } float o[3]; o[0] = originX; o[1] = originY; o[2] = originZ; float space[3]; space[0] = spaceX; space[1] = spaceY; space[2] = spaceZ; int dim[3]; dim[0] = dimX; dim[1] = dimY; dim[2] = dimZ; func->asignValueToVoxels(value, isIn, o, space, dim); int ***index = new int**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ index[i] = new int*[dimY+1]; for(int j=0; j<dimY+1; j++){ index[i][j] = new int[dimX+1]; for(int k=0; k<dimX+1; k++) index[i][j][k] = -1; } } int current = 0; int face_N = 0; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isIn[i][j][k] || !isIn[i][j][k+1]) continue; if((value[i][j][k] > 0 && value[i][j][k+1] <= 0) || (value[i][j][k] <= 0 && value[i][j][k+1] > 0)){ face_N++; if(index[i][j][k+1] < 0){ index[i][j][k+1] = current; current++; } if(index[i][j+1][k+1] < 0){ index[i][j+1][k+1] = current; current++; } if(index[i+1][j][k+1] < 0){ index[i+1][j][k+1] = current; current++; } if(index[i+1][j+1][k+1] < 0){ index[i+1][j+1][k+1] = current; current++; } } } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isIn[j][k][i] || !isIn[j][k+1][i]) continue; if((value[j][k][i] > 0 && value[j][k+1][i] <= 0) || (value[j][k][i] <= 0&& value[j][k+1][i] > 0)){ face_N++; if(index[j][k+1][i] < 0){ index[j][k+1][i] = current; current++; } if(index[j+1][k+1][i] < 0){ index[j+1][k+1][i] = current; current++; } if(index[j][k+1][i+1] < 0){ index[j][k+1][i+1] = current; current++; } if(index[j+1][k+1][i+1] < 0){ index[j+1][k+1][i+1] = current; current++; } } } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isIn[k][i][j] || !isIn[k+1][i][j]) continue; if((value[k][i][j] > 0 && value[k+1][i][j] <= 0) || (value[k][i][j] <= 0 && value[k+1][i][j] > 0)){ face_N++; if(index[k+1][i][j] < 0){ index[k+1][i][j] = current; current++; } if(index[k+1][i+1][j] < 0){ index[k+1][i+1][j] = current; current++; } if(index[k+1][i][j+1] < 0){ index[k+1][i][j+1] = current; current++; } if(index[k+1][i+1][j+1] < 0){ index[k+1][i+1][j+1] = current; current++; } } } PolygonalMesh* mesh = new PolygonalMesh; int vertex_N = current; mesh->setVertexCount(vertex_N); float (*vertex)[3] = mesh->vertex; int* degree = mesh->degree_f = new int[vertex_N]; current = 0; for(int i=0; i<vertex_N; i++){ vertex[i][0] = vertex[i][1] = vertex[i][2] = 0; degree[i] = 0; } mesh->setFaceCount(face_N); double (*Q)[10] = new double[vertex_N][10]; for(int i=0; i<vertex_N; i++) MAT_INIT(Q[i]); for(int i=0; i<face_N; i++) mesh->setPolygonCount(i, 4); face_N = 0; int **face = mesh->face; bool flag = false; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isIn[i][j][k] || !isIn[i][j][k+1]) continue; if(value[i][j][k] > 0 && value[i][j][k+1] <= 0){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i][j+1][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i+1][j][k+1]; face_N++; flag = true; } else if(value[i][j][k] <= 0 && value[i][j][k+1] > 0){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i+1][j][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i][j+1][k+1]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[0] = originX + k*spaceX; e[0] = originX + (k+1)*spaceX; s[1] = e[1] = originY + j*spaceY; s[2] = e[2] = originZ + i*spaceZ; float f1 = value[i][j][k]; float f2 = value[i][j][k+1]; searchZero(p, s, e, f1, f2, epsilon); float g[3]; //func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[i][j][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i][j+1][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i+1][j+1][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i+1][j][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isIn[j][k][i] || !isIn[j][k+1][i]) continue; if(value[j][k][i] > 0 && value[j][k+1][i] <= 0){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j+1][k+1][i]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j][k+1][i+1]; face_N++; flag = true; } else if(value[j][k][i] <= 0 && value[j][k+1][i] > 0){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j][k+1][i+1]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j+1][k+1][i]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[1] = originY + k*spaceY; e[1] = originY + (k+1)*spaceY; s[2] = e[2] = originZ + j*spaceZ; s[0] = e[0] = originX + i*spaceX; float f1 = value[j][k][i]; float f2 = value[j][k+1][i]; searchZero(p, s, e, f1, f2, epsilon); float g[3]; //func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[j][k+1][i]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j+1][k+1][i]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j+1][k+1][i+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j][k+1][i+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isIn[k][i][j] || !isIn[k+1][i][j]) continue; if(value[k][i][j] > 0 && value[k+1][i][j] <= 0){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i][j+1]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i+1][j]; face_N++; flag = true; } else if(value[k][i][j] <= 0 && value[k+1][i][j] > 0){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i+1][j]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i][j+1]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[2] = originZ + k*spaceZ; e[2] = originZ + (k+1)*spaceZ; s[0] = e[0] = originX + j*spaceX; s[1] = e[1] = originY + i*spaceY; float f1 = value[k][i][j]; float f2 = value[k+1][i][j]; searchZero(p, s, e, f1, f2, epsilon); float g[3]; //func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[k+1][i][j]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i][j+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i+1][j+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i+1][j]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } //FOR SVD vnl_matrix< float > A( 3, 3, 0. ); vnl_vector<float> b( 3, 0. ); for(int i=0; i<vertex_N; i++){ if(degree[i] == 0) continue; vertex[i][0] /= degree[i]; vertex[i][1] /= degree[i]; vertex[i][2] /= degree[i]; continue; A[0][0] = (float)Q[i][0]; A[1][0] = A[0][1] = (float)Q[i][1]; A[2][0] = A[0][2] = (float)Q[i][2]; A[1][1] = (float)Q[i][3]; A[1][2] = A[2][1] = (float)Q[i][4]; A[2][2] = (float)Q[i][5]; float Av[3]; MAT_BY_VEC(Av, Q[i], vertex[i]); b[1] = -(float)Q[i][6] - Av[0]; b[2] = -(float)Q[i][7] - Av[1]; b[3] = -(float)Q[i][8] - Av[2]; vnl_svd<float> svd( A ); svd.zero_out_absolute( tau ); vnl_vector< float > x = svd.solve( b ); if(fabs(x[1]) > spaceX || fabs(x[2]) > spaceY || fabs(x[3]) > spaceZ) continue; mesh->vertex[i][0] += x[1]; mesh->vertex[i][1] += x[2]; mesh->vertex[i][2] += x[3]; } for(int i=0; i<dimZ+1; i++){ for(int j=0; j<dimY+1; j++){ delete[] isIn[i][j]; delete[] index[i][j]; delete[] value[i][j]; } delete[] isIn[i]; delete[] index[i]; delete[] value[i]; } delete[] isIn; delete[] index; delete[] Q; delete[] value; return mesh; }
PolygonalMesh* Polygonizer::computeSurfaceNet() { float p[3]; bool ***isIn = new bool**[dimZ+1]; bool ***isValid = new bool**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ isIn[i] = new bool*[dimY+1]; isValid[i] = new bool*[dimY+1]; p[2] = originZ + i*spaceZ; for(int j=0; j<dimY+1; j++){ isIn[i][j] = new bool[dimX+1]; isValid[i][j] = new bool[dimX+1]; p[1] = originY + j*spaceY; for(int k=0; k<dimX+1; k++){ p[0] = originX + k*spaceX; isIn[i][j][k] = (func->value(p[0], p[1], p[2], isValid[i][j][k]) > 0); } } } int ***index = new int**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ index[i] = new int*[dimY+1]; for(int j=0; j<dimY+1; j++){ index[i][j] = new int[dimX+1]; for(int k=0; k<dimX+1; k++) index[i][j][k] = -1; } } int current = 0; int face_N = 0; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isValid[i][j][k] || !isValid[i][j][k+1]) continue; if((!isIn[i][j][k] && isIn[i][j][k+1]) || (isIn[i][j][k] && !isIn[i][j][k+1])){ face_N++; if(index[i][j][k+1] < 0){ index[i][j][k+1] = current; current++; } if(index[i][j+1][k+1] < 0){ index[i][j+1][k+1] = current; current++; } if(index[i+1][j][k+1] < 0){ index[i+1][j][k+1] = current; current++; } if(index[i+1][j+1][k+1] < 0){ index[i+1][j+1][k+1] = current; current++; } } } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isValid[j][k][i] || !isValid[j][k+1][i]) continue; if((!isIn[j][k][i] && isIn[j][k+1][i]) || (isIn[j][k][i] && !isIn[j][k+1][i])){ face_N++; if(index[j][k+1][i] < 0){ index[j][k+1][i] = current; current++; } if(index[j+1][k+1][i] < 0){ index[j+1][k+1][i] = current; current++; } if(index[j][k+1][i+1] < 0){ index[j][k+1][i+1] = current; current++; } if(index[j+1][k+1][i+1] < 0){ index[j+1][k+1][i+1] = current; current++; } } } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isValid[k][i][j] || !isValid[k+1][i][j]) continue; if((!isIn[k][i][j] && isIn[k+1][i][j]) || (isIn[k][i][j] && !isIn[k+1][i][j])){ face_N++; if(index[k+1][i][j] < 0){ index[k+1][i][j] = current; current++; } if(index[k+1][i+1][j] < 0){ index[k+1][i+1][j] = current; current++; } if(index[k+1][i][j+1] < 0){ index[k+1][i][j+1] = current; current++; } if(index[k+1][i+1][j+1] < 0){ index[k+1][i+1][j+1] = current; current++; } } } PolygonalMesh* mesh = new PolygonalMesh; int vertex_N = current; mesh->setVertexCount(vertex_N); float (*vertex)[3] = mesh->vertex; current = 0; for(int i=0; i<dimZ+1; i++) for(int j=0; j<dimY+1; j++) for(int k=0; k<dimX+1; k++) if(index[i][j][k] >= 0){ index[i][j][k] = current; vertex[current][0] = spaceX*((float)k-0.5f) + originX; vertex[current][1] = spaceY*((float)j-0.5f) + originY; vertex[current][2] = spaceZ*((float)i-0.5f) + originZ; current++; } mesh->setFaceCount(face_N); for(int i=0; i<face_N; i++) mesh->setPolygonCount(i, 4); face_N = 0; int **face = mesh->face; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isValid[i][j][k] || !isValid[i][j][k+1]) continue; if(isIn[i][j][k] && !isIn[i][j][k+1]){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i][j+1][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i+1][j][k+1]; face_N++; } else if(!isIn[i][j][k] && isIn[i][j][k+1]){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i+1][j][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i][j+1][k+1]; face_N++; } } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isValid[j][k][i] || !isValid[j][k+1][i]) continue; if(isIn[j][k][i] && !isIn[j][k+1][i]){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j+1][k+1][i]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j][k+1][i+1]; face_N++; } else if(!isIn[j][k][i] && isIn[j][k+1][i]){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j][k+1][i+1]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j+1][k+1][i]; face_N++; } } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isValid[k][i][j] || !isValid[k+1][i][j]) continue; if(isIn[k][i][j] && !isIn[k+1][i][j]){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i][j+1]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i+1][j]; face_N++; } else if(!isIn[k][i][j] && isIn[k+1][i][j]){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i+1][j]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i][j+1]; face_N++; } } for(int i=0; i<dimZ+1; i++){ for(int j=0; j<dimY+1; j++){ delete[] isIn[i][j]; delete[] index[i][j]; } delete[] isIn[i]; delete[] index[i]; } delete[] isIn; delete[] index; return mesh; }
PolygonalMesh* Polygonizer::computeSurfaceNetOctTree(float tol, int min, int max) { OctTreeP oct; oct.func = func; oct.originX = originX; oct.originY = originY; oct.originZ = originZ; oct.sizeX = dimX*spaceX; oct.sizeY = dimY*spaceY; oct.sizeZ = dimZ*spaceZ; oct.constructStandard(min, max); int vertex_N, face_N; oct.countVertexAndFace(vertex_N, face_N); PolygonalMesh* mesh = new PolygonalMesh; mesh->setVertexCount(vertex_N); mesh->setFaceCount(face_N); for(int i=0; i<face_N; i++) mesh->setPolygonCount(i, 4); double (*Q)[10] = new double[vertex_N][10]; for(int i=0; i<vertex_N; i++) MAT_INIT(Q[i]); oct.simplify(Q, tol); oct.polygonize2(mesh->vertex, mesh->face); //return mesh; //oct.simplify(Q, tol); //oct.polygonize2(mesh->vertex, mesh->face); //FOR SVD vnl_matrix< float > A( 3, 3, 0. ); vnl_vector<float> b( 3, 0. ), x( 3, 0. ); for(int i=0; i<vertex_N; i++){ A[0][0] = Q[i][0]; A[1][0] = A[0][1] = Q[i][1]; A[2][0] = A[0][2] = Q[i][2]; A[1][1] = Q[i][3]; A[1][2] = A[2][1] = Q[i][4]; A[2][2] = Q[i][5]; float tmp[3]; MAT_BY_VEC(tmp, Q[i], mesh->vertex[i]); b[1] = -Q[i][6] - tmp[0]; b[2] = -Q[i][7] - tmp[1]; b[3] = -Q[i][8] - tmp[2]; vnl_svd< float > svd( A ); svd.zero_out_relative( 0.025 ); x = svd.solve( b ); mesh->vertex[i][0] += x[1]; mesh->vertex[i][1] += x[2]; mesh->vertex[i][2] += x[3]; } delete[] Q; return mesh; }
PolygonalMesh* Polygonizer::computeSurfaceNetSIG02(float epsilon, float tau) { float p[3]; bool ***isIn = new bool**[dimZ+1]; bool ***isValid = new bool**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ isIn[i] = new bool*[dimY+1]; isValid[i] = new bool*[dimY+1]; p[2] = originZ + i*spaceZ; for(int j=0; j<dimY+1; j++){ isIn[i][j] = new bool[dimX+1]; isValid[i][j] = new bool[dimX+1]; p[1] = originY + j*spaceY; for(int k=0; k<dimX+1; k++){ p[0] = originX + k*spaceX; isIn[i][j][k] = (func->value(p[0], p[1], p[2], isValid[i][j][k]) > 0); } } } int ***index = new int**[dimZ+1]; for(int i=0; i<dimZ+1; i++){ index[i] = new int*[dimY+1]; for(int j=0; j<dimY+1; j++){ index[i][j] = new int[dimX+1]; for(int k=0; k<dimX+1; k++) index[i][j][k] = -1; } } int current = 0; int face_N = 0; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isValid[i][j][k] || !isValid[i][j][k+1]) continue; if((!isIn[i][j][k] && isIn[i][j][k+1]) || (isIn[i][j][k] && !isIn[i][j][k+1])){ face_N++; if(index[i][j][k+1] < 0){ index[i][j][k+1] = current; current++; } if(index[i][j+1][k+1] < 0){ index[i][j+1][k+1] = current; current++; } if(index[i+1][j][k+1] < 0){ index[i+1][j][k+1] = current; current++; } if(index[i+1][j+1][k+1] < 0){ index[i+1][j+1][k+1] = current; current++; } } } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isValid[j][k][i] || !isValid[j][k+1][i]) continue; if((!isIn[j][k][i] && isIn[j][k+1][i]) || (isIn[j][k][i] && !isIn[j][k+1][i])){ face_N++; if(index[j][k+1][i] < 0){ index[j][k+1][i] = current; current++; } if(index[j+1][k+1][i] < 0){ index[j+1][k+1][i] = current; current++; } if(index[j][k+1][i+1] < 0){ index[j][k+1][i+1] = current; current++; } if(index[j+1][k+1][i+1] < 0){ index[j+1][k+1][i+1] = current; current++; } } } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isValid[k][i][j] || !isValid[k+1][i][j]) continue; if((!isIn[k][i][j] && isIn[k+1][i][j]) || (isIn[k][i][j] && !isIn[k+1][i][j])){ face_N++; if(index[k+1][i][j] < 0){ index[k+1][i][j] = current; current++; } if(index[k+1][i+1][j] < 0){ index[k+1][i+1][j] = current; current++; } if(index[k+1][i][j+1] < 0){ index[k+1][i][j+1] = current; current++; } if(index[k+1][i+1][j+1] < 0){ index[k+1][i+1][j+1] = current; current++; } } } PolygonalMesh* mesh = new PolygonalMesh; int vertex_N = current; mesh->setVertexCount(vertex_N); float (*vertex)[3] = mesh->vertex; int* degree = mesh->degree_f = new int[vertex_N]; current = 0; for(int i=0; i<vertex_N; i++){ vertex[i][0] = vertex[i][1] = vertex[i][2] = 0; degree[i] = 0; } /* for(i=0; i<dimZ+1; i++) for(int j=0; j<dimY+1; j++) for(int k=0; k<dimX+1; k++) if(index[i][j][k] >= 0){ index[i][j][k] = current; vertex[current][0] = spaceX*((float)k-0.5f) + originX; vertex[current][1] = spaceY*((float)j-0.5f) + originY; vertex[current][2] = spaceZ*((float)i-0.5f) + originZ; current++; } */ mesh->setFaceCount(face_N); double (*Q)[10] = new double[vertex_N][10]; for(int i=0; i<vertex_N; i++) MAT_INIT(Q[i]); for(int i=0; i<face_N; i++) mesh->setPolygonCount(i, 4); face_N = 0; int **face = mesh->face; bool flag = false; for(int i=0; i<dimZ; i++) for(int j=0; j<dimY; j++) for(int k=0; k<dimX-1; k++){ if(!isValid[i][j][k] || !isValid[i][j][k+1]) continue; if(isIn[i][j][k] && !isIn[i][j][k+1]){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i][j+1][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i+1][j][k+1]; face_N++; flag = true; } else if(!isIn[i][j][k] && isIn[i][j][k+1]){ face[face_N][0] = index[i][j][k+1]; face[face_N][1] = index[i+1][j][k+1]; face[face_N][2] = index[i+1][j+1][k+1]; face[face_N][3] = index[i][j+1][k+1]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[0] = originX + k*spaceX; e[0] = originX + (k+1)*spaceX; s[1] = e[1] = originY + j*spaceY; s[2] = e[2] = originZ + i*spaceZ; bisection(p, s, e, epsilon); float g[3]; func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); //if((float)len == 0) //continue; double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[i][j][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i][j+1][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i+1][j+1][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[i+1][j][k+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } for(int i=0; i<dimX; i++) for(int j=0; j<dimZ; j++) for(int k=0; k<dimY-1; k++){ if(!isValid[j][k][i] || !isValid[j][k+1][i]) continue; if(isIn[j][k][i] && !isIn[j][k+1][i]){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j+1][k+1][i]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j][k+1][i+1]; face_N++; flag = true; } else if(!isIn[j][k][i] && isIn[j][k+1][i]){ face[face_N][0] = index[j][k+1][i]; face[face_N][1] = index[j][k+1][i+1]; face[face_N][2] = index[j+1][k+1][i+1]; face[face_N][3] = index[j+1][k+1][i]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[1] = originY + k*spaceY; e[1] = originY + (k+1)*spaceY; s[2] = e[2] = originZ + j*spaceZ; s[0] = e[0] = originX + i*spaceX; bisection(p, s, e, epsilon); float g[3]; func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); //if((float)len == 0) //continue; double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[j][k+1][i]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j+1][k+1][i]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j+1][k+1][i+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[j][k+1][i+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } for(int i=0; i<dimY; i++) for(int j=0; j<dimX; j++) for(int k=0; k<dimZ-1; k++){ if(!isValid[k][i][j] || !isValid[k+1][i][j]) continue; if(isIn[k][i][j] && !isIn[k+1][i][j]){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i][j+1]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i+1][j]; face_N++; flag = true; } else if(!isIn[k][i][j] && isIn[k+1][i][j]){ face[face_N][0] = index[k+1][i][j]; face[face_N][1] = index[k+1][i+1][j]; face[face_N][2] = index[k+1][i+1][j+1]; face[face_N][3] = index[k+1][i][j+1]; face_N++; flag = true; } if(!flag) continue; flag = false; float p[3], s[3], e[3]; s[2] = originZ + k*spaceZ; e[2] = originZ + (k+1)*spaceZ; s[0] = e[0] = originX + j*spaceX; s[1] = e[1] = originY + i*spaceY; bisection(p, s, e, epsilon); float g[3]; func->gradient(g, p[0], p[1], p[2]); double len = PolygonalMesh::LENGTH(g); //if((float)len == 0) //continue; double nor[3]; nor[0] = g[0]/len; nor[1] = g[1]/len; nor[2] = g[2]/len; double d = -PolygonalMesh::DOT(nor, p); double Q_tmp[10]; MATRIX(Q_tmp, nor, d); int i0 = index[k+1][i][j]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i][j+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i+1][j+1]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; i0 = index[k+1][i+1][j]; MAT_SUM(Q[i0], Q_tmp); vertex[i0][0] += p[0]; vertex[i0][1] += p[1]; vertex[i0][2] += p[2]; degree[i0]++; } //FOR SVD vnl_matrix< float > A( 3, 3, 0. ); vnl_vector< float > b(3, 0.), x(3, 0.); for(int i=0; i<vertex_N; i++){ if(degree[i] == 0) continue; vertex[i][0] /= degree[i]; vertex[i][1] /= degree[i]; vertex[i][2] /= degree[i]; continue; A[0][0] = (float)Q[i][0]; A[1][0] = A[0][1] = (float)Q[i][1]; A[2][0] = A[0][2] = (float)Q[i][2]; A[1][1] = (float)Q[i][3]; A[1][2] = A[2][1] = (float)Q[i][4]; A[2][2] = (float)Q[i][5]; float Av[3]; MAT_BY_VEC(Av, Q[i], vertex[i]); b[0] = -(float)Q[i][6] - Av[0]; b[1] = -(float)Q[i][7] - Av[1]; b[2] = -(float)Q[i][8] - Av[2]; vnl_svd<float> svd( A ); svd.zero_out_absolute( 0.0000001 ); x = svd.solve( b ); if(fabs(x[1]) > spaceX || fabs(x[2]) > spaceY || fabs(x[3]) > spaceZ) continue; mesh->vertex[i][0] += x[1]; mesh->vertex[i][1] += x[2]; mesh->vertex[i][2] += x[3]; } for(int i=0; i<dimZ+1; i++){ for(int j=0; j<dimY+1; j++){ delete[] isIn[i][j]; delete[] index[i][j]; } delete[] isIn[i]; delete[] index[i]; } delete[] isIn; delete[] index; delete[] Q; delete[] isValid; return mesh; }
//2D mesh for cross sections. (for the paper) PolygonalMesh* HRBF::generateCrossSection(float o[], float t1[], float t2[], int n, int m) { PolygonalMesh *mesh = new PolygonalMesh; mesh->setVertexCount(n*m); mesh->setFaceCount((n-1)*(m-1)); int **face = mesh->face; float (*vertex)[3] = mesh->vertex; float *v = mesh->value = new float[mesh->vertex_N]; mesh->isValid = new bool[mesh->vertex_N]; mesh->isCovered = new bool[mesh->vertex_N]; double t3[3]; PolygonalMesh::CROSS(t3, t1, t2); double len = PolygonalMesh::LENGTH(t3); //0.3 for kernal t3[0] /= -0.4*len; t3[1] /= -0.4*len; t3[2] /= -0.4*len; int i; for(i = 0; i< mesh->vertex_N; i++) mesh->isValid[i] = true; for(i=0; i<n; i++){ float p1[3]; p1[0] = o[0] + t1[0]*i; p1[1] = o[1] + t1[1]*i; p1[2] = o[2] + t1[2]*i; for(int j=0; j<m; j++){ float p2[3]; p2[0] = t2[0]*j; p2[1] = t2[1]*j; p2[2] = t2[2]*j; int index = i*m+j; vertex[index][0] = p1[0] + p2[0]; vertex[index][1] = p1[1] + p2[1]; vertex[index][2] = p1[2] + p2[2]; bool flag; float f = value(vertex[index][0], vertex[index][1], vertex[index][2], flag);//);// if(_isnan(f)){ v[index] = 0; continue; } /* vertex[index][0] += f*(float)t3[0]; vertex[index][1] += f*(float)t3[1]; vertex[index][2] += f*(float)t3[2]; */ v[index] = f; mesh->isCovered[index] = flag; //if(!flag) //v[index] = 1000000; //else //v[index] = -10000000; } } for(i=0; i<n-1; i++){ for(int j=0; j<m-1; j++){ int index = i*(m-1)+j; mesh->setPolygonCount(index, 4); face[index][3] = i*m+j; face[index][2] = (i+1)*m+j; face[index][1] = (i+1)*m+j+1; face[index][0] = i*m+j+1; //bool flag = (v[face[index][0]] > 0); /* if(PolygonalMesh::LENGTH(vertex[face[index][0]]) > 5 || PolygonalMesh::LENGTH(vertex[face[index][1]]) > 5 || PolygonalMesh::LENGTH(vertex[face[index][2]]) > 5 || PolygonalMesh::LENGTH(vertex[face[index][3]]) > 5) face[index][0] = -1; */ /* for(int k=1; k<4; k++){ if(flag != (v[face[index][k]] > 0)){ v[i*n+j] = -100; } }*/ /* if(v[face[index][0]] == v[face[index][1]] == v[face[index][2]] == v[face[index][3]] == 0) v[i*n+j] = 1000000;*/ } } mesh->computeFaceNormal(); return mesh; }