Ejemplo n.º 1
0
// this function specifically meshes a quadToTri top in an unstructured way
// return 1 if success, return 0 if failed.
// Added 2010-12-20
static int MeshQuadToTriTopUnstructured(GFace *from, GFace *to,
                                   std::set<MVertex*, MVertexLessThanLexicographic> &pos)
{

  // if the source is all triangles, then just return 1.
  if( from->triangles.size() && !from->quadrangles.size() )
    return 1;

  if( !to->meshAttributes.extrude || !to->meshAttributes.extrude->mesh.QuadToTri  )
    return 0;


  // in weird case of NO quads and NO tri
  if( !from->triangles.size() && !from->quadrangles.size() )
    return 0;


  // make set of source edge vertices
  std::set<MVertex*, MVertexLessThanLexicographic> pos_src_edge;
  QuadToTriInsertFaceEdgeVertices(from, pos_src_edge);

  // Loop through all the quads and make the triangles with diagonals running
  // in a selected direction.

  to->triangles.reserve(to->triangles.size()+from->quadrangles.size()*2);
  std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp;

  for(unsigned int i = 0; i < from->quadrangles.size(); i++){
    std::vector<MVertex*> verts;
    for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){
      MVertex *v = from->quadrangles[i]->getVertex(j);
      MVertex tmp(v->x(), v->y(), v->z(), 0, -1);
      ExtrudeParams *ep = to->meshAttributes.extrude;
      ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
                  tmp.x(), tmp.y(), tmp.z());
      itp = pos.find(&tmp);
      if(itp == pos.end()){ // FIXME: workaround
        Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
        itp = tmp.linearSearch(pos);
      }
      if(itp == pos.end()) {
        Msg::Error("Could not find extruded vertex (%.16g, %.16g, %.16g) in surface %d",
            tmp.x(), tmp.y(), tmp.z(), to->tag());
        to->triangles.reserve(to->triangles.size()+1);
        return 0;
      }
      verts.push_back(*itp);
    }


    if( verts.size() != 4 ){
      Msg::Error("During mesh of QuadToTri surface %d, %d vertices found "
                 "in quad of source surface %d.", to->tag(), verts.size(),
                 from->tag() );
      return 0;
    }


    // draw other diagonals to minimize difference in average edge length with diagonal length, in quadrature

    double mag_sq_ave = 0.0;
    for( int p = 0; p < 4; p++ ){
      int d_leg = verts[p]->distance(verts[(p+1)%4]);
      mag_sq_ave += d_leg*d_leg;
    }
    mag_sq_ave /= 4;

    double d1 = verts[0]->distance(verts[2]);
    double d2 = verts[1]->distance(verts[3]);

    if(fabs(d1*d1-mag_sq_ave) <= fabs(d2*d2-mag_sq_ave) ){
      addTriangle(verts[0],verts[1],verts[2],to);
      addTriangle(verts[0],verts[2],verts[3],to);
    }
    else{
      addTriangle(verts[1],verts[2],verts[3],to);
      addTriangle(verts[1],verts[3],verts[0],to);
    }
  }

  return 1;
}
Ejemplo n.º 2
0
// This function meshes the top surface of a QuadToTri extrusion.  It returns 0 if it is given a
// non-quadToTri extrusion or if it fails.
// Args:
//       'GFace *to' is the top surface to mesh, 'from' is the source surface, 'pos' is a std::set
//       of vertex positions for the top surface.
int MeshQuadToTriTopSurface( GFace *from, GFace *to, std::set<MVertex*,
                             MVertexLessThanLexicographic> &pos )
{
  if( !to->meshAttributes.extrude || !to->meshAttributes.extrude->mesh.QuadToTri  )
   return 0;

  // if the source is all triangles, then just let this function is not needed. Return 1.
  if( from->triangles.size() && !from->quadrangles.size() )
    return 1;

  // in weird case of NO quads and NO tri
  if( !from->triangles.size() && !from->quadrangles.size() )
    return 0;


  ExtrudeParams *ep = to->meshAttributes.extrude;
  if( !ep || !ep->mesh.ExtrudeMesh || !(ep->geo.Mode == COPIED_ENTITY) ){
    Msg::Error("In MeshQuadToTriTopSurface(), incomplete or no "
		"extrude information for top face %d.", to->tag() );
    return 0;
  }
  
  // is this a quadtri extrusion with added vertices?
  bool is_addverts = false;
  if( ep && (ep->mesh.QuadToTri == QUADTRI_ADDVERTS_1 || ep->mesh.QuadToTri == QUADTRI_ADDVERTS_1_RECOMB) )
    is_addverts = true;

  // execute this section if 
  // IF this is a 'no new vertices' quadToTri, mesh the surfaces according to this modified
  // least point value method: if a 3 boundary point quad, draw diagonals from middle corner toward
  // interior.  If a a 2- or 1- point boundary quad, draw toward lowest pointer number NOT on boundary.
  // All interior quad, draw diagonal to vertex with lowest pointer number.

  if( !is_addverts ){
    std::set<MVertex*, MVertexLessThanLexicographic> pos_src_edge;
    QuadToTriInsertFaceEdgeVertices(from, pos_src_edge);
    std::set<MVertex*, MVertexLessThanLexicographic>::iterator itp;

    // loop through each element source quadrangle and extrude
    for(unsigned int i = 0; i < from->quadrangles.size(); i++){
      std::vector<MVertex*> verts;
      for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){
        MVertex *v = from->quadrangles[i]->getVertex(j);
        MVertex tmp(v->x(), v->y(), v->z(), 0, -1);
        ExtrudeParams *ep = to->meshAttributes.extrude;
        ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
                    tmp.x(), tmp.y(), tmp.z());
        itp = pos.find(&tmp);
        if(itp == pos.end()){ // FIXME: workaround
          Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
          itp = tmp.linearSearch(pos);
        }
        if(itp == pos.end()) {
          Msg::Error("In MeshQuadToTriTopSurface(), Could not find "
                     "extruded vertex (%.16g, %.16g, %.16g) in surface %d",
              tmp.x(), tmp.y(), tmp.z(), to->tag());
          to->triangles.reserve(to->triangles.size()+1);
          return 0;
        }
        verts.push_back(*itp);
      }


      if( verts.size() != 4 ){
        Msg::Error("During mesh of QuadToTri surface %d, %d vertices found "
                   "in quad of source surface %d.", to->tag(), verts.size(),
                   from->tag() );
        return 0;
      }

      // make the element
      MElement *element = from->quadrangles[i];

      // count vertices that are on a boundary edge
      int edge_verts_count = 0;
      //int skip_index = 0;
      int bnd_indices[4];
      for( int p = 0; p < element->getNumVertices(); p++ ){
        if( pos_src_edge.find( element->getVertex(p) ) != pos_src_edge.end() ){
          edge_verts_count++;
          bnd_indices[p] = 1;
        }
        else{
          //skip_index = p;
          bnd_indices[p] = 0;
        }
      }

      // Apply modified lowest vertex pointer diagonalization
      int low_index = -1;
      if( edge_verts_count == 3 || edge_verts_count == 2 || edge_verts_count == 1 ){
        for( int p = 0; p < 4; p++ ){
          if( !bnd_indices[p] && verts[p] != element->getVertex(p) ){
            if( low_index < 0 )
              low_index = p;
            else if( verts[p] < verts[low_index] )
              low_index = p;
          }
        }
        if( low_index < 0 ) // what if they are all degenerate?  Avoid the out-of-bounds error.
          low_index = 0;
      }

      // lowest possible vertex pointer, regardless of if on edge or not
      else if( edge_verts_count == 4 || edge_verts_count == 0 )
        low_index = getIndexForLowestVertexPointer(verts);

      addTriangle( verts[low_index],verts[(low_index+1)%verts.size()],
                   verts[(low_index+2)%verts.size()],to);
      addTriangle( verts[low_index],verts[(low_index+2)%verts.size()],
                   verts[(low_index+3)%verts.size()],to);
    }
    return 1;
  }


  // AFTER THIS POINT IN FUNCTION, CODE IS ALL FOR 'ADD INTERNAL VERTEX' EXTRUSIONS (Less restrictive).

  // if source face is unstructured, can try to make the top mesh a little neater
  GFace *root_source = findRootSourceFaceForFace( from );
  ExtrudeParams *ep_src = root_source->meshAttributes.extrude;
  bool struct_root = false;
  if( root_source &&
      ( (ep_src && ep_src->mesh.ExtrudeMesh && ep_src->geo.Mode == EXTRUDED_ENTITY) ||
        root_source->meshAttributes.method == MESH_TRANSFINITE ) )
    struct_root = true;

  if( !struct_root && MeshQuadToTriTopUnstructured(from, to, pos) )
    return 1;

  // And top surface for the 'added internal vertex' method can be meshed quite easily
  else{
    std::set<MVertex *, MVertexLessThanLexicographic >::iterator itp;
    // loop through each element source quadrangle and extrude
    for(unsigned int i = 0; i < from->quadrangles.size(); i++){
      std::vector<MVertex*> verts;
      for(int j = 0; j < from->quadrangles[i]->getNumVertices(); j++){
        MVertex *v = from->quadrangles[i]->getVertex(j);
        MVertex tmp(v->x(), v->y(), v->z(), 0, -1);
        ExtrudeParams *ep = to->meshAttributes.extrude;
        ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
                    tmp.x(), tmp.y(), tmp.z());
        itp = pos.find(&tmp);
        if(itp == pos.end()){ // FIXME: workaround
          Msg::Info("Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
          itp = tmp.linearSearch(pos);
        }
        if(itp == pos.end()) {
          Msg::Error("In MeshQuadToTriTopSurface(), Could not find "
                     "extruded vertex (%.16g, %.16g, %.16g) in surface %d",
              tmp.x(), tmp.y(), tmp.z(), to->tag());
          to->triangles.reserve(to->triangles.size()+1);
          return 0;
        }
        verts.push_back(*itp);
      }


      if( verts.size() != 4 ){
        Msg::Error("During mesh of QuadToTri surface %d, %d vertices found "
                   "in quad of source surface %d.", to->tag(), verts.size(),
                   from->tag() );
        return 0;
      }

      // make the elements
      addTriangle( verts[0],verts[2], verts[3],to);
      addTriangle( verts[0],verts[1], verts[2],to);
    }
    return 1;
  }

  return 0;

}
Ejemplo n.º 3
0
static void extrudeMesh(GFace *from, GRegion *to, MVertexRTree &pos)
{
  ExtrudeParams *ep = to->meshAttributes.extrude;

  // interior vertices
  std::vector<MVertex*> mesh_vertices = from->mesh_vertices;

  // add all embedded vertices
  std::vector<MVertex*> embedded = from->getEmbeddedMeshVertices();
  mesh_vertices.insert(mesh_vertices.end(), embedded.begin(), embedded.end());

  // create extruded vertices
  for(unsigned int i = 0; i < mesh_vertices.size(); i++){
    MVertex *v = mesh_vertices[i];
    for(int j = 0; j < ep->mesh.NbLayer; j++) {
      for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
        double x = v->x(), y = v->y(), z = v->z();
        ep->Extrude(j, k + 1, x, y, z);
        if(j != ep->mesh.NbLayer - 1 || k != ep->mesh.NbElmLayer[j] - 1){
          MVertex *newv = new MVertex(x, y, z, to);
          to->mesh_vertices.push_back(newv);
          pos.insert(newv);
        }
      }
    }
  }

  if(ep && ep->mesh.ExtrudeMesh && ep->mesh.QuadToTri && ep->mesh.Recombine){
    meshQuadToTriRegion(to, pos);
    return;
  }

  // create elements (note that it would be faster to access the *interior*
  // nodes by direct indexing, but it's just simpler to query everything by
  // position)
  for(unsigned int i = 0; i < from->triangles.size(); i++){
    for(int j = 0; j < ep->mesh.NbLayer; j++) {
      for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
        std::vector<MVertex*> verts;
        if(getExtrudedVertices(from->triangles[i], ep, j, k, pos, verts) == 6) {
          createPriPyrTet(verts, to,from->triangles[i]);
        }
      }
    }
  }

  if(from->quadrangles.size() && !ep->mesh.Recombine){
    Msg::Error("Cannot extrude quadrangles without Recombine");
  }
  else{
    for(unsigned int i = 0; i < from->quadrangles.size(); i++){
      for(int j = 0; j < ep->mesh.NbLayer; j++) {
        for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
          std::vector<MVertex*> verts;
          if(getExtrudedVertices(from->quadrangles[i], ep, j, k, pos, verts) == 8)
            createHexPri(verts, to, from->quadrangles[i]);
        }
      }
    }
  }
}