示例#1
0
/*
 * ***************************************************************************
 * Routine:  SurfaceMesh_refine
 *
 * Author:   Johan Hake ([email protected])
 *
 * Purpose:  Refine a surface mesh and recalculate the neighbors
 * ***************************************************************************
 */
void SurfaceMesh_refine(SurfaceMesh* surfmesh)
{
  unsigned int local_num_edges = 0, total_num_edges = 0, edge_num = 0;
  unsigned int min_vertex_num, max_vertex_num, face_num;
  unsigned int k, m, n, nv;
  unsigned int a, b, c;
  unsigned int* num_edges;
  unsigned int* offsets;
  unsigned int* vertex2edge;
  unsigned int local_vertices[3], local_additional_vertices[3];
  NPNT3* ngr;
  SurfaceMesh* surfmesh_refine;
  float ax, ay, az;
  float nx, ny, nz;
  
  // Check if neighborlist is created
  if (surfmesh->neighbor_list == NULL)
    SurfaceMesh_createNeighborlist(surfmesh);

  NPNT3** neighbor_list = surfmesh->neighbor_list;

  // Assign the number of vertices in the original mesh
  nv = surfmesh->num_vertices;

  // Create an array with the number of edges associated with each vertex
  num_edges = (unsigned int*)malloc(sizeof(unsigned int)*nv);

  // Create an array with the offsets into the vertex2edge array for each vertex
  offsets = (unsigned int*)malloc(sizeof(unsigned int)*nv);

  // Iterate over all vertices and collect edges
  for (n = 0; n < nv; n++){
    offsets[n] = total_num_edges;
    local_num_edges = 0;
    ngr = neighbor_list[n];
    while (ngr != NULL) {
      // If n is smaller than ngr->a we have an edge
      if (n < ngr->a){
	total_num_edges++;
	local_num_edges++;
      }
      ngr = ngr->next;
    }
    num_edges[n] = local_num_edges;
    
  }
  
  // Create memory for the refined mesh
  surfmesh_refine = SurfaceMesh_ctor(nv + total_num_edges, surfmesh->num_faces*4);
  surfmesh_refine->num_vertices = nv;
  surfmesh_refine->num_faces = surfmesh->num_faces;
  
  // Copy the original mesh to the new mesh
  for (n = 0; n < nv; n++) {
    surfmesh_refine->vertex[n].x = surfmesh->vertex[n].x;
    surfmesh_refine->vertex[n].y = surfmesh->vertex[n].y;
    surfmesh_refine->vertex[n].z = surfmesh->vertex[n].z;
  }
  
  for (n = 0; n < surfmesh->num_faces; n++) {
    surfmesh_refine->face[n].a = surfmesh->face[n].a;
    surfmesh_refine->face[n].b = surfmesh->face[n].b;
    surfmesh_refine->face[n].c = surfmesh->face[n].c;
  }
  
  // Create the map from vertices to edges
  vertex2edge = (unsigned int*)malloc(sizeof(unsigned int)*total_num_edges);

  // Iterate over all vertices and split edges
  for (n = 0; n < nv; n++){

    // Get the coordinates of vertex n
    nx = surfmesh_refine->vertex[n].x;
    ny = surfmesh_refine->vertex[n].y;
    nz = surfmesh_refine->vertex[n].z;

    ngr = neighbor_list[n];
    while (ngr != NULL) {
   
      // If n is smaller than ngr->a we have an edge
      if (n < ngr->a){

	// Add the value of the opposite vertex to the map
	vertex2edge[edge_num] = ngr->a;
	
	// Get the coordinates of vertex ngr->a
	ax = surfmesh_refine->vertex[ngr->a].x;
	ay = surfmesh_refine->vertex[ngr->a].y;
	az = surfmesh_refine->vertex[ngr->a].z;
	
	// Add the new vertex coordinates of the splitted edge
	surfmesh_refine->vertex[nv + edge_num].x = 0.5*(ax + nx);
	surfmesh_refine->vertex[nv + edge_num].y = 0.5*(ay + ny);
	surfmesh_refine->vertex[nv + edge_num].z = 0.5*(az + nz);
	
	// Increase the edge number
	edge_num++;
      }
      ngr = ngr->next;
    }
  }

  // A counter for adding new faces
  face_num = surfmesh_refine->num_faces;

  // Iterate over faces and add information of the refined face
  for (n = 0; n < surfmesh_refine->num_faces; n++) {
    local_vertices[0] = surfmesh_refine->face[n].a;
    local_vertices[1] = surfmesh_refine->face[n].b;
    local_vertices[2] = surfmesh_refine->face[n].c;

    // Iterate over the vertices and find the edges
    for (m = 0; m < 3; m++){
      min_vertex_num = min(local_vertices[m], local_vertices[(m+1)%3]);
      max_vertex_num = max(local_vertices[m], local_vertices[(m+1)%3]);
      
      // Find the edge number that fit the pair of vertices
      for (k = 0; k < num_edges[min_vertex_num]; k++)
	if (vertex2edge[offsets[min_vertex_num] + k] == max_vertex_num)
	  break;
      
      // The edge number represents the number of the added vertex plus the 
      // number of original vertices
      local_additional_vertices[m] = nv + offsets[min_vertex_num] + k;

    }
    
    // Add information of the four new faces

    // First the mid face
    surfmesh_refine->face[n].a = local_additional_vertices[0];
    surfmesh_refine->face[n].b = local_additional_vertices[1];
    surfmesh_refine->face[n].c = local_additional_vertices[2];

    // Then the three corner faces
    for (m = 0; m < 3; m++){
      surfmesh_refine->face[face_num].a = local_vertices[m];
      surfmesh_refine->face[face_num].b = local_additional_vertices[m];
      surfmesh_refine->face[face_num].c = local_additional_vertices[(m+2)%3];
      face_num++;
    }
  }

  // Release memory
  free(num_edges);
  free(offsets);
  free(vertex2edge);

  // Update number information
  surfmesh_refine->num_vertices += total_num_edges;
  surfmesh_refine->num_faces *= 4;
  
  // Release old data
  SurfaceMesh_releaseData(surfmesh);

  // Assign the refined mesh to the passed
  surfmesh->num_vertices = surfmesh_refine->num_vertices;
  surfmesh->num_faces = surfmesh_refine->num_faces;
  surfmesh->vertex = surfmesh_refine->vertex;
  surfmesh->face = surfmesh_refine->face;
  
  // Free memory of refined surface mesh struct
  free(surfmesh_refine);

  // Recreate the neigborlist
  SurfaceMesh_createNeighborlist(surfmesh);

}
示例#2
0
文件: GemMesh.C 项目: mcellteam/gamer
/*
FIXME: Are we using the neighbor list at all?
 */
