Пример #1
0
  int MESH_BuildFaceClassfn(Mesh_ptr mesh, int use_geometry) {
  int i, j, k, idx, idx2, fnd, gfid, gfid2, gdim;
  int ngfaces, ngfalloc, grid0, grid1;
  int max_gface_id, processedmk, submk;
  int nfe, nef, nbf, nfr, nsub, *gfids, (*gfregids)[2];
  double PI=3.141592, ang, COSSHARPANG;
  MEdge_ptr edge;
  MFace_ptr face, subface, adjface;
  MRegion_ptr freg0, freg1;
  List_ptr fregs, fedges, efaces, ebfaces, gffaces, subfaces;

  COSSHARPANG = cos(9*PI/12);  /* 135 degrees */


  /* Verify that mesh faces on the boundary have classification
     information; if not, assign all faces to the same model faces */

  ngfaces = 0; ngfalloc = 10;
  gfids = (int *) malloc(ngfalloc*sizeof(int));
  gfregids = (int (*)[2]) malloc(ngfalloc*sizeof(int [2]));


  /* Take stock of existing model face information */

  max_gface_id = 0;
  idx = 0;
  while ((face = MESH_Next_Face(mesh,&idx))) {
    gdim = MF_GEntDim(face);
    if (gdim != 2)
      continue;

    gfid = MF_GEntID(face);
    if (gfid) {

      /* Has this model face been encountered? If not, add it to list
	 of model faces */

      for (i = 0, fnd = 0; i < ngfaces; i++)
	if (gfids[i] == gfid) {
	  fnd = 1;
	  break;
	}

      if (!fnd) {
	if (gfid > max_gface_id)
	  max_gface_id = gfid;

	if (ngfalloc == ngfaces) {
	  ngfalloc *= 2;
	  gfids = (int *) realloc(gfids,ngfalloc*sizeof(int));
	  gfregids = (int (*)[2])realloc(gfregids,ngfalloc*sizeof(int [2]));
	}

	gfids[ngfaces] = gfid;
	gfregids[ngfaces][0] = gfregids[ngfaces][1] = 0;
	fregs = MF_Regions(face);
	if (fregs) {
	  nfr = List_Num_Entries(fregs);
      
	  freg0 = List_Entry(fregs,0);
	  gfregids[ngfaces][0] = MR_GEntID(freg0); /* NOTE 1 (see EOF) */
      
	  if (nfr == 2) {
	    freg1 = List_Entry(fregs,1); 
	    gfregids[ngfaces][1] = MR_GEntID(freg1);
	  }	  
	  
	  List_Delete(fregs);
	}

	ngfaces++;
      }

    }
  }


  /* Build new model face information based on adjacent model region info */

  idx = 0;
  while ((face = MESH_Next_Face(mesh,&idx))) {
    
    gdim = MF_GEntDim(face);
    gfid = MF_GEntID(face);

    /* Face has no classification? Assign classification info */
    /* Face classified as interior face? Verify */
    
    freg0 = freg1 = NULL;
    grid0 = grid1 = 0;
    fregs = MF_Regions(face);
    if (fregs) {
      nfr = List_Num_Entries(fregs);
      
      freg0 = List_Entry(fregs,0);
      grid0 = MR_GEntID(freg0);
      
      if (nfr == 2) {
	freg1 = List_Entry(fregs,1); 
	grid1 = MR_GEntID(freg1);
      }
      
      List_Delete(fregs);
    }
    else
      nfr = 0;
    
    if (nfr == 2 && (grid0 == grid1)) {
      /* Interior face */
      
      MF_Set_GEntDim(face,3);
      MF_Set_GEntID(face,grid0);
    }
    else {
      /* Boundary face */
      
      if (gdim > 2 || (gdim == 2 && gfid <= 0)) { 
	MF_Set_GEntDim(face,2);

	/* Check if this type of face with these adjacent regions has
	   been encountered before; if it has, we just use the
	   existing model face id */

	for (i = 0, fnd = 0; i < ngfaces; i++)
	  if ((gfregids[i][0] == grid0 && gfregids[i][1] == grid1) ||
	      (gfregids[i][0] == grid1 && gfregids[i][1] == grid0)) {
	    fnd = 1;
	    break;
	  }

	if (fnd)
	  MF_Set_GEntID(face,gfids[i]);
	else {
	  max_gface_id++;
	  MF_Set_GEntID(face,max_gface_id);

	  if (ngfalloc == ngfaces) {
	    ngfalloc *= 2;
	    gfids = (int *) realloc(gfids,ngfalloc*sizeof(int));
	    gfregids = (int (*)[2]) realloc(gfregids,ngfalloc*sizeof(int [2]));
	  }

	  gfids[ngfaces] = max_gface_id;
	  gfregids[ngfaces][0] = grid0;
	  gfregids[ngfaces][1] = grid1;
	  ngfaces++;
	}
      }
    }
  }

  if (use_geometry == 1) {

    /* Now assign model face IDs based on whether a sharp set of edges
       enclose a set of faces */

    for (i = 0; i < ngfaces; i++) {

      /* Find all mesh faces with this model face id */

      gffaces = List_New(10);
      idx = 0; 
      while ((face = MESH_Next_Face(mesh,&idx))) {
        if (MF_GEntDim(face) == 2 && MF_GEntID(face) == gfids[i])
          List_Add(gffaces,face);
      }

      /* Process faces of this list and subdivide them into subfaces */
      /* The way we do that is 
       
         1) we put an unprocessed face from the original list in a subface
         list

         2) we then add its neighboring faces to subface list if they are
         of the same color (same model face id) and do not have a sharp
         edge separating them from the current face

         3) we then process the next face in the subface list 

         4) we are done if we cannot find any more neighbors of faces in
         the subface list to add to the subface list

         5) we then repeat steps 1 through 4 until we are left with no
         more faces to process from the original list
       
      */

      processedmk = MSTK_GetMarker();

      nsub = 0;
      idx = 0;
      while ((face = List_Next_Entry(gffaces,&idx))) {
        if (MEnt_IsMarked(face,processedmk))
          continue;

        /* Found a face in gffaces that has not been processed */
        MEnt_Mark(face,processedmk);

        submk = MSTK_GetMarker();
        subfaces = List_New(10);
        List_Add(subfaces,face);
        MEnt_Mark(face,submk);

        idx2 = 0;
        while ((subface = List_Next_Entry(subfaces,&idx2))) {
          gfid = MF_GEntID(subface);

          fedges = MF_Edges(subface,1,0);
          nfe = List_Num_Entries(fedges);

          for (j = 0; j < nfe; j++) {
            edge = List_Entry(fedges,j);
            efaces = ME_Faces(edge);
            nef = List_Num_Entries(efaces);

            ebfaces = List_New(nef); /* list of boundary faces cnctd 2 edge */
            for (k = 0; k < nef; k++) {
              adjface = List_Entry(efaces,k);
              if (MF_GEntDim(adjface) == 2)
                List_Add(ebfaces,adjface);
            }
            List_Delete(efaces);

            nbf = List_Num_Entries(ebfaces);
            if (nbf == 2) {
              /* we might be on a model face or on a model edge */
            
              adjface = List_Entry(ebfaces,0);
              if (adjface == subface)
                adjface = List_Entry(ebfaces,1);
              gfid2 = MF_GEntID(adjface);

            
              if (gfid == gfid2) {
                /* The two faces are of the same ID. If the angle
                   between them is not sharp they can be classified as
                   being on the same subface */
	      
                ang = MFs_DihedralAngle(subface,adjface,edge);
              
                if (ang <= COSSHARPANG) {
                  /* Add face2 to subface list unless its already there */
                  if (!MEnt_IsMarked(adjface,submk)) {
                    List_Add(subfaces,adjface);
                    MEnt_Mark(adjface,submk);
                  }
                }
                else {
                  /* The two faces make a very sharp angle. We will
                     consider the edge b/w them to be a model edge */
                  /* Tag the edge as being on a model edge (we don't
                     know the model edge ID as yet) and continue */
                
                  ME_Set_GEntDim(edge,1);
                  ME_Set_GEntID(edge,0);
                }
              }
              else {
                /* we reached a model edge */
                /* Tag the edge as being on a model edge (we don't know
                   the model edge ID as yet) and continue */

                ME_Set_GEntDim(edge,1);
                ME_Set_GEntID(edge,0);
              }
            }
            else {
              /* we reached a a model edge */
              /* Tag the edge as being on a model edge (we don't know
                 the model edge ID as yet) and continue */

              ME_Set_GEntDim(edge,1);
              ME_Set_GEntID(edge,0);
            }
            List_Delete(ebfaces);
          }

          /* Finished processing all neighbors of the face */
          List_Delete(fedges);
        }

        /* Now we have a list of faces which we believe constitutes a
           model face by itself. If this is the first subface (which
           means it could also be the entire model face originally
           considered), leave the model face tag as it is. If not,
           assign the faces in the subface a new model face ID */

        if (nsub != 0) {
          max_gface_id++;
          idx2 = 0;
          while ((subface = List_Next_Entry(subfaces,&idx2))) 
            MF_Set_GEntID(subface,max_gface_id);
        }
        nsub++;

        /* Done with this subface */

        idx2 = 0;
        while ((subface = List_Next_Entry(subfaces,&idx2))) {
          MEnt_Mark(subface,processedmk);
          MEnt_Unmark(subface,submk);
        }
        MSTK_FreeMarker(submk);
        List_Delete(subfaces);
      }

      List_Unmark(gffaces,processedmk);
      MSTK_FreeMarker(processedmk);
      List_Delete(gffaces);
    }
  
  } /* if use_geometry == 1 */

  free(gfids);
  free(gfregids);
       
  return 1;
}
Пример #2
0
  int MESH_ConcatSubMesh_Face(Mesh_ptr mesh, int num, Mesh_ptr *submeshes) {
    int nfv, nfe, i, j, k, ival;
    MVertex_ptr mv, new_mv, sub_mv;
    MEdge_ptr me, new_me, sub_me;
    MFace_ptr new_mf, sub_mf;
    List_ptr mfverts, mfedges;
    int add_face, idx, global_id, iloc, *loc;
    double coor[3], rval;
    void *pval;
    Mesh_ptr submesh;

    List_ptr parbndry_verts = List_New(10);
    List_ptr parbndry_edges = List_New(10);

    MEdge_ptr *fedges = (MEdge_ptr *) malloc(MAXPV2*sizeof(MEdge_ptr));
    int *fedirs = (int *) malloc(MAXPV2*sizeof(int));

    MAttrib_ptr parbndryatt = MAttrib_New(mesh, "on_parbndry", INT, MVERTEX);
    
    /* collect edges and vertices on the partition boundary */
    int num_parbndry_edges = 0;
    idx = 0;
    while ((me = MESH_Next_Edge(mesh,&idx))) 
      if (ME_PType(me) != PINTERIOR) {
        List_Add(parbndry_edges,me);
        num_parbndry_edges++;
      }
    int num_parbndry_verts = 0;
    idx = 0;
    while ((mv = MESH_Next_Vertex(mesh,&idx)))
      if (MV_PType(mv) != PINTERIOR) {
        List_Add(parbndry_verts,mv);
        MEnt_Set_AttVal(mv, parbndryatt, 1, 0.0, NULL);
        num_parbndry_verts++;
      }
    /* sort based on global ID */
    List_Sort(parbndry_edges,num_parbndry_edges,sizeof(MEdge_ptr),compareGlobalID);
    List_Sort(parbndry_verts,num_parbndry_verts,sizeof(MVertex_ptr),compareGlobalID);

    int *parbndry_vert_gids = (int *) malloc(num_parbndry_verts*sizeof(int));
    int *parbndry_edge_gids = (int *) malloc(num_parbndry_edges*sizeof(int));

    /* store them in array for binary search */
    for (i = 0; i < num_parbndry_edges; i++) {
      me = List_Entry(parbndry_edges,i);
      parbndry_edge_gids[i] = ME_GlobalID(me);
    }
    for (i = 0; i < num_parbndry_verts; i++) {
      mv = List_Entry(parbndry_verts,i);
      parbndry_vert_gids[i] = MV_GlobalID(mv);
    }

    
    /* Make list of new edges and vertices which will be updated
       with each mesh that is concatenated */
    int max_vnew = 0, max_enew = 0;
    for (i = 0; i < num; i++) {
      max_vnew += MESH_Num_Vertices(submeshes[i]);
      max_enew += MESH_Num_Edges(submeshes[i]);
    }

    int num_new_verts = 0, num_new_edges = 0; 
    int *new_vert_gids = (int *) malloc(max_vnew*sizeof(int));
    int *new_edge_gids = (int *) malloc(max_enew*sizeof(int));

    List_ptr new_verts = List_New(max_vnew);
    List_ptr new_edges = List_New(max_enew);


    /* Now process each mesh and add a layer of ghost elements from
       each of them to the main partition */
    
    for (i = 0; i < num; i++) {
      submesh = submeshes[i];
    
      MAttrib_ptr vidatt = MAttrib_New(submesh, "tempvid", POINTER, MVERTEX);
      MAttrib_ptr eidatt = MAttrib_New(submesh, "tempeid", POINTER, MEDGE);

      idx = 0;
      while ((sub_mf = MESH_Next_Face(submesh, &idx))) {
        add_face = 0;
      
        /* Find matching vertices between the submesh and main mesh */
      
        mfverts = MF_Vertices(sub_mf,1,0);
        nfv = List_Num_Entries(mfverts);
        for (j = 0; j < nfv; j++) {
          sub_mv = List_Entry(mfverts,j);
        
          /* Does the vertex have a known counterpart on the partition
           * boundary of the main mesh? */
          MEnt_Get_AttVal(sub_mv, vidatt, &ival, &rval, &mv);

          if (mv) {
            int on_parbndry=0;
            MEnt_Get_AttVal(mv, parbndryatt, &on_parbndry, &rval, &pval);
            if (on_parbndry)
              add_face = 1; 
          } else {
        
            /* Does the global ID of this vertex of the sub mesh face
             * match the global ID of a partition boundary vertex in
             * the main mesh? */
            
            global_id = MV_GlobalID(sub_mv);
            loc = (int *) bsearch(&global_id, parbndry_vert_gids, num_parbndry_verts, sizeof(int),
                                  compareINT);
            if (loc) {  /* found a match */
              add_face = 1; 
              iloc = loc - parbndry_vert_gids;
              mv = List_Entry(parbndry_verts,iloc); 
              /* here set the ghost vertex property, only necessary when the input submeshes are not consistent */
              if (MV_PType(mv) == PGHOST && MV_PType(sub_mv) != PGHOST) {
                MV_Set_GEntDim(mv,MV_GEntDim(sub_mv));
                MV_Set_GEntID(mv,MV_GEntID(sub_mv));
              }
              
              MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, mv);
            }
          }
        }
        List_Delete(mfverts);
      
        /* Find matching edges between the submesh and main mesh */
      
        mfedges = MF_Edges(sub_mf,1,0);
        nfe = List_Num_Entries(mfedges);
        for (j = 0; j < nfe; j++) {
          sub_me = List_Entry(mfedges,j);

          /* Does the edge have a known counterpart on the partition
           * boundary of the main mesh */
          MEnt_Get_AttVal(sub_me, eidatt, &ival, &rval, &me);

          if (!me) {
            /* Does the global ID of this edge of the sub mesh face
             * match the global ID of a partition boundary edge in the
             * main mesh? */
            
            global_id = ME_GlobalID(sub_me);
            loc = (int *) bsearch(&global_id, parbndry_edge_gids, num_parbndry_edges, sizeof(int),
                                  compareINT);
            if (loc) {
              iloc = loc - parbndry_edge_gids;
              me = List_Entry(parbndry_edges,iloc); 
              /* here set the ghost edge property, only necessary when the input submeshes are not consistent */
              if (ME_PType(me) == PGHOST && ME_PType(sub_me) != PGHOST) {
                ME_Set_GEntDim(me,ME_GEntDim(sub_me));
                ME_Set_GEntID(me,ME_GEntID(sub_me));
              }
              
	      MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, me);
            }
          }
        }
        
        if (!add_face) {
          List_Delete(mfedges);
          continue;
        }

        new_mf = MF_New(mesh); /* add face */
        MF_Set_GEntDim(new_mf,MF_GEntDim(sub_mf));
        MF_Set_GEntID(new_mf,MF_GEntID(sub_mf));
        MF_Set_PType(new_mf,PGHOST);
        MF_Set_MasterParID(new_mf,MF_MasterParID(sub_mf));
        MF_Set_GlobalID(new_mf,MF_GlobalID(sub_mf));
      
        nfe = List_Num_Entries(mfedges);
        for (j = 0; j < nfe; j++) {
          sub_me = List_Entry(mfedges,j);
          global_id = ME_GlobalID(sub_me);
          fedirs[j] = MF_EdgeDir_i(sub_mf,j) == 1 ? 1 : 0;

          new_me = NULL;	  
	  MEnt_Get_AttVal(sub_me, eidatt, &ival, &rval, &new_me);

          if (!new_me) {
            /* search in the ghost layer if another edge with
             * this global ID has been added */
            loc = (int *) bsearch(&global_id, new_edge_gids, num_new_edges,
                                  sizeof(int), compareINT);
            if (loc) {
              iloc = loc - new_edge_gids;
              new_me = List_Entry(new_edges, iloc);
              MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, new_me);
            }
          }

          if (new_me) {
            if (MV_GlobalID(ME_Vertex(new_me,0)) != MV_GlobalID(ME_Vertex(sub_me,0)))
              fedirs[j] = 1 - fedirs[j];  /* if the edge dir is not the same, reverse the edge dir */
          } else  {  /* add a new edge to main mesh */
            
            new_me = ME_New(mesh);
            ME_Set_GEntDim(new_me,ME_GEntDim(sub_me));
            ME_Set_GEntID(new_me,ME_GEntID(sub_me));
            ME_Set_PType(new_me,PGHOST);
            ME_Set_MasterParID(new_me,ME_MasterParID(sub_me));
            ME_Set_GlobalID(new_me,ME_GlobalID(sub_me));
	  
            MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, new_me);
	    List_Add(new_edges, new_me);
          
            for (k = 0; k < 2; k++) {
              sub_mv = ME_Vertex(sub_me,k);
              global_id = MV_GlobalID(sub_mv);

              new_mv = NULL;
              MEnt_Get_AttVal(sub_mv, vidatt, &ival, &rval, &new_mv);
	      if (!new_mv) {
		/* search in the ghost layer if another vertex with
                 * this global ID has been added */
                loc = (int *) bsearch(&global_id, new_vert_gids, num_new_verts,
                                      sizeof(int), compareINT);
                if (loc) {
                  iloc = loc - new_vert_gids;
                  new_mv = List_Entry(new_verts, iloc);
                  MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, new_mv);
                }
              }

              if (!new_mv) {  /* add a new vertex to main mesh */
                new_mv = MV_New(mesh);
                MV_Set_GEntDim(new_mv,MV_GEntDim(sub_mv));
                MV_Set_GEntID(new_mv,MV_GEntID(sub_mv));
                MV_Set_PType(new_mv,PGHOST);
                MV_Set_MasterParID(new_mv,MV_MasterParID(sub_mv));
                MV_Set_GlobalID(new_mv,MV_GlobalID(sub_mv));
                MV_Coords(sub_mv,coor);
                MV_Set_Coords(new_mv,coor);
	      
                MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, new_mv);
		List_Add(new_verts, new_mv);
              }
              ME_Set_Vertex(new_me,k,new_mv);  /* set edge-vertex */
            }
          }								
          fedges[j] = new_me;
        }
        MF_Set_Edges(new_mf,nfe,fedges,fedirs); /* set face-edge */

        List_Delete(mfedges);
      }

      idx = 0;
      while ((sub_mv = MESH_Next_Vertex(submesh, &idx)))
	MEnt_Rem_AttVal(sub_mv, vidatt);
      MAttrib_Delete(vidatt);
      idx = 0;
      while ((sub_me = MESH_Next_Edge(submesh, &idx)))
	MEnt_Rem_AttVal(sub_me, eidatt);
      MAttrib_Delete(eidatt);

      /* Sort the added entity lists by GlobalID */
      num_new_edges = List_Num_Entries(new_edges);
      List_Sort(new_edges, num_new_edges, sizeof(MEdge_ptr), compareGlobalID);
      for (j = 0; j < num_new_edges; j++)
        new_edge_gids[j] = ME_GlobalID(List_Entry(new_edges, j));

      num_new_verts = List_Num_Entries(new_verts);
      List_Sort(new_verts, num_new_verts, sizeof(MVertex_ptr), compareGlobalID);
      for (j = 0; j < num_new_verts; j++)
        new_vert_gids[j] = MV_GlobalID(List_Entry(new_verts, j));
    }

    idx = 0;
    while ((mv = List_Next_Entry(parbndry_verts, &idx)))
      MEnt_Rem_AttVal(mv, parbndryatt);
    MAttrib_Delete(parbndryatt);
    
    List_Delete(parbndry_edges);
    List_Delete(parbndry_verts);
    List_Delete(new_edges);
    List_Delete(new_verts);

    free(parbndry_vert_gids);
    free(parbndry_edge_gids);
    free(new_vert_gids);
    free(new_edge_gids);

    free(fedges);
    free(fedirs);

    return 1;
  }
