Esempio n. 1
0
IGL_INLINE void igl::boundary_loop(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& F,
    Eigen::VectorXi& b)
{
  std::vector<int> bnd;
  bnd.clear();
  std::vector<bool> isVisited(V.rows(),false);

  // Actually mesh only needs to be manifold near boundary, so this is
  // over zealous (see gptoolbox's outline_loop for a more general
  // (and probably faster) implementation)
  assert(is_edge_manifold(V,F) && "Mesh must be manifold");
  Eigen::MatrixXi TT,TTi;
  std::vector<std::vector<int> > VF, VFi;
  igl::triangle_triangle_adjacency(V,F,TT,TTi);
  igl::vertex_triangle_adjacency(V,F,VF,VFi);

  // Extract one boundary edge
  bool done = false;
  for (int i = 0; i < TT.rows() && !done; i++)
  {
    for (int j = 0; j < TT.cols(); j++)
    {
      if (TT(i,j) < 0)
      {
        int idx1, idx2;
        idx1 = F(i,j);
        idx2 = F(i,(j+1) % F.cols());
        bnd.push_back(idx1);
        bnd.push_back(idx2);
        isVisited[idx1] = true;
        isVisited[idx2] = true;
        done = true;
        break;
      }
    }
  }

  // Traverse boundary
  while(1)
  {
    bool changed = false;
    int lastV;
    lastV = bnd[bnd.size()-1];

    for (int i = 0; i < (int)VF[lastV].size(); i++)
    {
      int curr_neighbor = VF[lastV][i];

      if (TT.row(curr_neighbor).minCoeff() < 0.) // Face contains boundary edge
      {
        int idx_lastV_in_face;
        if (F(curr_neighbor,0) == lastV) idx_lastV_in_face = 0;
        if (F(curr_neighbor,1) == lastV) idx_lastV_in_face = 1;
        if (F(curr_neighbor,2) == lastV) idx_lastV_in_face = 2;

        int idx_prev = (idx_lastV_in_face + F.cols()-1) % F.cols();
        int idx_next = (idx_lastV_in_face + 1) % F.cols();
        bool isPrevVisited = isVisited[F(curr_neighbor,idx_prev)];
        bool isNextVisited = isVisited[F(curr_neighbor,idx_next)];

        bool gotBndEdge = false;
        int next_bnd_vertex;
        if (!isNextVisited && TT(curr_neighbor,idx_lastV_in_face) < 0)
        {
          next_bnd_vertex = idx_next;
          gotBndEdge = true;
        }
        else if (!isPrevVisited && TT(curr_neighbor,(idx_lastV_in_face+2) % F.cols()) < 0)
        {
          next_bnd_vertex = idx_prev;
          gotBndEdge = true;
        }

        if (gotBndEdge)
        {
          changed = true;
          bnd.push_back(F(curr_neighbor,next_bnd_vertex));
          isVisited[F(curr_neighbor,next_bnd_vertex)] = true;
          break;
        }
      }
    }

    if (!changed)
      break;
  }

  b.resize(bnd.size());
  for(unsigned i=0;i<bnd.size();++i)
    b(i) = bnd[i];
}
void igl::crouzeix_raviart_cotmatrix(
  const Eigen::MatrixBase<DerivedV> & V, 
  const Eigen::MatrixBase<DerivedF> & F, 
  const Eigen::MatrixBase<DerivedE> & E,
  const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  Eigen::SparseMatrix<LT> & L)
{
  // number of rows
  const int m = F.rows();
  // Element simplex size
  const int ss = F.cols();
  // Mesh should be edge-manifold
  assert(F.cols() != 3 || is_edge_manifold(F));
  typedef Eigen::Matrix<LT,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
  MatrixXS C;
  cotmatrix_entries(V,F,C);
  Eigen::MatrixXi F2E(m,ss);
  {
    int k =0;
    for(int c = 0;c<ss;c++)
    {
      for(int f = 0;f<m;f++)
      {
        F2E(f,c) = k++;
      }
    }
  }
  // number of entries inserted per facet
  const int k = ss*(ss-1)*2;
  std::vector<Eigen::Triplet<LT> > LIJV;LIJV.reserve(k*m);
  Eigen::VectorXi LI(k),LJ(k),LV(k);
  // Compensation factor to match scales in matlab version
  double factor = 2.0;

  switch(ss)
  {
    default: assert(false && "unsupported simplex size");
    case 3:
      factor = 4.0;
      LI<<0,1,2,1,2,0,0,1,2,1,2,0;
      LJ<<1,2,0,0,1,2,0,1,2,1,2,0;
      LV<<2,0,1,2,0,1,2,0,1,2,0,1;
      break;
    case 4:
      factor *= -1.0;
      LI<<0,3,3,3,1,2,1,0,1,2,2,0,0,3,3,3,1,2,1,0,1,2,2,0;
      LJ<<1,0,1,2,2,0,0,3,3,3,1,2,0,3,3,3,1,2,1,0,1,2,2,0;
      LV<<2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1;
      break;
  }

  for(int f=0;f<m;f++)
  {
    for(int c = 0;c<k;c++)
    {
      LIJV.emplace_back(
        EMAP(F2E(f,LI(c))),
        EMAP(F2E(f,LJ(c))),
        (c<(k/2)?-1.:1.) * factor *C(f,LV(c)));
    }
  }
  L.resize(E.rows(),E.rows());
  L.setFromTriplets(LIJV.begin(),LIJV.end());
}