GemMesh* GemMesh_fromTetgen(tetgenio& tetio)
{
  GemMesh *gem_mesh;
  unsigned int i, j, k;
  FILE *fout;
  long node_index;
  int *face_type, tetra_node[4];
  float x,y,z;
  int cell_type, boundary_face=0;
  float dist;
  long a,b,c,d;
  float ax,ay,az;
  float bx,by,bz;
  float cx,cy,cz;
  float dx,dy,dz;
  int active, exterior_cell_type;
  long neighbor, neightype;
  long *map_w_o,*map_w_i,*map_w_t; 
  Triface** tet_to_triface;
  int tet0, tet1, tet2;
  int *tetp;
  bool on_boundary[2];
  int* vertex_markers;
  Triface* triface;
  
  // Check for higher order cells
  const bool higher_order = tetio.numberofcorners==10;

  // Initialization and memory allocation
  gem_mesh = GemMesh_ctor(tetio.numberofpoints, tetio.numberoftetrahedra, higher_order);
  tet_to_triface = new Triface*[tetio.numberoftetrahedra];
  vertex_markers = new int[tetio.numberofpoints];

  for (i = 0; i < tetio.numberoftetrahedra; i++)
    tet_to_triface[i] = NULL;
  
  for (i = 0; i < tetio.numberofpoints; i++)
    vertex_markers[i] = 0;
  
  // Using the markers from the trifaces to mark vertices beeing on the boundary
  SurfaceMesh* boundary = SurfaceMesh_ctor(0, tetio.numberoftrifaces);
  for (i = 0; i < tetio.numberoftrifaces; i++)
  {
    tetp = &tetio.adjtetlist[i*2];
    on_boundary[0] = tetp[0] >= 0 && tetp[1] < 0;
    on_boundary[1] = tetp[1] >= 0 && tetp[0] < 0;
    
    // Iterate over the adjacent tets and register stored face information
    for (j=0; j<2; j++)
    {
      // If no tet continue
      if (tetp[j] < 0)
	continue;
      
      triface = new Triface;
      triface->next = NULL;
      triface->points[0] = tetio.trifacelist[i*3]-1;
      triface->points[1] = tetio.trifacelist[i*3+1]-1;
      triface->points[2] = tetio.trifacelist[i*3+2]-1;
      
      // If we are on a boundary face register it
      if (on_boundary[j])
      {
	boundary->face[boundary_face].a = triface->points[0];
	boundary->face[boundary_face].b = triface->points[1];
	boundary->face[boundary_face].c = triface->points[2];
	if (tetio.trifacemarkerlist != NULL)
	  boundary->face[boundary_face].m = tetio.trifacemarkerlist[i];
	else
	  boundary->face[boundary_face].m = 1;
	boundary_face++;
      }
      
      if (tetio.trifacemarkerlist != NULL)
	triface->marker = tetio.trifacemarkerlist[i];
      else
	triface->marker = 1;
      
      triface->next = tet_to_triface[tetp[j]-1];
      tet_to_triface[tetp[j]-1] = triface;
      
      vertex_markers[triface->points[0]] = triface->marker;
      vertex_markers[triface->points[1]] = triface->marker;
      vertex_markers[triface->points[2]] = triface->marker;
    }
  }
  
  // Store the actuall number of boundary faces
  boundary->num_faces = boundary_face;

  // Generate facetype information
  face_type = new int[tetio.numberoftetrahedra*4];

  for (i = 0; i < tetio.numberoftetrahedra; i++) {
    
    // Zero out all face types
    for (j = 0; j < 4; j++) 
      face_type[i*4+j] = 0;

    // Check tetra orientation
    a = tetio.tetrahedronlist[i * tetio.numberofcorners + 0] - 1;
    b = tetio.tetrahedronlist[i * tetio.numberofcorners + 1] - 1;
    c = tetio.tetrahedronlist[i * tetio.numberofcorners + 2] - 1;
    d = tetio.tetrahedronlist[i * tetio.numberofcorners + 3] - 1;
    ax = tetio.pointlist[a * 3];
    ay = tetio.pointlist[a * 3 + 1];
    az = tetio.pointlist[a * 3 + 2];
    bx = tetio.pointlist[b * 3];
    by = tetio.pointlist[b * 3 + 1];
    bz = tetio.pointlist[b * 3 + 2];
    cx = tetio.pointlist[c * 3];
    cy = tetio.pointlist[c * 3 + 1];
    cz = tetio.pointlist[c * 3 + 2];
    dx = tetio.pointlist[d * 3];
    dy = tetio.pointlist[d * 3 + 1];
    dz = tetio.pointlist[d * 3 + 2];
    bx -= ax;
    by -= ay;
    bz -= az;
    cx -= ax;
    cy -= ay;
    cz -= az;
    dx -= ax;
    dy -= ay;
    dz -= az;
    ax = by*cz-bz*cy;
    ay = bz*cx-bx*cz;
    az = bx*cy-by*cx;
    
    if (ax*dx+ay*dy+az*dz < 0 && !higher_order)
    {
      tetio.tetrahedronlist[i * 4 + 1] = c;
      tetio.tetrahedronlist[i * 4 + 2] = b;
      k = tetio.neighborlist[i * 4 + 1];
      tetio.neighborlist[i * 4 + 1] = tetio.neighborlist[i * 4 + 2];
      tetio.neighborlist[i * 4 + 2] = k;
    }

    // Check if we have a marked face
    while (tet_to_triface[i] != NULL)
    {

      // If so find out which face is on the boundary
      if (same_face(b, c, d, tet_to_triface[i]->points))
      {
	face_type[i*4] = tet_to_triface[i]->marker;
	triface = tet_to_triface[i];
	tet_to_triface[i] = triface->next;
	delete triface;
	continue;
      }

      if (same_face(a, c, d, tet_to_triface[i]->points))
      {
	face_type[i*4+1] = tet_to_triface[i]->marker;
	triface = tet_to_triface[i];
	tet_to_triface[i] = triface->next;
	delete triface;
	continue;
      }

      if (same_face(a, b, d, tet_to_triface[i]->points))
      {
	face_type[i*4+2] = tet_to_triface[i]->marker;
	triface = tet_to_triface[i];
	tet_to_triface[i] = triface->next;
	delete triface;
	continue;
      }

      if (same_face(a, b, c, tet_to_triface[i]->points))
      {
	face_type[i*4+3] = tet_to_triface[i]->marker;
	triface = tet_to_triface[i];
	tet_to_triface[i] = triface->next;
	delete triface;
	continue;
      }
    }
  }

  // Start output mesh
  gem_mesh->num_vertices = tetio.numberofpoints;
  gem_mesh->num_cells = tetio.numberoftetrahedra;

  // Write all nodes to a GemMesh structure
  for (i = 0; i < tetio.numberofpoints; i++)
  {
      gem_mesh->vv[i].id = i;
      gem_mesh->vv[i].chrt = vertex_markers[i]; // This might be ambigious
      gem_mesh->vv[i].x = tetio.pointlist[i * 3];
      gem_mesh->vv[i].y = tetio.pointlist[i * 3 + 1];
      gem_mesh->vv[i].z = tetio.pointlist[i * 3 + 2];
  }

  // Write all tets to a GemMesh structure
  for (i = 0; i < tetio.numberoftetrahedra; i++) 
  {
    gem_mesh->ss[i].id = i;
    gem_mesh->ss[i].grp = 0;
  
    if (tetio.numberoftetrahedronattributes > 0)
      gem_mesh->ss[i].mat = (int)tetio.tetrahedronattributelist[i*tetio.numberoftetrahedronattributes];
    else
      gem_mesh->ss[i].mat = 0;

    gem_mesh->ss[i].fa = face_type[4*i+0];
    gem_mesh->ss[i].fb = face_type[4*i+1];
    gem_mesh->ss[i].fc = face_type[4*i+2];
    gem_mesh->ss[i].fd = face_type[4*i+3];

    // NOTE: Index in tetrahedronlist starts from 1
    gem_mesh->ss[i].na = tetio.tetrahedronlist[i*tetio.numberofcorners+0] - 1;
    gem_mesh->ss[i].nb = tetio.tetrahedronlist[i*tetio.numberofcorners+1] - 1;
    gem_mesh->ss[i].nc = tetio.tetrahedronlist[i*tetio.numberofcorners+2] - 1;
    gem_mesh->ss[i].nd = tetio.tetrahedronlist[i*tetio.numberofcorners+3] - 1;

    // Add higher order cell info
    if (higher_order)
    {
      gem_mesh->hs[i].a = tetio.tetrahedronlist[i*tetio.numberofcorners+4] - 1;
      gem_mesh->hs[i].b = tetio.tetrahedronlist[i*tetio.numberofcorners+5] - 1;
      gem_mesh->hs[i].c = tetio.tetrahedronlist[i*tetio.numberofcorners+6] - 1;
      gem_mesh->hs[i].d = tetio.tetrahedronlist[i*tetio.numberofcorners+7] - 1;
      gem_mesh->hs[i].e = tetio.tetrahedronlist[i*tetio.numberofcorners+8] - 1;
      gem_mesh->hs[i].f = tetio.tetrahedronlist[i*tetio.numberofcorners+9] - 1;
    }
    
  }

  // Store boundary
  gem_mesh->boundary = boundary;

  // Release memory
  delete[] face_type;
  delete[] tet_to_triface;
  delete[] vertex_markers;

  return gem_mesh;
}
示例#3
0
SurfaceMesh* SurfaceMesh_marchingCube(int xdim, int ydim, int zdim, float* dataset, 
				      float isovalue, float* intensity, 
				      float intensity_isovalue, SPNT **holelist)
{
  int tempt_x, tempt_y, tempt_z;
  int i,j,k;
  int m,n,l;
  int number, ii, stack_size;
  float den1,den2,ratio;
  int v_num, t_num;
  FLTVECT *vertex;
  INT3VECT *triangle;
  int cellVerts[12]; 
  unsigned char cellIndex;      
  INT3VECT *mc_edge;
  unsigned char *mc_sign;
  SurfaceMesh *surfmesh;
  SPNT *hole_end, *hole_start;
  FLTVECT interior_seed;
  float max_density = -9999.0;
  bool use_intensity;

  // Check if we are using intensity values (neede for Lattice Data)
  use_intensity = intensity != NULL;

  // Initialize memory
  vertex = (FLTVECT*)malloc(sizeof(FLTVECT)*xdim*ydim*zdim);
  triangle = (INT3VECT*)malloc(sizeof(INT3VECT)*xdim*ydim*zdim);
  v_num = 0;
  t_num = 0;
  
  mc_edge = (INT3VECT*)malloc(sizeof(INT3VECT)*xdim*ydim*zdim);
  mc_sign = (unsigned char*)malloc(sizeof(unsigned char)*xdim*ydim*zdim);

  // preprocessing: removing small holes
  for (k=0; k<zdim; k++)
    for (j=0; j<ydim; j++) 
      for (i=0; i<xdim; i++) {
	if (dataset[IndexVect(i,j,k)] > max_density)
	  max_density = dataset[IndexVect(i,j,k)];
	mc_sign[IndexVect(i,j,k)] = 0;
      }

  triangle[0].a = 0;
  triangle[0].b = 0;
  triangle[0].c = 0;
  mc_sign[0] = 1;
  stack_size = 1;
  while (stack_size > 0) {
    stack_size--;
    tempt_x = triangle[stack_size].a;
    tempt_y = triangle[stack_size].b;
    tempt_z = triangle[stack_size].c;
    for (k=max(tempt_z-1,0); k<=min(tempt_z+1,zdim-1); k++) 
      for (j=max(tempt_y-1,0); j<=min(tempt_y+1,ydim-1); j++) 
	for (i=max(tempt_x-1,0); i<=min(tempt_x+1,xdim-1); i++) {
	  if (dataset[IndexVect(i,j,k)] < isovalue &&
	      mc_sign[IndexVect(i,j,k)] == 0) {
	    mc_sign[IndexVect(i,j,k)] = 1;
	    triangle[stack_size].a = i;
	    triangle[stack_size].b = j;
	    triangle[stack_size].c = k;
	    stack_size++;
	  }
	}
  }   
  hole_start = NULL;
  hole_end = NULL;
  den1 = 0;
  for (l=0; l<zdim; l++)
    for (n=0; n<ydim; n++) 
      for (m=0; m<xdim; m++) {
	if (dataset[IndexVect(m,n,l)] > den1) {
	  den1 = dataset[IndexVect(m,n,l)];
	  interior_seed.x = (float)m;
	  interior_seed.y = (float)n;
	  interior_seed.z = (float)l;
	}

	if (dataset[IndexVect(m,n,l)] < isovalue &&
	    mc_sign[IndexVect(m,n,l)] == 0) {
	  number = 1;
	  triangle[0].a = m;
	  triangle[0].b = n;
	  triangle[0].c = l;
	  mc_sign[0] = 1;
	  stack_size = 1;
	  while (stack_size > 0) {
	    stack_size--;
	    tempt_x = triangle[stack_size].a;
	    tempt_y = triangle[stack_size].b;
	    tempt_z = triangle[stack_size].c;
	    for (k=max(tempt_z-1,0); k<=min(tempt_z+1,zdim-1); k++) 
	      for (j=max(tempt_y-1,0); j<=min(tempt_y+1,ydim-1); j++) 
		for (i=max(tempt_x-1,0); i<=min(tempt_x+1,xdim-1); i++) {
		  if (dataset[IndexVect(i,j,k)] < isovalue &&
		      mc_sign[IndexVect(i,j,k)] == 0) {
		    mc_sign[IndexVect(i,j,k)] = 1;
		    triangle[stack_size].a = i;
		    triangle[stack_size].b = j;
		    triangle[stack_size].c = k;
		    stack_size++;
		    number++;
		  }
		}
	  }
	  printf("hole size: %d \n",number);
	  if (number < MIN_VOLUME) {
	    triangle[0].a = m;
	    triangle[0].b = n;
	    triangle[0].c = l;
	    dataset[IndexVect(m,n,l)] = max_density;
	    stack_size = 1;
	    while (stack_size > 0) {
	      stack_size--;
	      tempt_x = triangle[stack_size].a;
	      tempt_y = triangle[stack_size].b;
	      tempt_z = triangle[stack_size].c;
	      for (k=max(tempt_z-1,0); k<=min(tempt_z+1,zdim-1); k++) 
		for (j=max(tempt_y-1,0); j<=min(tempt_y+1,ydim-1); j++) 
		  for (i=max(tempt_x-1,0); i<=min(tempt_x+1,xdim-1); i++) {
		    if (dataset[IndexVect(i,j,k)] < isovalue) {
		      dataset[IndexVect(i,j,k)] = max_density;
		      triangle[stack_size].a = i;
		      triangle[stack_size].b = j;
		      triangle[stack_size].c = k;
		      stack_size++;
		    }
		  }
	    }
	  }
	  else {
	    /* could be improved here ?????*/ 
	    if (hole_start == NULL) {
	      hole_end = (SPNT*)malloc(sizeof(SPNT));
	      hole_start = hole_end;
	    }
	    else {
	      hole_end->next = (SPNT*)malloc(sizeof(SPNT));
	      hole_end = hole_end->next;
	    }
	    hole_end->x = (float)m;
	    hole_end->y = (float)n;
	    hole_end->z = (float)l;
	  }
	}
      }
  if (hole_end != NULL)
    hole_end->next = NULL;
  *holelist = hole_start;
  
  for (k=0; k<zdim; k++)
    for (j=0; j<ydim; j++) 
      for (i=0; i<xdim; i++) {
	if (dataset[IndexVect(i,j,k)] > isovalue-0.0001 &&
	    dataset[IndexVect(i,j,k)] < isovalue+0.0001)
	  dataset[IndexVect(i,j,k)] = isovalue+0.0001;
	
	mc_edge[IndexVect(i,j,k)].a = -1;
	mc_edge[IndexVect(i,j,k)].b = -1;
	mc_edge[IndexVect(i,j,k)].c = -1;
	if (dataset[IndexVect(i,j,k)] >= isovalue)
	  mc_sign[IndexVect(i,j,k)] = 1;
	else
	  mc_sign[IndexVect(i,j,k)] = 255;
      }	
  
  for (tempt_z=0; tempt_z<zdim-1; tempt_z++)
    for (tempt_y=0; tempt_y<ydim-1; tempt_y++) 
      for (tempt_x=0; tempt_x<xdim-1; tempt_x++) {
	
	for (ii = 0; ii < 12; ii++)
	  cellVerts[ii] = -1;
	
	cellIndex = 0;
	if (mc_sign[IndexVect(tempt_x,tempt_y,tempt_z)] == 255) cellIndex |= 1;
	if (mc_sign[IndexVect(tempt_x,tempt_y+1,tempt_z)] == 255) cellIndex |= 2;
	if (mc_sign[IndexVect(tempt_x+1,tempt_y+1,tempt_z)] == 255) cellIndex |= 4;
	if (mc_sign[IndexVect(tempt_x+1,tempt_y,tempt_z)] == 255) cellIndex |= 8;
	if (mc_sign[IndexVect(tempt_x,tempt_y,tempt_z+1)] == 255) cellIndex |= 16;
	if (mc_sign[IndexVect(tempt_x,tempt_y+1,tempt_z+1)] == 255) cellIndex |= 32;
	if (mc_sign[IndexVect(tempt_x+1,tempt_y+1,tempt_z+1)] == 255) cellIndex |= 64;
	if (mc_sign[IndexVect(tempt_x+1,tempt_y,tempt_z+1)] == 255) cellIndex |= 128;     
	
	if (edgeTable[cellIndex] & 1) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].b == -1) {  
	    
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x;
	    vertex[v_num].y = (float)tempt_y+ratio;
	    vertex[v_num].z = (float)tempt_z;
	    cellVerts[0] = v_num;
	    mc_edge[IndexVect(tempt_x,tempt_y,tempt_z)].b = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[0] = mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].b;
	}

	if (edgeTable[cellIndex] & 2) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].a == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+ratio;
	    vertex[v_num].y = (float)tempt_y+1;
	    vertex[v_num].z = (float)tempt_z;
	    cellVerts[1]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].a = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[1] = mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].a;
	}
	if (edgeTable[cellIndex] & 4) {
	  if (mc_edge[IndexVect(tempt_x+1,tempt_y,tempt_z)].b == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+1;
	    vertex[v_num].y = (float)tempt_y+ratio;
	    vertex[v_num].z = (float)tempt_z;
	    cellVerts[2] = v_num;
	    mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z)].b = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[2] = mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z)].b;
	}
	if (edgeTable[cellIndex] & 8) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].a == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+ratio;
	    vertex[v_num].y = (float)tempt_y;
	    vertex[v_num].z = (float)tempt_z;
	    cellVerts[3]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].a = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[3] = mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].a;
	}
	if (edgeTable[cellIndex] & 16) {
	  if (mc_edge[IndexVect(tempt_x,tempt_y,tempt_z+1)].b == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y, tempt_z+1)];
	      den2 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y, tempt_z+1)];
	      den2 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x;
	    vertex[v_num].y = (float)tempt_y+ratio;
	    vertex[v_num].z = (float)tempt_z+1;
	    cellVerts[4]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y, tempt_z+1)].b = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[4] = mc_edge[IndexVect(tempt_x, tempt_y, tempt_z+1)].b;
	}
	if (edgeTable[cellIndex] & 32) {
	  if (mc_edge[IndexVect(tempt_x,tempt_y+1,tempt_z+1)].a == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+ratio;
	    vertex[v_num].y = (float)tempt_y+1;
	    vertex[v_num].z = (float)tempt_z+1;
	    cellVerts[5]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z+1)].a = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[5] = mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z+1)].a;
	}
	if (edgeTable[cellIndex] & 64) {
	  if (mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z+1)].b == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+1;
	    vertex[v_num].y = (float)tempt_y+ratio;
	    vertex[v_num].z = (float)tempt_z+1;
	    cellVerts[6]  = v_num;
	    mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z+1)].b = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[6] = mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z+1)].b;
	}
	if (edgeTable[cellIndex] & 128) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y, tempt_z+1)].a == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y, tempt_z+1)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y, tempt_z+1)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+ratio;
	    vertex[v_num].y = (float)tempt_y;
	    vertex[v_num].z = (float)tempt_z+1;
	    cellVerts[7]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y, tempt_z+1)].a = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[7] = mc_edge[IndexVect(tempt_x, tempt_y, tempt_z+1)].a;
	}
	if (edgeTable[cellIndex] & 256) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].c == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x, tempt_y, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x, tempt_y, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x;
	    vertex[v_num].y = (float)tempt_y;
	    vertex[v_num].z = (float)tempt_z+ratio;
	    cellVerts[8]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y, tempt_z)].c = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[8] = mc_edge[IndexVect(tempt_x,tempt_y,tempt_z)].c;
	}
	if (edgeTable[cellIndex] & 512) {
	  if (mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].c == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x, tempt_y+1, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x;
	    vertex[v_num].y = (float)tempt_y+1;
	    vertex[v_num].z = (float)tempt_z+ratio;
	    cellVerts[9]  = v_num;
	    mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].c = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[9] = mc_edge[IndexVect(tempt_x, tempt_y+1, tempt_z)].c;
	}
	if (edgeTable[cellIndex] & 1024) {
	  if (mc_edge[IndexVect(tempt_x+1, tempt_y+1, tempt_z)].c == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y+1, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+1;
	    vertex[v_num].y = (float)tempt_y+1;
	    vertex[v_num].z = (float)tempt_z+ratio;
	    cellVerts[10]  = v_num;
	    mc_edge[IndexVect(tempt_x+1, tempt_y+1, tempt_z)].c = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[10] = mc_edge[IndexVect(tempt_x+1, tempt_y+1, tempt_z)].c;
	}
	if (edgeTable[cellIndex] & 2048) {
	  if (mc_edge[IndexVect(tempt_x+1,tempt_y,tempt_z)].c == -1) {  
	    if(use_intensity)
	    {
	      den1 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z)];
	      den2 = intensity[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];

	      ratio = get_intensity_ratio(den1, den2, intensity_isovalue);
  	    }
	    else
	    {
	      den1 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z)];
	      den2 = dataset[IndexVect(tempt_x+1, tempt_y, tempt_z+1)];
	      if (den1 != den2)
		ratio = (isovalue-den1)/(den2-den1);
	      else 
		ratio = 0;
	    }
	    vertex[v_num].x = (float)tempt_x+1;
	    vertex[v_num].y = (float)tempt_y;
	    vertex[v_num].z = (float)tempt_z+ratio;
	    cellVerts[11]  = v_num;
	    mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z)].c = v_num;
	    v_num++;
	  }
	  else 
	    cellVerts[11] = mc_edge[IndexVect(tempt_x+1, tempt_y, tempt_z)].c;
	}
	
	ii = 0;
	while (triTable[cellIndex][ii] != -1) {
	  triangle[t_num].a = cellVerts[triTable[cellIndex][ii++]];
	  triangle[t_num].b = cellVerts[triTable[cellIndex][ii++]];
	  triangle[t_num].c = cellVerts[triTable[cellIndex][ii++]];
	  t_num++;
	}
      }

  // Allocate memory
  surfmesh = SurfaceMesh_ctor(v_num, t_num);
  
  for (n = 0; n < surfmesh->nv; n++) {
    surfmesh->vertex[n].x = vertex[n].x;
    surfmesh->vertex[n].y = vertex[n].y;
    surfmesh->vertex[n].z = vertex[n].z;
  }
  for (n = 0; n < surfmesh->nf; n++) {
    surfmesh->face[n].a = triangle[n].a;
    surfmesh->face[n].b = triangle[n].b;
    surfmesh->face[n].c = triangle[n].c;
  }
  
  free(vertex);
  free(triangle);
  free(mc_edge);
  free(mc_sign);

  // Return created SurfaceMesh
  return surfmesh;
  
}