Ejemplo n.º 1
0
  int MESH_ConcatSubMesh_Region(Mesh_ptr mesh, int num, Mesh_ptr *submeshes) {
    int nrf, nre, nrv, nfe, i, j, k, num_parbndry_verts, num_parbndry_edges, num_parbndry_faces, ival;
    MVertex_ptr mv, new_mv, sub_mv;
    MEdge_ptr me, new_me, sub_me;
    MFace_ptr mf, new_mf, sub_mf;
    MRegion_ptr new_mr, sub_mr;
    List_ptr mrfaces, mredges, mrverts, mfedges;
    int add_region, 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);
    List_ptr parbndry_faces = List_New(10);

    MFace_ptr *rfaces = (MFace_ptr *) malloc(MAXPF3*sizeof(MFace_ptr));
    int *rfdirs = (int *) malloc(MAXPF3*sizeof(int));
    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 faces, edges and vertices on the partition boundary */
    idx = 0; num_parbndry_faces = 0;
    while ((mf = MESH_Next_Face(mesh,&idx))) 
      if (MF_PType(mf) != PINTERIOR) {
        List_Add(parbndry_faces,mf);
        num_parbndry_faces++;
      }
    idx = 0; num_parbndry_edges = 0;
    while ((me = MESH_Next_Edge(mesh,&idx))) 
      if (ME_PType(me) != PINTERIOR) {
        List_Add(parbndry_edges,me);
        num_parbndry_edges++;
      }
    idx = 0; num_parbndry_verts = 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_faces,num_parbndry_faces,sizeof(MFace_ptr),compareGlobalID);
    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));
    int *parbndry_face_gids = (int *)malloc(num_parbndry_faces*sizeof(int));

    /* store them in array for binary search */
    for (i = 0; i < num_parbndry_faces; i++) {
      mf = List_Entry(parbndry_faces,i);
      parbndry_face_gids[i] = MF_GlobalID(mf);
    }
    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, max_fnew = 0;
    for (i = 0; i < num; i++) {
      max_vnew += MESH_Num_Vertices(submeshes[i]);
      max_enew += MESH_Num_Edges(submeshes[i]);
      max_fnew += MESH_Num_Faces(submeshes[i]);
    }

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

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

    /* 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);
      MAttrib_ptr fidatt = MAttrib_New(submesh, "tempfid", POINTER, MFACE);

      idx = 0;
      while ((sub_mr = MESH_Next_Region(submesh, &idx))) {
        add_region = 0;

        /* Find matching vertices between submesh and main mesh */

        mrverts = MR_Vertices(sub_mr);
        nrv = List_Num_Entries(mrverts);
        for (j = 0; j < nrv; j++) {
          sub_mv = List_Entry(mrverts,j);

          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_region = 1; 
          } else {

            /* Does the global ID of this vertex of the sub mesh region
             * match the global ID of a 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) {
              add_region = 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(mrverts);

        /* Find matching edges between submesh and main mesh */

        mredges = MR_Edges(sub_mr);
        nre = List_Num_Entries(mredges);
        for (j = 0; j < nre; j++) {
          sub_me = List_Entry(mredges,j);
          
          /* Does the edge already have a counterpart in 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 region
             * match the global ID of a 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) {
              add_region = 1; 
              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);
            }
          }
        }
        List_Delete(mredges);
          
        /* Find matching faces between submesh and main mesh */

        mrfaces = MR_Faces(sub_mr);
        nrf = List_Num_Entries(mrfaces);
        for (j = 0; j < nrf; j++) {
          sub_mf = List_Entry(mrfaces,j);

          MEnt_Get_AttVal(sub_mf, fidatt, &ival, &rval, &mf);

          if (!mf) {
            /* Does the global ID of this face of the sub mesh region
             * match the global ID of a boundary face in the main
             * mesh? */
            
            global_id = MF_GlobalID(sub_mf);
            loc = (int *) bsearch(&global_id, parbndry_face_gids, num_parbndry_faces, sizeof(int),
                                  compareINT);
            if (loc) {
              iloc = loc - parbndry_face_gids;
              mf = List_Entry(parbndry_faces,iloc); 
              /* here set the ghost edge property, only necessary when the input submeshes are not consistent */
              if (MF_PType(mf) == PGHOST && MF_PType(sub_mf) != PGHOST) {
                MF_Set_GEntDim(mf,MF_GEntDim(sub_mf));
                MF_Set_GEntID(mf,MF_GEntID(sub_mf));
              }

              MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, mf);
            }
          }
        }

        if (!add_region) {
          List_Delete(mrfaces);
          continue;
        }
        
        new_mr = MR_New(mesh);                  /* add region */
        MR_Set_GEntDim(new_mr,MR_GEntDim(sub_mr));
        MR_Set_GEntID(new_mr,MR_GEntID(sub_mr));
        MR_Set_PType(new_mr,PGHOST);
        MR_Set_MasterParID(new_mr,MR_MasterParID(sub_mr));
        MR_Set_GlobalID(new_mr,MR_GlobalID(sub_mr));
	
        nrf = List_Num_Entries(mrfaces);
        int i2;
        for(i2 = 0; i2 < nrf; i2++) {
          sub_mf = List_Entry(mrfaces,i2);
          global_id = MF_GlobalID(sub_mf);
          rfdirs[i2] = MR_FaceDir_i(sub_mr,i2) == 1 ? 1 : 0;

          new_mf = NULL;
          MEnt_Get_AttVal(sub_mf, fidatt, &ival, &rval, &new_mf);

          if (!new_mf) {
            /* search in the ghost layer if another face with
             * this global ID has been added */
            loc = (int *) bsearch(&global_id, new_face_gids, num_new_faces,
                                  sizeof(int), compareINT);
            if (loc) {
              iloc = loc - new_face_gids;
              new_mf = List_Entry(new_faces, iloc);
              MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, new_mf);
            }
          }

          if (new_mf) {
            List_ptr mfverts = MF_Vertices(sub_mf,1,0);
            int fvgid0[2];
            fvgid0[0] = MF_GlobalID(List_Entry(mfverts,0));
            fvgid0[1] = MF_GlobalID(List_Entry(mfverts,1));
            List_Delete(mfverts);

            mfverts = MF_Vertices(new_mf,1,0);
            int nfv = List_Num_Entries(mfverts);
            int fvgid1[MAXPV2];
            for (j = 0; j < nfv; j++)
              fvgid1[j] = MF_GlobalID(List_Entry(mfverts,j));
            List_Delete(mfverts);

            for (j = 0; j < nfv; j++) {
              if (fvgid1[j] == fvgid0[0]) {
                if (fvgid1[(j+nfv-1)%nfv] == fvgid0[1]) /* reverse dir */
                  rfdirs[i2] = !rfdirs[i2];
                break;
              }
            }                  
          }
          else {  /* add a new face to main mesh */
            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));
	    
            MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, new_mf);
            List_Add(new_faces, new_mf);
	    
            mfedges = MF_Edges(sub_mf,1,0);
            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);      /* add new edge and copy information */
                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 new vertex to main mesh */
                    new_mv = MV_New(mesh);  /* add new vertex and copy information */
                    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);
          }
          rfaces[i2] = new_mf;
        }
        MR_Set_Faces(new_mr,nrf,rfaces,rfdirs); /* set region-face */

        List_Delete(mrfaces);
      }

      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);
      idx = 0;
      while ((sub_mf = MESH_Next_Face(submesh, &idx)))
	MEnt_Rem_AttVal(sub_mf, fidatt);
      MAttrib_Delete(fidatt);

      /* Sort the added entity lists by GlobalID */
      num_new_faces = List_Num_Entries(new_faces);
      List_Sort(new_faces, num_new_faces, sizeof(MFace_ptr), compareGlobalID);
      for (j = 0; j < num_new_faces; j++)
        new_face_gids[j] = MF_GlobalID(List_Entry(new_faces, j));

      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_faces);
    List_Delete(parbndry_edges);
    List_Delete(parbndry_verts);
    List_Delete(new_faces);
    List_Delete(new_edges);
    List_Delete(new_verts);

    free(parbndry_vert_gids);
    free(parbndry_edge_gids);
    free(parbndry_face_gids);
    free(new_face_gids);
    free(new_edge_gids);
    free(new_vert_gids);
    free(fedges);
    free(fedirs);
    free(rfaces);
    free(rfdirs);

    return 1;
  }
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
MVertex_ptr MF_Split_SimplexMesh(MFace_ptr fsplit, double *splitxyz) {
  int i, j, k, rfdir=1, ntets=0, ntris=0, *rid=NULL, fgdim, fgid, found;
  MVertex_ptr vsplit, ev[2], (*tetverts)[4]=NULL, triverts[3], fv;
  MVertex_ptr fvarr[3], rvarr[4];
  MFace_ptr f;
  MRegion_ptr r;
  List_ptr fedges, ftets, rfaces, fverts;
  Mesh_ptr mesh = MF_Mesh(fsplit);

  /* point is not on the boundary of the face */
    
  ftets = MF_Regions(fsplit);
  if (ftets) {
    ntets = List_Num_Entries(ftets);   
    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(ftets,i);

    rfaces = MR_Faces(r);

    /* Find the face to be split and get the first three vertices
       in a suitable order from it. Also, find another face and 
       get a vertex that is not in the face to be split. This vertex
       forms the fourth vertex of the tet */

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

      if (f == fsplit) {
        rfdir = MR_FaceDir_i(r,j);        
        fverts = MF_Vertices(f,!rfdir,0);

        for (k = 0; k < 3; k++) {
          tetverts[i][0] = List_Entry(fverts,0);
          tetverts[i][1] = List_Entry(fverts,1);
          tetverts[i][2] = List_Entry(fverts,2);
        }
        List_Delete(fverts);
        break;
      }
    }

    found = 0;
    for (j = 0; j < 4; j++) {
      f = List_Entry(rfaces,j);
      if (f != fsplit) {
        fverts = MF_Vertices(f,!rfdir,0);
        for (k = 0; k < 3; k++) {
          fv = List_Entry(fverts,k);
          if (!MF_UsesEntity(fsplit,fv,MVERTEX)) {
            tetverts[i][3] = fv;
            found = 1;
            break;
          }
        }
        List_Delete(fverts);
      }
      if (found) break;
    }

    List_Delete(rfaces);
  }

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

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

    List_Delete(ftets);
  }

  /* Delete the face itself */

  fverts = MF_Vertices(fsplit,1,0);
  for (i = 0; i < 3; i++)
    triverts[i] = List_Entry(fverts,i);
  List_Delete(fverts);

  fgdim = MF_GEntDim(fsplit);
  fgid  = MF_GEntID(fsplit);


  /* Split the face */

  vsplit = MF_Split(fsplit, splitxyz);

  
  /* Create three tets for each tet that was deleted */

  for (i = 0; i < ntets; i++) {
    for (j = 0; j < 3; j++) {
      r = MR_New(mesh);
      rvarr[0] = vsplit;
      rvarr[1] = tetverts[i][j];
      rvarr[2] = tetverts[i][(j+1)%3];
      rvarr[3] = tetverts[i][3];
      MR_Set_Vertices(r, 4, rvarr, 0, NULL);
      MR_Set_GEntID(r,rid[i]);
    }
  }

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

  return vsplit;
}