Esempio n. 1
0
// The function that tests whether a surface is a QuadToTri top surface and whether
// there are conflicts. If surface is not a top for a valid QuadToTri region or if
// there are QuadToTri conflicts, return 0.
// if the surface turns out to be the source of a toroidal loop extrusion (which will then
// NOT have geo.Mode == COPIED_ENTITY), return 2 (this will require special meshing considerations).
// Note that RemoveDuplicateSurfaces() makes this DIFFICULT. 
// Also, the type of QuadToTri interface is placed into the
// pointer argument quadToTri. .
// Added 2010-12-09.
int IsValidQuadToTriTop(GFace *face, int *quadToTri, bool *detectQuadToTriTop)
{
  (*quadToTri) = NO_QUADTRI;
  (*detectQuadToTriTop) = false;

  int is_toroidal_quadtri = 0;
  
  GModel *model = face->model();

  // First thing is first: determine if this is a toroidal quadtri extrusion.  if so, can skip the  rest
  
  
  // It seems the member pointers to neighboring regions for extruded top faces are not set.
  // For now, have to loop through
  // ALL the regions to see if the presently considered face belongs to the region.
  // The following loop will find all the regions that the face bounds, and determine
  // whether the face is a top face of the region (including whether the region is even extruded).
  // After that information is determined, function can test for QuadToTri neighbor conflicts.

  

  
  // first determine if this is toroidal quadtotri
  is_toroidal_quadtri = IsInToroidalQuadToTri(face);
  
  if( is_toroidal_quadtri )
    (*detectQuadToTriTop) = true;
  else{
    std::vector<GRegion *> top_regions;
    std::vector<GRegion *> adjacent_regions;
    std::vector<GRegion *> all_regions;
    int numRegions = 0;
    int numTopRegions = 0;
    std::set<GRegion *, GEntityLessThan>::iterator itreg;

    for( itreg = model->firstRegion(); itreg != model->lastRegion(); itreg++ )
      all_regions.push_back( (*itreg) );

    for(unsigned int i_reg = 0; i_reg < all_regions.size(); i_reg++ ){

      // save time
      if( numRegions >= 2 )
	break;

      GRegion *region = all_regions[i_reg];

      // is region in the current model's regions or is it deleted?
      if( !FindVolume( ( region->tag() ) ) )
	continue;

      // does face belong to region?
      std::list<GFace *> region_faces = std::list<GFace *>( region->faces() );
      if( std::find( region_faces.begin(), region_faces.end(), face ) !=
	    region_faces.end() ){
	adjacent_regions.push_back(region);
	numRegions++;
      }
      else
	continue;

      // is region a structured extruded?
      if( !(region->meshAttributes.extrude && region->meshAttributes.extrude->mesh.ExtrudeMesh &&
	    region->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY) )
	continue;

      // Test whether the face is a top for the region
      if( IsSurfaceATopForRegion(region, face) ){
	top_regions.push_back(region);
	numTopRegions++;
	if( region->meshAttributes.extrude->mesh.QuadToTri )
	  (*detectQuadToTriTop) = true;
      }
	      
    }
 
    // MAIN test of whether this is even a quadToTri extrusion lateral
    // the only return 0 path that is NOT an error
    if( !(*detectQuadToTriTop) )
      return 0;

    ExtrudeParams *ep = face->meshAttributes.extrude;

    if(!ep && !is_toroidal_quadtri){
      Msg::Error("In IsValidQuadToTriTop(), no extrude info for surface %d.",
		face->tag() );
      return 0;
    }

    if( ep->geo.Mode != COPIED_ENTITY ){
      Msg::Error("In IsValidQuadToTriTop(), surface %d is not copied from source.",
		face->tag() );
      return 0;
    }

    if( ep->mesh.QuadToTri == 0){
      Msg::Error("In IsValidQuadToTriTop(), surface %d was determined to be the top surface "
		"for a QuadToTri extrusion, but does not have QuadToTri parameters set within itself.",
		face->tag() );
      return 0;
    }

    GFace *face_source = model->getFaceByTag(std::abs(ep->geo.Source));
    if(!face_source){
      Msg::Error("In IsValidQuadToTriTop(), unknown source face number %d.",
		  face->meshAttributes.extrude->geo.Source);
      return 0;
    }

    if(numRegions > 2){
      Msg::Error("In IsValidQuadToTriTop(), too many regions adjacent to surface %d.",
		face->tag() );
      return 0;
    }


    if( top_regions.size() ){
      (*quadToTri) = top_regions[0]->meshAttributes.extrude->mesh.QuadToTri;
    }

    // Make sure that face is the top for only one region. if not, then there will likely
    // be conflicts (two regions extruded into each other).
    if( top_regions.size() > 1 ){
      Msg::Error("In IsValidQuadToTriTop(), QuadToTri top surface %d identified as top "
		"surface for more than one region. Likely conflict.",  face->tag() );
      return 0;
    }

  }  // end of else that executes if NOT toroidal extrusion

  
  // this is technically redundant...but if changes are made, it's good to keep this here at the end for safety
  if( !(*detectQuadToTriTop) )
    return 0;

  if( !is_toroidal_quadtri )
    return 1;
  else if( is_toroidal_quadtri == 1 )
  { return 2;} // for toroidal extrusion
  else
    return 3;
    
}
Esempio n. 2
0
int SubdivideExtrudedMesh(GModel *m)
{
  // get all non-recombined extruded regions and vertices; also,
  // create a vector of quadToTri regions that have NOT been meshed
  // yet
  std::vector<GRegion*> regions, regions_quadToTri;
  MVertexRTree pos(CTX::instance()->geom.tolerance * CTX::instance()->lc);
  for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
    ExtrudeParams *ep = (*it)->meshAttributes.extrude;
    if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
       !ep->mesh.Recombine){
      regions.push_back(*it);
      insertAllVertices(*it, pos);
    }
    // create vector of valid quadToTri regions...not all will necessarily be meshed here.
    if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
       ep->mesh.Recombine && ep->mesh.QuadToTri){
      regions_quadToTri.push_back(*it);
    }
  }

  if(regions.empty()) return 0;
  Msg::Info("Subdividing extruded mesh");

  // create edges on lateral sides of "prisms"
  std::set<std::pair<MVertex*, MVertex*> > edges;
  for(unsigned int i = 0; i < regions.size(); i++)
    phase1(regions[i], pos, edges);

  // swap lateral edges to make them "tet-compatible"
  int j = 0, swap;
  std::set<std::pair<MVertex*, MVertex*> > edges_swap;
  do {
    swap = 0;
    for(unsigned int i = 0; i < regions.size(); i++)
      phase2(regions[i], pos, edges, edges_swap, swap);
    Msg::Info("Swapping %d", swap);
    if(j && j == swap) {
      Msg::Error("Unable to subdivide extruded mesh: change surface mesh or");
      Msg::Error("recombine extrusion instead");
      return -1;
    }
    j = swap;
  } while(swap);

  // delete volume elements and create tetrahedra instead
  for(unsigned int i = 0; i < regions.size(); i++){
    GRegion *gr = regions[i];

    for(unsigned int i = 0; i < gr->tetrahedra.size(); i++)
      delete gr->tetrahedra[i];
    gr->tetrahedra.clear();
    for(unsigned int i = 0; i < gr->hexahedra.size(); i++)
      delete gr->hexahedra[i];
    gr->hexahedra.clear();
    for(unsigned int i = 0; i < gr->prisms.size(); i++)
      delete gr->prisms[i];
    gr->prisms.clear();
    for(unsigned int i = 0; i < gr->pyramids.size(); i++)
      delete gr->pyramids[i];
    gr->pyramids.clear();
    phase3(gr, pos, edges);

    // re-Extrude bounding surfaces using edges as constraint
    std::list<GFace*> faces = gr->faces();
    for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++){
      ExtrudeParams *ep = (*it)->meshAttributes.extrude;
      if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
        !ep->mesh.Recombine){
        GFace *gf = *it;
        Msg::Info("Remeshing surface %d", gf->tag());
        for(unsigned int i = 0; i < gf->triangles.size(); i++)
          delete gf->triangles[i];
        gf->triangles.clear();
        for(unsigned int i = 0; i < gf->quadrangles.size(); i++)
          delete gf->quadrangles[i];
        gf->quadrangles.clear();
        MeshExtrudedSurface(gf, &edges);
      }
    }
  }

  // now mesh the QuadToTri regions. Everything can be done locally
  // for each quadToTri region, but still use edge set from above just
  // to make sure laterals get remeshed properly (
  // QuadToTriEdgeGenerator detects if the neighbor has been meshed or
  // if a lateral surface should remain static for any other reason).
  // If this function detects allNonGlobalSharedLaterals, it won't
  // mesh the region (should already be done in ExtrudeMesh).
  for(unsigned int i = 0; i < regions_quadToTri.size(); i++){
    GRegion *gr = regions_quadToTri[i];
    MVertexRTree pos_local(CTX::instance()->geom.tolerance * CTX::instance()->lc);
    insertAllVertices(gr, pos_local);
    meshQuadToTriRegionAfterGlobalSubdivide(gr, &edges, pos_local);
  }

  // carve holes if any
  // TODO: update extrusion information
  for(unsigned int i = 0; i < regions.size(); i++){
    GRegion *gr = regions[i];
    ExtrudeParams *ep = gr->meshAttributes.extrude;
    if(ep->mesh.Holes.size()){
      std::map<int, std::pair<double, std::vector<int> > >::iterator it;
      for(it = ep->mesh.Holes.begin(); it != ep->mesh.Holes.end(); it++)
        carveHole(gr, it->first, it->second.first, it->second.second);
    }
  }
  for(unsigned int i = 0; i < regions_quadToTri.size(); i++){
    GRegion *gr = regions_quadToTri[i];
    ExtrudeParams *ep = gr->meshAttributes.extrude;
    if(ep->mesh.Holes.size()){
      std::map<int, std::pair<double, std::vector<int> > >::iterator it;
      for(it = ep->mesh.Holes.begin(); it != ep->mesh.Holes.end(); it++)
        carveHole(gr, it->first, it->second.first, it->second.second);
    }
  }

  return 1;
}