Пример #1
0
IGL_INLINE void igl::jet(
  const Eigen::PlainObjectBase<DerivedZ> & Z,
  const bool normalize,
  Eigen::PlainObjectBase<DerivedC> & C)
{
  const double min_z = (normalize?Z.minCoeff():0);
  const double max_z = (normalize?Z.maxCoeff():-1);
  return jet(Z,min_z,max_z,C);
}
Пример #2
0
IGL_INLINE void igl::slice(
  const Eigen::PlainObjectBase<DerivedX> & X,
  const Eigen::PlainObjectBase<DerivedR> & R,
  const Eigen::PlainObjectBase<DerivedC> & C,
  Eigen::PlainObjectBase<DerivedY> & Y)
{
#ifndef NDEBUG
  int xm = X.rows();
  int xn = X.cols();
#endif
  int ym = R.size();
  int yn = C.size();

  // special case when R or C is empty
  if(ym == 0 || yn == 0)
  {
    Y.resize(ym,yn);
    return;
  }

  assert(R.minCoeff() >= 0);
  assert(R.maxCoeff() < xm);
  assert(C.minCoeff() >= 0);
  assert(C.maxCoeff() < xn);

  // Resize output
  Y.resize(ym,yn);
  // loop over output rows, then columns
  for(int i = 0;i<ym;i++)
  {
    for(int j = 0;j<yn;j++)
    {
      Y(i,j) = X(R(i),C(j));
    }
  }
}
Пример #3
0
IGL_INLINE bool igl::arap_precomputation(
    const Eigen::PlainObjectBase<DerivedV> & V,
    const Eigen::PlainObjectBase<DerivedF> & F,
    const int dim,
    const Eigen::PlainObjectBase<Derivedb> & b,
    ARAPData & data)
{
    using namespace std;
    using namespace Eigen;
    typedef typename DerivedV::Scalar Scalar;
    // number of vertices
    const int n = V.rows();
    data.n = n;
    assert((b.size() == 0 || b.maxCoeff() < n) && "b out of bounds");
    assert((b.size() == 0 || b.minCoeff() >=0) && "b out of bounds");
    // remember b
    data.b = b;
    //assert(F.cols() == 3 && "For now only triangles");
    // dimension
    //const int dim = V.cols();
    assert((dim == 3 || dim ==2) && "dim should be 2 or 3");
    data.dim = dim;
    //assert(dim == 3 && "Only 3d supported");
    // Defaults
    data.f_ext = MatrixXd::Zero(n,data.dim);

    assert(data.dim <= V.cols() && "solve dim should be <= embedding");
    bool flat = (V.cols() - data.dim)==1;

    DerivedV plane_V;
    DerivedF plane_F;
    typedef SparseMatrix<Scalar> SparseMatrixS;
    SparseMatrixS ref_map,ref_map_dim;
    if(flat)
    {
        project_isometrically_to_plane(V,F,plane_V,plane_F,ref_map);
        repdiag(ref_map,dim,ref_map_dim);
    }
    const PlainObjectBase<DerivedV>& ref_V = (flat?plane_V:V);
    const PlainObjectBase<DerivedF>& ref_F = (flat?plane_F:F);
    SparseMatrixS L;
    cotmatrix(V,F,L);

    ARAPEnergyType eff_energy = data.energy;
    if(eff_energy == ARAP_ENERGY_TYPE_DEFAULT)
    {
        switch(F.cols())
        {
        case 3:
            if(data.dim == 3)
            {
                eff_energy = ARAP_ENERGY_TYPE_SPOKES_AND_RIMS;
            } else
            {
                eff_energy = ARAP_ENERGY_TYPE_ELEMENTS;
            }
            break;
        case 4:
            eff_energy = ARAP_ENERGY_TYPE_ELEMENTS;
            break;
        default:
            assert(false);
        }
    }


    // Get covariance scatter matrix, when applied collects the covariance
    // matrices used to fit rotations to during optimization
    covariance_scatter_matrix(ref_V,ref_F,eff_energy,data.CSM);
    if(flat)
    {
        data.CSM = (data.CSM * ref_map_dim.transpose()).eval();
    }
    assert(data.CSM.cols() == V.rows()*data.dim);

    // Get group sum scatter matrix, when applied sums all entries of the same
    // group according to G
    SparseMatrix<double> G_sum;
    if(data.G.size() == 0)
    {
        if(eff_energy == ARAP_ENERGY_TYPE_ELEMENTS)
        {
            speye(F.rows(),G_sum);
        } else
        {
            speye(n,G_sum);
        }
    } else
    {
        // groups are defined per vertex, convert to per face using mode
        if(eff_energy == ARAP_ENERGY_TYPE_ELEMENTS)
        {
            Eigen::Matrix<int,Eigen::Dynamic,1> GG;
            MatrixXi GF(F.rows(),F.cols());
            for(int j = 0; j<F.cols(); j++)
            {
                Matrix<int,Eigen::Dynamic,1> GFj;
                slice(data.G,F.col(j),GFj);
                GF.col(j) = GFj;
            }
            mode<int>(GF,2,GG);
            data.G=GG;
        }
        //printf("group_sum_matrix()\n");
        group_sum_matrix(data.G,G_sum);
    }
    SparseMatrix<double> G_sum_dim;
    repdiag(G_sum,data.dim,G_sum_dim);
    assert(G_sum_dim.cols() == data.CSM.rows());
    data.CSM = (G_sum_dim * data.CSM).eval();


    arap_rhs(ref_V,ref_F,data.dim,eff_energy,data.K);
    if(flat)
    {
        data.K = (ref_map_dim * data.K).eval();
    }
    assert(data.K.rows() == data.n*data.dim);

    SparseMatrix<double> Q = (-L).eval();

    if(data.with_dynamics)
    {
        const double h = data.h;
        assert(h != 0);
        SparseMatrix<double> M;
        massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,data.M);
        const double dw = (1./data.ym)*(h*h);
        SparseMatrix<double> DQ = dw * 1./(h*h)*data.M;
        Q += DQ;
        // Dummy external forces
        data.f_ext = MatrixXd::Zero(n,data.dim);
        data.vel = MatrixXd::Zero(n,data.dim);
    }

    return min_quad_with_fixed_precompute(
               Q,b,SparseMatrix<double>(),true,data.solver_data);
}