Ejemplo n.º 1
0
PView *GMSH_CVTRemeshPlugin::execute(PView *v)
{
  //TODO normalization

  GModel* m = GModel::current() ;

  std::vector<double> vertices ;
  std::vector<unsigned int> faces ;

  unsigned int offset = 0 ;
  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) {
    (*it)->buildSTLTriangulation() ;
    for(unsigned int i = 0; i < (*it)->stl_vertices.size(); ++i) {
      GPoint p = (*it)->point((*it)->stl_vertices[i]) ;
      vertices.push_back(p.x()) ;
      vertices.push_back(p.y()) ;
      vertices.push_back(p.z()) ;
    }
    for(unsigned int i = 0; i < (*it)->stl_triangles.size(); ++i) {
      faces.push_back((*it)->stl_triangles[i]+offset) ;
    }
    offset += (*it)->stl_vertices.size() ;
  }

  Revoropt::MeshBuilder<3> mesh ;
  mesh.swap_vertices(vertices) ;
  mesh.swap_faces(faces) ;

  double mesh_center[3] ;
  double mesh_scale ;
  Revoropt::normalize_mesh(&mesh, mesh_center, &mesh_scale) ;

  double nradius = (double)CVTRemeshOptions_Number[5].def ;

  //normals
  std::vector<double> normals(3*mesh.vertices_size()) ;
  Revoropt::full_robust_vertex_normals(&mesh,nradius,normals.data()) ;

  //lifted vertices
  std::vector<double> lifted_vertices(6*mesh.vertices_size(), 0) ;
  for(unsigned int vertex = 0; vertex < mesh.vertices_size(); ++vertex) {
    std::copy( mesh.vertex(vertex),
               mesh.vertex(vertex)+3,
               lifted_vertices.data()+6*vertex
             ) ;
    std::copy( normals.data()+3*vertex,
               normals.data()+3*vertex+3,
               lifted_vertices.data()+6*vertex+3
             ) ;
  }

  //setup lifted mesh
  Revoropt::ROMeshWrapper<3,6> lifted_mesh(
    lifted_vertices.data(),
    lifted_vertices.size()/6,
    &mesh
  ) ;

  //triangle weight factor
  double twfactor = (double)CVTRemeshOptions_Number[3].def ;

  //face ratios
  std::vector<double> triangle_weights(lifted_mesh.faces_size()) ;
  if(twfactor > 0) {
    for(unsigned int f = 0; f < lifted_mesh.faces_size(); ++f) {
      //vertices of the initial triangle
      const unsigned int* fverts = mesh.face(f) ;

      //positions
      const double* x[3] ;
      for(int i=0; i<3; ++i) {
        x[i] = lifted_mesh.vertex(fverts[i]) ;
      }

      //ratio
      double ratio = 1 ;

      //vectors
      typedef Eigen::Matrix<double,3,1> Vector3 ;

      Eigen::Map<const Vector3> v0(x[0]) ;
      Eigen::Map<const Vector3> v1(x[1]) ;
      Eigen::Map<const Vector3> v2(x[2]) ;

      //triangle frame
      Vector3 U = (v1-v0) ;
      const double U_len = U.norm() ;
      if(U_len > 0) {
        U /= U_len ;
        Vector3 H = (v2-v0) ;
        H = H - H.dot(U)*U ;
        const double H_len = H.norm() ;
        if(H_len > 0) {
          //we know that the triangle is not flat
          H /= H_len ;

          //gradient of the barycentric weights in the triangle
          Eigen::Matrix<double,3,2> bar_grads ;
          bar_grads(2,0) = 0 ;
          bar_grads(2,1) = 1/H_len ;

          //gradient norms of every normal component
          for(int i = 0; i < 2; ++i) {
            //reference frame for the vertex
            Eigen::Map<const Vector3> vi0(x[(i+1)%3]) ;
            Eigen::Map<const Vector3> vi1(x[(i+2)%3]) ;
            Eigen::Map<const Vector3> vi2(x[ i     ]) ;

            Vector3 Ui = (vi1-vi0) ;
            Ui /= Ui.norm() ;
            Vector3 Hi = (vi2-vi0) ;
            Hi = Hi - Hi.dot(Ui)*Ui ;
            const double Hi_invlen = 1/Hi.norm() ;
            Hi *= Hi_invlen ;
            bar_grads(i,0) = Hi.dot(U)*Hi_invlen ;
            bar_grads(i,1) = Hi.dot(H)*Hi_invlen ;
          }

          //gradient of each component of the normal
          Eigen::Map<const Vector3> n0(x[0]+3) ;
          Eigen::Map<const Vector3> n1(x[1]+3) ;
          Eigen::Map<const Vector3> n2(x[2]+3) ;

          Eigen::Matrix<double,3,2> n_grads = Eigen::Matrix<double,3,2>::Zero() ;

          n_grads = n0*bar_grads.row(0) ;
          n_grads += n1*bar_grads.row(1) ;
          n_grads += n2*bar_grads.row(2) ;

          //maximal gradient norm
          double g_max = n_grads.row(0).dot(n_grads.row(0)) ;
          double g_other = n_grads.row(1).dot(n_grads.row(1)) ;
          g_max = g_max > g_other ? g_max : g_other ;
          g_other = n_grads.row(2).dot(n_grads.row(2)) ;
          g_max = g_max > g_other ? g_max : g_other ;

          if(g_max == g_max) { //prevent nan
            ratio += g_max ;
          }
        }
      }
      triangle_weights[f] = pow(ratio,twfactor) ;
    }
  }

  //normal factor
  double nfactor = (double)CVTRemeshOptions_Number[2].def ; ;

  //weight the normal component by the provided factor
  for(unsigned int i = 0; i<lifted_mesh.vertices_size(); ++i) {
    double* v = lifted_vertices.data() + 6*i ;
    v[3]*= nfactor ;
    v[4]*= nfactor ;
    v[5]*= nfactor ;
  }

  //number of sites
  unsigned int nsites = (unsigned int)CVTRemeshOptions_Number[0].def ;

  //lifted sites
  std::vector<double> lifted_sites(6*nsites) ;
  if(twfactor > 0) {
    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
      &lifted_mesh, nsites, lifted_sites.data(), triangle_weights.data()
    ) ;
  } else {
    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
      &lifted_mesh, nsites, lifted_sites.data()
    ) ;
  }

  //setup the cvt minimizer
  Revoropt::CVT::DirectMinimizer< Revoropt::ROMesh<3,6> > cvt ;
  cvt.set_sites(lifted_sites.data(), nsites) ;
  cvt.set_mesh(&lifted_mesh) ;
  if(twfactor > 0) {
    cvt.set_triangle_weights(triangle_weights.data()) ;
  }

  //setup the callback
  SolverCallback callback ;

  //number of iterations
  unsigned int niter = (unsigned int)CVTRemeshOptions_Number[1].def ; ;
  unsigned int aniso_niter = std::min<unsigned int>(10,niter) ;

  //solver status
  int status = 0 ;

  //isotropic iterations
  if(niter > 10) {
    aniso_niter = std::max(aniso_niter,niter*10/100) ;
    cvt.set_anisotropy(1) ;
    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(niter-aniso_niter, &callback) ;
  }

  //anisotropic iterations
  if(niter > 0) {
    //tangent space anisotropy
    double tanisotropy = (double)CVTRemeshOptions_Number[4].def ; ;

    //anisotropic iterations
    cvt.set_anisotropy(tanisotropy) ;
    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(aniso_niter, &callback) ;
  }

  //rdt
  std::vector<unsigned int> rdt_triangles ;
  Revoropt::RDTBuilder< Revoropt::ROMesh<3,6> > build_rdt(rdt_triangles) ;
  Revoropt::RVD< Revoropt::ROMesh<3,6> > rvd ;
  rvd.set_sites(lifted_sites.data(), nsites) ;
  rvd.set_mesh(&lifted_mesh) ;
  rvd.compute(build_rdt) ;

  GFace* res_face = new discreteFace(m, m->getMaxElementaryNumber(2)+1) ;
  m->add(res_face) ;

  //scale back and transfer to gmsh
  std::vector<MVertex*> m_verts(nsites) ;
  for(unsigned int i = 0; i < nsites; ++i) {
    m_verts[i] = new MVertex(
        lifted_sites[6*i  ]*mesh_scale + mesh_center[0],
        lifted_sites[6*i+1]*mesh_scale + mesh_center[1],
        lifted_sites[6*i+2]*mesh_scale + mesh_center[2]
        ) ;
    res_face->addMeshVertex(m_verts[i]) ;
  }
  for(unsigned int i = 0; i < rdt_triangles.size()/3; ++i) {
    res_face->addTriangle(
      new MTriangle(
        m_verts[rdt_triangles[3*i  ]],
        m_verts[rdt_triangles[3*i+1]],
        m_verts[rdt_triangles[3*i+2]]
        )
    ) ;
  }

  res_face->setAllElementsVisible(true) ;

  return v ;
}
Ejemplo n.º 2
0
PView *GMSH_BubblesPlugin::execute(PView *v)
{
  double shrink = (double)BubblesOptions_Number[0].def;
  std::string fileName = BubblesOptions_String[0].def;

  FILE *fp = Fopen(fileName.c_str(), "w");
  if(!fp){
    Msg::Error("Could not open output file '%s'", fileName.c_str());
    return v;
  }

  GModel *m = GModel::current();

  int p = m->getMaxElementaryNumber(0) + 1;
  int l = m->getMaxElementaryNumber(1) + 1;
  int s = m->getMaxElementaryNumber(2) + 1;
  int ll = s, ps = 1;

  SBoundingBox3d bbox = m->bounds();
  double lc = norm(SVector3(bbox.max(), bbox.min())) / 100;
  fprintf(fp, "lc = %g;\n", lc);

  for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++)
    (*vit)->writeGEO(fp, "lc");

  for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++)
    (*eit)->writeGEO(fp);

  for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){
    (*fit)->writeGEO(fp);
    fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag());

    int sbeg = s;
    int llbeg = ll;

    // compute vertex-to-triangle_barycenter map
    std::map<MVertex*, std::vector<SPoint3> > v2t;
    for(unsigned int i = 0; i < (*fit)->triangles.size(); i++)
      for(int j = 0; j < 3; j++)
        v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter());

    // add boundary vertices in map to get cells "closer" to the boundary
    for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin();
        it != v2t.end(); it++){
      MVertex *v = it->first;
      if(v->onWhat() && v->onWhat()->dim() < 2)
        it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z()));
    }

    for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin();
        it != v2t.end(); it++){
      if(it->second.size() > 2){
        // get barycenter of cell boundary points and order them
        SPoint3 bc;
        for(unsigned int i = 0; i < it->second.size(); i++)
          bc += it->second[i];
        bc *= 1. / (double)it->second.size();
        compareAngle comp(bc);
        std::sort(it->second.begin(), it->second.end(), comp);
        // shrink cells
        if(shrink){
          for(unsigned int i = 0; i < it->second.size(); i++){
            double dir[3] = {it->second[i].x() - bc.x(),
                             it->second[i].y() - bc.y(),
                             it->second[i].z() - bc.z()};
            it->second[i][0] -= shrink * dir[0];
            it->second[i][1] -= shrink * dir[1];
            it->second[i][2] -= shrink * dir[2];
          }
        }
        // create b-spline bounded surface for each cell
        int nump = it->second.size();
        for(int i = 0; i < nump; i++){
          SPoint3 &b(it->second[i]);
          fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z());
        }
        fprintf(fp, "BSpline(%d) = {", l++);
        for(int i = nump - 1; i >= 0; i--)
          fprintf(fp, "%d,", p - i - 1);
        fprintf(fp, "%d};\n", p - nump);
        fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1);
        fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1);
      }
    }
    fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1);

    fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1);
    fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1);
  }

  fclose(fp);

  return v;
}