|
@@ -20,15 +20,13 @@ namespace igl
|
|
|
typename DerivedP,
|
|
|
typename DerivedSC,
|
|
|
typename DerivedS,
|
|
|
- typename Derivedb,
|
|
|
typename Derivedw>
|
|
|
IGL_INLINE bool shapeup_precomputation(const Eigen::PlainObjectBase<DerivedP>& P,
|
|
|
const Eigen::PlainObjectBase<DerivedSC>& SC,
|
|
|
const Eigen::PlainObjectBase<DerivedS>& S,
|
|
|
const Eigen::PlainObjectBase<DerivedS>& E,
|
|
|
- const Eigen::PlainObjectBase<Derivedb>& b,
|
|
|
+ const Eigen::PlainObjectBase<DerivedSC>& b,
|
|
|
const Eigen::PlainObjectBase<Derivedw>& w,
|
|
|
- const std::function<bool(const Eigen::PlainObjectBase<DerivedP>&, const Eigen::PlainObjectBase<DerivedSC>&, const Eigen::PlainObjectBase<DerivedS>&, Eigen::PlainObjectBase<DerivedP>&)>& local_projection,
|
|
|
ShapeupData & sudata)
|
|
|
{
|
|
|
using namespace std;
|
|
@@ -37,24 +35,24 @@ namespace igl
|
|
|
sudata.SC=SC;
|
|
|
sudata.S=S;
|
|
|
sudata.b=b;
|
|
|
- //sudata.local_projection=local_projection;
|
|
|
+ typedef typename DerivedP::Scalar Scalar;
|
|
|
|
|
|
sudata.DShape.conservativeResize(SC.sum(), P.rows()); //Shape matrix (integration);
|
|
|
sudata.DClose.conservativeResize(b.rows(), P.rows()); //Closeness matrix for positional constraints
|
|
|
sudata.DSmooth.conservativeResize(E.rows(), P.rows()); //smoothness matrix
|
|
|
|
|
|
//Building shape matrix
|
|
|
- std::vector<Triplet<double> > DShapeTriplets;
|
|
|
+ std::vector<Triplet<Scalar> > DShapeTriplets;
|
|
|
int currRow=0;
|
|
|
for (int i=0;i<S.rows();i++){
|
|
|
- double avgCoeff=1.0/(double)SC(i);
|
|
|
+ double avgCoeff=1.0/(Scalar)SC(i);
|
|
|
|
|
|
for (int j=0;j<SC(i);j++){
|
|
|
for (int k=0;k<SC(i);k++){
|
|
|
if (j==k)
|
|
|
- DShapeTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (1.0-avgCoeff)));
|
|
|
+ DShapeTriplets.push_back(Triplet<Scalar>(currRow+j, S(i,k), (1.0-avgCoeff)));
|
|
|
else
|
|
|
- DShapeTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (-avgCoeff)));
|
|
|
+ DShapeTriplets.push_back(Triplet<Scalar>(currRow+j, S(i,k), (-avgCoeff)));
|
|
|
}
|
|
|
}
|
|
|
currRow+=SC(i);
|
|
@@ -63,26 +61,25 @@ namespace igl
|
|
|
sudata.DShape.setFromTriplets(DShapeTriplets.begin(), DShapeTriplets.end());
|
|
|
|
|
|
//Building closeness matrix
|
|
|
- std::vector<Triplet<double> > DCloseTriplets;
|
|
|
+ std::vector<Triplet<Scalar> > DCloseTriplets;
|
|
|
for (int i=0;i<b.size();i++)
|
|
|
- DCloseTriplets.push_back(Triplet<double>(i,b(i), 1.0));
|
|
|
+ DCloseTriplets.push_back(Triplet<Scalar>(i,b(i), 1.0));
|
|
|
|
|
|
sudata.DClose.setFromTriplets(DCloseTriplets.begin(), DCloseTriplets.end());
|
|
|
|
|
|
//Building smoothness matrix
|
|
|
- std::vector<Triplet<double> > DSmoothTriplets;
|
|
|
+ std::vector<Triplet<Scalar> > DSmoothTriplets;
|
|
|
for (int i = 0; i < E.rows(); i++) {
|
|
|
- DSmoothTriplets.push_back(Triplet<double>(i, E(i, 0), -1));
|
|
|
- DSmoothTriplets.push_back(Triplet<double>(i, E(i, 1), 1));
|
|
|
+ DSmoothTriplets.push_back(Triplet<Scalar>(i, E(i, 0), -1));
|
|
|
+ DSmoothTriplets.push_back(Triplet<Scalar>(i, E(i, 1), 1));
|
|
|
}
|
|
|
|
|
|
- igl::cat(1, sudata.DShape, sudata.DClose, sudata.A);
|
|
|
- //is this allowed? repeating A.
|
|
|
- igl::cat(1, sudata.A, sudata.DSmooth, sudata.A);
|
|
|
- //sudata.At=sudata.A.transpose(); //to save up this expensive computation.
|
|
|
+ SparseMatrix<Scalar> tempMat;
|
|
|
+ igl::cat(1, sudata.DShape, sudata.DClose, tempMat);
|
|
|
+ igl::cat(1, tempMat, sudata.DSmooth, sudata.A);
|
|
|
|
|
|
//weight matrix
|
|
|
- vector<Triplet<double> > WTriplets;
|
|
|
+ vector<Triplet<Scalar> > WTriplets;
|
|
|
|
|
|
//one weight per set in S.
|
|
|
currRow=0;
|
|
@@ -98,23 +95,25 @@ namespace igl
|
|
|
for (int i=0;i<E.rows();i++)
|
|
|
WTriplets.push_back(Triplet<double>(SC.sum()+b.size()+i, SC.sum()+b.size()+i, sudata.smoothCoeff));
|
|
|
|
|
|
-
|
|
|
sudata.W.conservativeResize(SC.sum()+b.size()+E.rows(), SC.sum()+b.size()+E.rows());
|
|
|
sudata.W.setFromTriplets(WTriplets.begin(), WTriplets.end());
|
|
|
|
|
|
- sudata.At=sudata.A.transpose(); //for efficieny, as we use the transpose a lot in the least squares
|
|
|
+ sudata.At=sudata.A.transpose(); //for efficieny, as we use the transpose a lot in the iteration
|
|
|
sudata.Q=sudata.At*sudata.W*sudata.A;
|
|
|
-
|
|
|
+
|
|
|
return min_quad_with_fixed_precompute(sudata.Q,VectorXi(),SparseMatrix<double>(),true,sudata.solver_data);
|
|
|
}
|
|
|
|
|
|
|
|
|
template <
|
|
|
- typename Derivedbc,
|
|
|
- typename DerivedP>
|
|
|
- IGL_INLINE bool shapeup_solve(const Eigen::PlainObjectBase<Derivedbc>& bc,
|
|
|
+ typename DerivedP,
|
|
|
+ typename DerivedSC,
|
|
|
+ typename DerivedS>
|
|
|
+ IGL_INLINE bool shapeup_solve(const Eigen::PlainObjectBase<DerivedP>& bc,
|
|
|
+ const std::function<bool(const Eigen::PlainObjectBase<DerivedP>&, const Eigen::PlainObjectBase<DerivedSC>&, const Eigen::PlainObjectBase<DerivedS>&, Eigen::PlainObjectBase<DerivedP>&)>& local_projection,
|
|
|
const Eigen::PlainObjectBase<DerivedP>& P0,
|
|
|
const ShapeupData & sudata,
|
|
|
+ const bool quiet,
|
|
|
Eigen::PlainObjectBase<DerivedP>& P)
|
|
|
{
|
|
|
using namespace Eigen;
|
|
@@ -125,30 +124,33 @@ namespace igl
|
|
|
MatrixXd rhs(sudata.A.rows(), 3); rhs.setZero();
|
|
|
rhs.block(sudata.DShape.rows(), 0, sudata.b.rows(),3)=bc; //this stays constant throughout the iterations
|
|
|
|
|
|
+ if (!quiet){
|
|
|
+ cout<<"Shapeup Iterations, "<<sudata.DShape.rows()<<" constraints, solution size "<<P0.size()<<endl;
|
|
|
+ cout<<"**********************************************************************************************"<<endl;
|
|
|
+ }
|
|
|
projP.conservativeResize(sudata.SC.rows(), 3*sudata.SC.maxCoeff());
|
|
|
- for (int i=0;i<sudata.maxIterations;i++){
|
|
|
+ for (int iter=0;iter<sudata.maxIterations;iter++){
|
|
|
+
|
|
|
+ local_projection(currP, sudata.SC,sudata.S,projP);
|
|
|
|
|
|
- for (int j=0;j<sudata.SC.rows();j++)
|
|
|
- sudata.local_projection(currP, sudata.SC,sudata.S,projP);
|
|
|
//constructing the projection part of the (DShape rows of the) right hand side
|
|
|
int currRow=0;
|
|
|
- for (int i=0;i<sudata.S.rows();i++){
|
|
|
- for (int j=0;j<sudata.SC(i);j++){
|
|
|
+ for (int i=0;i<sudata.S.rows();i++)
|
|
|
+ for (int j=0;j<sudata.SC(i);j++)
|
|
|
rhs.row(currRow++)=projP.block(i, 3*j, 1,3);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //the global solve is independent per dimension
|
|
|
+
|
|
|
Eigen::PlainObjectBase<DerivedP> lsrhs=-sudata.At*sudata.W*rhs;
|
|
|
- min_quad_with_fixed_solve(sudata.solver_data, rhs,Eigen::PlainObjectBase<DerivedP>(),Eigen::PlainObjectBase<DerivedP>(), currP);
|
|
|
+ MatrixXd Y(0,3), Beq(0,3);
|
|
|
+ min_quad_with_fixed_solve(sudata.solver_data, lsrhs,Y,Beq,currP);
|
|
|
|
|
|
double currChange=(currP-prevP).lpNorm<Infinity>();
|
|
|
- cout << "currChange: " << currChange << endl;
|
|
|
+ if (!quiet)
|
|
|
+ cout << "Iteration "<<iter<<", integration Linf error: "<<currChange<< endl;
|
|
|
prevP=currP;
|
|
|
if (currChange<sudata.pTolerance)
|
|
|
break;
|
|
|
-
|
|
|
}
|
|
|
+ P=currP;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
@@ -158,7 +160,7 @@ namespace igl
|
|
|
|
|
|
|
|
|
#ifdef IGL_STATIC_LIBRARY
|
|
|
-template bool igl::shapeup_precomputation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, const std::function<bool(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, const Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, const Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& ) >& local_projection, igl::ShapeupData&);
|
|
|
+template bool igl::shapeup_precomputation< typename Eigen::Matrix<double, -1, -1, 0, -1, -1>, typename Eigen::Matrix<int, -1, 1, 0, -1, 1>, typename Eigen::Matrix<int, -1, -1, 0, -1, -1>, typename Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, igl::ShapeupData&);
|
|
|
|
|
|
-template bool igl::shapeup_solve<typename Eigen::Matrix<double, -1, -1, 0, -1, -1>, typename Eigen::Matrix<double, -1, -1, 0, -1, -1> >(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& bc, const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& P0, const igl::ShapeupData & sudata, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& P);
|
|
|
+template bool igl::shapeup_solve<typename Eigen::Matrix<double, -1, -1, 0, -1, -1>, typename Eigen::Matrix<int, -1, 1, 0, -1, 1>, typename Eigen::Matrix<int, -1, -1, 0, -1, -1> >(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& bc, const std::function<bool(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, const Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, const Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& ) >& local_projection, const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& P0, const igl::ShapeupData & sudata, const bool quiet, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >& P);
|
|
|
#endif
|