Пример #3
0
MFace_ptr MR_Split_with_EdgeLoop(MRegion_ptr rsplit, int nfe, MEdge_ptr *fedges) {
  Mesh_ptr mesh;
  int i, j, idx1, idx2, fedirs[MAXPV2], rfdir_adj, curdir, edir, edir_adj;;
  int gid, mkid, nrf1, nrf2, rfdirs1[MAXPF3], rfdirs2[MAXPF3];
  MEdge_ptr fe;
  MFace_ptr fnew, eface, rfarray1[MAXPF3], rfarray2[MAXPF3], curface;
  MRegion_ptr rnew[2];
  List_ptr felist, efaces;

#ifdef DEBUG
  List_ptr redges;
#endif

  gid = MR_GEntID(rsplit);

#ifdef DEBUG
  /* check to make sure we got meaningful input */
  redges = MR_Edges(rsplit);
  for (i = 0; i < nfe; i++)
    if (!List_Contains(redges,fedges[i]))
      MSTK_Report("MR_Split","Input edges are not part of the region boundary",
                  MSTK_FATAL);
  List_Delete(redges);
#endif

  mesh = MR_Mesh(rsplit);


  /* Fix a set of directions for the edges */

  fedirs[0] = 1;
  for (i = 1; i < nfe; i++) {
    MVertex_ptr vprev, v0, v1;

    vprev = ME_Vertex(fedges[i-1],fedirs[i-1]);
    v0 = ME_Vertex(fedges[i],0);
    v1 = ME_Vertex(fedges[i],1);
    if (vprev == v0)
      fedirs[i] = 1;
    else if (vprev == v1)
      fedirs[i] = 0;
    else
      MSTK_Report("MR_Split","Input edges do not form a loop as listed",
                  MSTK_FATAL);
  }

  /* Create the splitting face */

  fnew = MF_New(mesh);
  MF_Set_GEntDim(fnew,3);
  MF_Set_GEntID(fnew,gid);
  MF_Set_Edges(fnew,nfe,fedges,fedirs);


  /* Collect info for the first region */

  List_ptr processed_faces = List_New(0);

  rfarray1[0] = fnew;
  rfdirs1[0] = 1; 
  nrf1 = 1;
  List_Add(processed_faces,rfarray1[0]);

  i = 0;
  while (i < nrf1) {
    curface = rfarray1[i];
    curdir = rfdirs1[i];
    i++;

    /* Get adjacent faces in region of current face and if they are
       not already in the new region face list (not marked), then add
       them */
 
    felist = MF_Edges(curface,1,0);
    idx1 = 0; j = 0;
    while ((fe = List_Next_Entry(felist,&idx1))) {
      edir = MF_EdgeDir_i(curface,j);      
      j++;

      efaces = ME_Faces(fe);
      if (curface != fnew && List_Contains(efaces,fnew)) {
        /* we have come back to the starting or splitting face - don't
           go across this edge */
        List_Delete(efaces);
        continue;
      }

      /* Add an adjacent unprocessed face of the region to the list of 
       faces for the new region */
      idx2 = 0; 
      while ((eface = List_Next_Entry(efaces,&idx2))) { 
        if (eface == curface) continue;
        if (List_Contains(processed_faces,eface)) continue;
        if (!MR_UsesEntity(rsplit,eface,MFACE)) continue; /* does not belong to region */

        edir_adj = MF_EdgeDir(eface,fe);
        rfdir_adj = MR_FaceDir(rsplit,eface);

        /* add adjacent face based on the check that if two adjacent faces of
           region are used by the region in the same sense, then their common
           edge should be used by the two faces in opposite senses (or the opposite
           of both the conditions should be true) */

        if ((edir != edir_adj && curdir == rfdir_adj) ||
            (edir == edir_adj && curdir != rfdir_adj)) {
          rfarray1[nrf1] = eface;
          rfdirs1[nrf1] = rfdir_adj;
          List_Add(processed_faces,rfarray1[nrf1]);
          nrf1++;
          break;
        }
      }
      List_Delete(efaces);
    }
    List_Delete(felist);
  }


  /* collect info for the second region */

  rfarray2[0] = fnew;
  rfdirs2[0] = !rfdirs1[0];
  nrf2 = 1;
  List_Add(processed_faces,rfarray2[0]);
  
  i = 0;
  while (i < nrf2) {
    curface = rfarray2[i];
    curdir = rfdirs2[i];
    i++;

    /* Get adjacent faces in region of current face and if they are
       not already in the new region face list (not marked), then add
       them */
 
    felist = MF_Edges(curface,1,0);
    idx1 = 0; j = 0;
    while ((fe = List_Next_Entry(felist,&idx1))) {
      edir = MF_EdgeDir_i(curface,j);      
      j++;

      efaces = ME_Faces(fe);
      if (curface != fnew && List_Contains(efaces,fnew)) {
        /* we have come back to the starting or splitting face - don't
           go across this edge */
        List_Delete(efaces);
        continue;
      }

      
      /* Add an adjacent unprocessed face of the region to the list of 
       faces for the new region */
      idx2 = 0; 
      while ((eface = List_Next_Entry(efaces,&idx2))) { 
        if (eface == curface) continue;
        if (List_Contains(processed_faces,eface)) continue;
        if (!MR_UsesEntity(rsplit,eface,MFACE)) continue; /* does not belong to region */

        edir_adj = MF_EdgeDir(eface,fe);
        rfdir_adj = MR_FaceDir(rsplit,eface);

        /* add adjacent face based on the check that if two adjacent faces of
           region are used by the region in the same sense, then their common
           edge should be used by the two faces in opposite senses (or the opposite
           of both the conditions should be true) */

        if ((edir != edir_adj && curdir == rfdir_adj) ||
            (edir == edir_adj && curdir != rfdir_adj)) {
          rfarray2[nrf2] = eface;
          rfdirs2[nrf2] = rfdir_adj;
          List_Add(processed_faces,rfarray2[nrf2]);
          nrf2++;
          break;
        }
      }
      List_Delete(efaces);
    }
    List_Delete(felist);
  }

  /* Delete the original region */

  MR_Delete(rsplit,0);

  /* Make the two new regions */

  rnew[0] = MR_New(mesh);
  MR_Set_GEntDim(rnew[0],3);
  MR_Set_GEntID(rnew[0],gid);
  MR_Set_Faces(rnew[0],nrf1,rfarray1,rfdirs1);

  rnew[1] = MR_New(mesh);
  MR_Set_GEntDim(rnew[1],3);
  MR_Set_GEntID(rnew[1],gid);
  MR_Set_Faces(rnew[1],nrf2,rfarray2,rfdirs2);

  List_Delete(processed_faces);

  return fnew;
}
Пример #4
0
MVertex_ptr ME_Split_SimplexMesh(MEdge_ptr esplit, double *splitxyz) {
  int i, j, k, rfdir, ntets=0, ntris=0, *fdim, *fid, *rid=NULL, found;
  MVertex_ptr vsplit, ev[2], (*tetverts)[4]=NULL, (*triverts)[3]=NULL, fv;
  MVertex_ptr fvarr[3], rvarr[4];
  MFace_ptr f;
  MRegion_ptr r;
  List_ptr etets, rfaces, etris, fverts;
  Mesh_ptr mesh = ME_Mesh(esplit);

  ev[0] = ME_Vertex(esplit,0);
  ev[1] = ME_Vertex(esplit,1);

  etets = ME_Regions(esplit);
  if (etets) {
    ntets = List_Num_Entries(etets);   
    tetverts = (MVertex_ptr (*)[4]) malloc(ntets*sizeof(MVertex_ptr [4]));
    rid = (int *) malloc(ntets*sizeof(int));
  }

  for (i = 0; i < ntets; i++) {

    r = List_Entry(etets,i);

    rfaces = MR_Faces(r);

    /* Find a tet face that uses ev[0] but not ev[1] */

    found = 0;
    for (j = 0; !found && j < 4; j++) {
      f = List_Entry(rfaces,j);

      fverts = MF_Vertices(f,1,0);
      if (List_Contains(fverts,ev[0]) &&
          !List_Contains(fverts,ev[1])) {

        found = 1;
        
        /* Get the two vertices (a,b) of this face excluding ev[0] in
           such an order that ev[0],a,b,ev[1] will form a valid
           tet. This requires checking whether the face points into or
           out of this tet (look at rfdir) */

        rfdir = MR_FaceDir_i(r,j);
        for (k = 0; k < 3; k++) {
          fv = List_Entry(fverts,k);
          if (fv == ev[0]) {
            tetverts[i][0] = ev[0];
            tetverts[i][1] = rfdir ? List_Entry(fverts,(k+2)%3) : List_Entry(fverts,(k+1)%3);
            tetverts[i][2] = rfdir ? List_Entry(fverts,(k+1)%3) : List_Entry(fverts,(k+2)%3);
            tetverts[i][3] = ev[1];
          }
        }
      }
      List_Delete(fverts);

      if (found) break;
    }

    List_Delete(rfaces);
  }

  /* Now that we finished collecting info about the connected tets we
     can delete them */

  if (etets) {
    for (i = 0; i < ntets; i++)
      MR_Delete(List_Entry(etets,i),0);

    List_Delete(etets);
  }

  /* Now get the triangular face connected to the edge. For each
     triangular face, record the vertex opposite to edge esplit and
     delete the triangular face */

  etris = ME_Faces(esplit);
  if (etris) {
    ntris = List_Num_Entries(etris);
    triverts = (MVertex_ptr (*)[3]) malloc(ntris*sizeof(MVertex_ptr[3]));
    fdim = (int *) malloc(ntris*sizeof(int));
    fid = (int *) malloc(ntris*sizeof(int));
  }
  
  for (i = 0; i < ntris; i++) {
    f = List_Entry(etris,i);

    fverts = MF_Vertices(f,1,0);
    for (j = 0; j < 3; j++) {
      fv = List_Entry(fverts,j);
      if (fv != ev[0] && fv != ev[1]) {        
        triverts[i][0] = fv;
        triverts[i][1] = List_Entry(fverts,(j+1)%3);
        triverts[i][2] = List_Entry(fverts,(j+2)%3);
        fdim[i] = MF_GEntDim(f);
        fid[i] = MF_GEntID(f);
        break;
      }
    }
    List_Delete(fverts);

    MF_Delete(f,0);
  }

  if (etris) List_Delete(etris);

  /* Now split the edge itself */

  vsplit = ME_Split(esplit, splitxyz);

  /* Now for each tri face that we deleted, create two tri faces that
     incorporate the split vertex, one of the split edge vertices and
     opposite vertex */

  for (i = 0; i < ntris; i++) {

    /* First triangle */

    fvarr[0] = triverts[i][0]; 
    fvarr[1] = triverts[i][1];
    fvarr[2] = vsplit;

    f = MF_New(mesh);
    MF_Set_Vertices(f,3,fvarr);
    MF_Set_GEntDim(f,fdim[i]);
    MF_Set_GEntID(f,fid[i]);
    
    /* Second triangle */

    fvarr[0] = triverts[i][0];
    fvarr[1] = vsplit;
    fvarr[2] = triverts[i][2];

    f = MF_New(mesh);
    MF_Set_Vertices(f,3,fvarr);
    MF_Set_GEntDim(f,fdim[i]);
    MF_Set_GEntID(f,fid[i]);
  }
  if (ntris) {
    free(triverts);
    free(fdim);
    free(fid);
  }

  /* Now for each tet that we deleted, create two tets (these will use
     the split faces that are already created */

  for (i = 0; i < ntets; i++) {
    rvarr[0] = vsplit;
    rvarr[1] = tetverts[i][2];
    rvarr[2] = tetverts[i][1];
    rvarr[3] = tetverts[i][0];

    r = MR_New(mesh);
    MR_Set_Vertices(r,4,rvarr,0,NULL);
    MR_Set_GEntID(r,rid[i]);

    rvarr[0] = vsplit;
    rvarr[1] = tetverts[i][1];
    rvarr[2] = tetverts[i][2];
    rvarr[3] = tetverts[i][3];

    r = MR_New(mesh);
    MR_Set_Vertices(r,4,rvarr,0,NULL);
    MR_Set_GEntID(r,rid[i]);
  }

  if (ntets) {
    free(tetverts);
    free(rid);
  }

  return vsplit;
}
Пример #5
0
MVertex_ptr MF_Split(MFace_ptr fsplit, double *splitxyz) {
  Mesh_ptr mesh;
  MVertex_ptr vsplit, fv[3];
  MEdge_ptr enew, *fedges0, *fedges1, fe;
  MFace_ptr fnew[MAXPV2];
  MRegion_ptr fr;
  int gid, gdim, i, j, idx, nnew;
  int nfv, fnewdir[MAXPV2], rfdir;
  List_ptr fregs, fverts;

  gdim = MF_GEntDim(fsplit);
  gid = MF_GEntID(fsplit);
 
  /* Collect information */

  mesh = MF_Mesh(fsplit);
  
  /* Regions connected to face */
  
  fregs = MF_Regions(fsplit);

  /* Vertices of face */

  fverts = MF_Vertices(fsplit,1,0);
  nfv = List_Num_Entries(fverts);

  /* Create the splitting vertex */

  vsplit = MV_New(mesh);
  MV_Set_Coords(vsplit,splitxyz);
  MV_Set_GEntDim(vsplit,gdim);
  MV_Set_GEntID(vsplit,gid);

  /* Create the 'nfe' faces */

  for (i = 0; i < nfv; i++) {
    fv[0] = vsplit;
    fv[1] = List_Entry(fverts,i);
    fv[2] = List_Entry(fverts,(i+1)%nfv);
    
    fnew[i] = MF_New(mesh);
    MF_Set_GEntDim(fnew[i],gdim);
    MF_Set_GEntID(fnew[i],gid);
    MF_Set_Vertices(fnew[i],3,fv);
  }
  List_Delete(fverts);
  nnew = nfv;


  if (fregs) {
    for (i = 0; i < List_Num_Entries(fregs); i++) {
      fr = List_Entry(fregs,i);
      rfdir = MR_FaceDir(fr,fsplit);
      for (j = 0; j < nnew; j++)
        fnewdir[j] = rfdir;
      MR_Replace_Faces(fr,1,&fsplit,nnew,fnew,fnewdir);
    }
    List_Delete(fregs);
  }

  MF_Delete(fsplit,0);

  return vsplit;
}