Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
igl::copyleft Namespace Reference

Namespaces

namespace  cgal
 
namespace  comiso
 
namespace  cork
 
namespace  tetgen
 

Functions

template<typename Derivedvalues , typename Derivedpoints , typename Derivedvertices , typename DerivedF >
IGL_INLINE void marching_cubes (const Eigen::PlainObjectBase< Derivedvalues > &values, const Eigen::PlainObjectBase< Derivedpoints > &points, const unsigned x_res, const unsigned y_res, const unsigned z_res, Eigen::PlainObjectBase< Derivedvertices > &vertices, Eigen::PlainObjectBase< DerivedF > &faces)
 
template<typename DerivedV , typename DerivedF , typename isolevelType , typename DerivedSV , typename DerivedSF , typename DerivedGV , typename Derivedside , typename DerivedS >
void offset_surface (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const isolevelType isolevel, const typename Derivedside::Scalar s, const SignedDistanceType &signed_distance_type, Eigen::PlainObjectBase< DerivedSV > &SV, Eigen::PlainObjectBase< DerivedSF > &SF, Eigen::PlainObjectBase< DerivedGV > &GV, Eigen::PlainObjectBase< Derivedside > &side, Eigen::PlainObjectBase< DerivedS > &S)
 
IGL_INLINE bool progressive_hulls (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J)
 
IGL_INLINE void progressive_hulls_cost_and_placement (const int e, const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double &cost, Eigen::RowVectorXd &p)
 
IGL_INLINE bool quadprog (const Eigen::MatrixXd &G, const Eigen::VectorXd &g0, const Eigen::MatrixXd &CE, const Eigen::VectorXd &ce0, const Eigen::MatrixXd &CI, const Eigen::VectorXd &ci0, Eigen::VectorXd &x)
 
IGL_INLINE void swept_volume (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< Eigen::Affine3d(const double t)> &transform, const size_t steps, const size_t grid_res, const size_t isolevel, Eigen::MatrixXd &SV, Eigen::MatrixXi &SF)
 

Function Documentation

◆ marching_cubes()

template<typename Derivedvalues , typename Derivedpoints , typename Derivedvertices , typename DerivedF >
IGL_INLINE void igl::copyleft::marching_cubes ( const Eigen::PlainObjectBase< Derivedvalues > &  values,
const Eigen::PlainObjectBase< Derivedpoints > &  points,
const unsigned  x_res,
const unsigned  y_res,
const unsigned  z_res,
Eigen::PlainObjectBase< Derivedvertices > &  vertices,
Eigen::PlainObjectBase< DerivedF > &  faces 
)
236{
238 points,
239 x_res,
240 y_res,
241 z_res,
242 vertices,
243 faces);
244}
Definition marching_cubes.cpp:61

Referenced by offset_surface(), and swept_volume().

+ Here is the caller graph for this function:

◆ offset_surface()

template<typename DerivedV , typename DerivedF , typename isolevelType , typename DerivedSV , typename DerivedSF , typename DerivedGV , typename Derivedside , typename DerivedS >
void igl::copyleft::offset_surface ( const Eigen::MatrixBase< DerivedV > &  V,
const Eigen::MatrixBase< DerivedF > &  F,
const isolevelType  isolevel,
const typename Derivedside::Scalar  s,
const SignedDistanceType signed_distance_type,
Eigen::PlainObjectBase< DerivedSV > &  SV,
Eigen::PlainObjectBase< DerivedSF > &  SF,
Eigen::PlainObjectBase< DerivedGV > &  GV,
Eigen::PlainObjectBase< Derivedside > &  side,
Eigen::PlainObjectBase< DerivedS > &  S 
)
28{
29 typedef typename DerivedV::Scalar Scalar;
30 typedef typename DerivedF::Scalar Index;
31 {
33 typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
34 assert(V.cols() == 3 && "V must contain positions in 3D");
35 RowVector3S min_ext = V.colwise().minCoeff().array() - isolevel;
36 RowVector3S max_ext = V.colwise().maxCoeff().array() + isolevel;
37 box.extend(min_ext.transpose());
38 box.extend(max_ext.transpose());
39 igl::voxel_grid(box,s,1,GV,side);
40 }
41
42 const Scalar h =
43 (GV.col(0).maxCoeff()-GV.col(0).minCoeff())/((Scalar)(side(0)-1));
44 const Scalar lower_bound = isolevel-sqrt(3.0)*h;
45 const Scalar upper_bound = isolevel+sqrt(3.0)*h;
46 {
50 GV,V,F,signed_distance_type,lower_bound,upper_bound,S,I,C,N);
51 }
52 igl::flood_fill(side,S);
53
54 DerivedS SS = S.array()-isolevel;
55 igl::copyleft::marching_cubes(SS,GV,side(0),side(1),side(2),SV,SF);
56}
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition ArrayCwiseUnaryOps.h:152
EIGEN_DEVICE_FUNC ConstColwiseReturnType colwise() const
Definition DenseBase.h:516
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:180
EIGEN_DEVICE_FUNC const MinCoeffReturnType minCoeff() const
Definition VectorwiseOp.h:304
EIGEN_DEVICE_FUNC const MaxCoeffReturnType maxCoeff() const
Definition VectorwiseOp.h:317
EIGEN_DEVICE_FUNC AlignedBox & extend(const MatrixBase< Derived > &p)
Definition AlignedBox.h:200
An axis aligned box.
Definition AlignedBox.h:31
IGL_INLINE void marching_cubes(const Eigen::PlainObjectBase< Derivedvalues > &values, const Eigen::PlainObjectBase< Derivedpoints > &points, const unsigned x_res, const unsigned y_res, const unsigned z_res, Eigen::PlainObjectBase< Derivedvertices > &vertices, Eigen::PlainObjectBase< DerivedF > &faces)
Definition marching_cubes.cpp:228
IGL_INLINE void flood_fill(const Eigen::MatrixBase< Derivedres > &res, Eigen::PlainObjectBase< DerivedS > &S)
Definition flood_fill.cpp:12
IGL_INLINE void signed_distance(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C, Eigen::PlainObjectBase< DerivedN > &N)
Definition signed_distance.cpp:26
IGL_INLINE void voxel_grid(const Eigen::AlignedBox< Scalar, 3 > &box, const int s, const int pad_count, Eigen::PlainObjectBase< DerivedGV > &GV, Eigen::PlainObjectBase< Derivedside > &side)
Definition voxel_grid.cpp:15

References Eigen::DenseBase< Derived >::colwise(), Eigen::AlignedBox< _Scalar, _AmbientDim >::extend(), igl::flood_fill(), marching_cubes(), Eigen::VectorwiseOp< ExpressionType, Direction >::maxCoeff(), Eigen::VectorwiseOp< ExpressionType, Direction >::minCoeff(), igl::signed_distance(), sqrt(), and igl::voxel_grid().

+ Here is the call graph for this function:

◆ progressive_hulls()

IGL_INLINE bool igl::copyleft::progressive_hulls ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const size_t  max_m,
Eigen::MatrixXd &  U,
Eigen::MatrixXi &  G,
Eigen::VectorXi &  J 
)
19{
20 int m = F.rows();
21 Eigen::VectorXi I;
22 return decimate(
23 V,
24 F,
25 progressive_hulls_cost_and_placement,
26 max_faces_stopping_condition(m,(const int)m,max_m),
27 U,
28 G,
29 J,
30 I);
31}
IGL_INLINE void max_faces_stopping_condition(int &m, const int orig_m, const int max_m, std::function< bool(const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set< std::pair< double, int > > &, const std::vector< std::set< std::pair< double, int > >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> &stopping_condition)
Definition max_faces_stopping_condition.cpp:10
IGL_INLINE bool decimate(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const size_t max_m, Eigen::MatrixXd &U, Eigen::MatrixXi &G, Eigen::VectorXi &J, Eigen::VectorXi &I)
Definition decimate.cpp:19

References igl::decimate(), igl::max_faces_stopping_condition(), and progressive_hulls_cost_and_placement().

+ Here is the call graph for this function:

◆ progressive_hulls_cost_and_placement()

IGL_INLINE void igl::copyleft::progressive_hulls_cost_and_placement ( const int  e,
const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXi &  E,
const Eigen::VectorXi &  EMAP,
const Eigen::MatrixXi &  EF,
const Eigen::MatrixXi &  EI,
double &  cost,
Eigen::RowVectorXd &  p 
)
26{
27 using namespace Eigen;
28 using namespace std;
29 // Controls the amount of quadratic energy to add (too small will introduce
30 // instabilities and flaps)
31 const double w = 0.1;
32
33 assert(V.cols() == 3 && "V.cols() should be 3");
34 // Gather list of unique face neighbors
35 vector<int> Nall = circulation(e, true,F,E,EMAP,EF,EI);
36 vector<int> Nother= circulation(e,false,F,E,EMAP,EF,EI);
37 Nall.insert(Nall.end(),Nother.begin(),Nother.end());
38 vector<int> N;
39 igl::unique(Nall,N);
40 // Gather:
41 // A #N by 3 normals scaled by area,
42 // D #N determinants of matrix formed by points as columns
43 // B #N point on plane dot normal
44 MatrixXd A(N.size(),3);
45 VectorXd D(N.size());
46 VectorXd B(N.size());
47 //cout<<"N=[";
48 for(int i = 0;i<N.size();i++)
49 {
50 const int f = N[i];
51 //cout<<(f+1)<<" ";
52 const RowVector3d & v01 = V.row(F(f,1))-V.row(F(f,0));
53 const RowVector3d & v20 = V.row(F(f,2))-V.row(F(f,0));
54 A.row(i) = v01.cross(v20);
55 B(i) = V.row(F(f,0)).dot(A.row(i));
56 D(i) =
57 (Matrix3d()<< V.row(F(f,0)), V.row(F(f,1)), V.row(F(f,2)))
58 .finished().determinant();
59 }
60 //cout<<"];"<<endl;
61 // linear objective
62 Vector3d f = A.colwise().sum().transpose();
63 VectorXd x;
64 //bool success = linprog(f,-A,-B,MatrixXd(0,A.cols()),VectorXd(0,1),x);
65 //VectorXd _;
66 //bool success = mosek_linprog(f,A.sparseView(),B,_,_,_,env,x);
67 //if(success)
68 //{
69 // cost = (1./6.)*(x.dot(f) - D.sum());
70 //}
71 bool success = false;
72 {
73 RowVectorXd mid = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
74 MatrixXd G = w*Matrix3d::Identity(3,3);
75 VectorXd g0 = (1.-w)*f - w*mid.transpose();
76 const int n = A.cols();
77 success = quadprog(
78 G,g0,
79 MatrixXd(n,0),VectorXd(0,1),
80 A.transpose(),-B,x);
81 cost = (1.-w)*(1./6.)*(x.dot(f) - D.sum()) +
82 w*(x.transpose()-mid).squaredNorm() +
83 w*(V.row(E(e,0))-V.row(E(e,1))).norm();
84 }
85
86 // A x >= B
87 // A x - B >=0
88 // This is annoyingly necessary. Seems the solver is letting some garbage
89 // slip by.
90 success = success && ((A*x-B).minCoeff()>-1e-10);
91 if(success)
92 {
93 p = x.transpose();
94 //assert(cost>=0 && "Cost should be positive");
95 }else
96 {
97 cost = std::numeric_limits<double>::infinity();
98 //VectorXi NM;
99 //igl::list_to_matrix(N,NM);
100 //cout<<matlab_format((NM.array()+1).eval(),"N")<<endl;
101 //cout<<matlab_format(f,"f")<<endl;
102 //cout<<matlab_format(A,"A")<<endl;
103 //cout<<matlab_format(B,"B")<<endl;
104 //exit(-1);
105 p = RowVectorXd::Constant(1,3,std::nan("inf-cost"));
106 }
107}
Definition LDLT.h:16
IGL_INLINE std::vector< int > circulation(const int e, const bool ccw, const Eigen::MatrixXi &F, const Eigen::MatrixXi &E, const Eigen::VectorXi &EMAP, const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI)
Definition circulation.cpp:11
IGL_INLINE void unique(const std::vector< T > &A, std::vector< T > &C, std::vector< size_t > &IA, std::vector< size_t > &IC)
Definition unique.cpp:21
STL namespace.

References igl::circulation(), quadprog(), and igl::unique().

Referenced by progressive_hulls().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ quadprog()

IGL_INLINE bool igl::copyleft::quadprog ( const Eigen::MatrixXd &  G,
const Eigen::VectorXd &  g0,
const Eigen::MatrixXd &  CE,
const Eigen::VectorXd &  ce0,
const Eigen::MatrixXd &  CI,
const Eigen::VectorXd &  ci0,
Eigen::VectorXd &  x 
)
92{
93 using namespace Eigen;
94 typedef double Scalar;
95 const auto distance = [](Scalar a, Scalar b)->Scalar
96 {
97 Scalar a1, b1, t;
98 a1 = std::abs(a);
99 b1 = std::abs(b);
100 if (a1 > b1)
101 {
102 t = (b1 / a1);
103 return a1 * std::sqrt(1.0 + t * t);
104 }
105 else
106 if (b1 > a1)
107 {
108 t = (a1 / b1);
109 return b1 * std::sqrt(1.0 + t * t);
110 }
111 return a1 * std::sqrt(2.0);
112 };
113 const auto compute_d = [](VectorXd &d, const MatrixXd& J, const VectorXd& np)
114 {
115 d = J.adjoint() * np;
116 };
117
118 const auto update_z =
119 [](VectorXd& z, const MatrixXd& J, const VectorXd& d, int iq)
120 {
121 z = J.rightCols(z.size()-iq) * d.tail(d.size()-iq);
122 };
123
124 const auto update_r =
125 [](const MatrixXd& R, VectorXd& r, const VectorXd& d, int iq)
126 {
127 r.head(iq) =
128 R.topLeftCorner(iq,iq).triangularView<Upper>().solve(d.head(iq));
129 };
130
131 const auto add_constraint = [&distance](
132 MatrixXd& R,
133 MatrixXd& J,
134 VectorXd& d,
135 int& iq,
136 double& R_norm)->bool
137 {
138 int n=J.rows();
139#ifdef TRACE_SOLVER
140 std::cerr << "Add constraint " << iq << '/';
141#endif
142 int i, j, k;
143 double cc, ss, h, t1, t2, xny;
144
145 /* we have to find the Givens rotation which will reduce the element
146 d(j) to zero.
147 if it is already zero we don't have to do anything, except of
148 decreasing j */
149 for (j = n - 1; j >= iq + 1; j--)
150 {
151 /* The Givens rotation is done with the matrix (cc cs, cs -cc).
152 If cc is one, then element (j) of d is zero compared with element
153 (j - 1). Hence we don't have to do anything.
154 If cc is zero, then we just have to switch column (j) and column (j - 1)
155 of J. Since we only switch columns in J, we have to be careful how we
156 update d depending on the sign of gs.
157 Otherwise we have to apply the Givens rotation to these columns.
158 The i - 1 element of d has to be updated to h. */
159 cc = d(j - 1);
160 ss = d(j);
161 h = distance(cc, ss);
162 if (h == 0.0)
163 continue;
164 d(j) = 0.0;
165 ss = ss / h;
166 cc = cc / h;
167 if (cc < 0.0)
168 {
169 cc = -cc;
170 ss = -ss;
171 d(j - 1) = -h;
172 }
173 else
174 d(j - 1) = h;
175 xny = ss / (1.0 + cc);
176 for (k = 0; k < n; k++)
177 {
178 t1 = J(k,j - 1);
179 t2 = J(k,j);
180 J(k,j - 1) = t1 * cc + t2 * ss;
181 J(k,j) = xny * (t1 + J(k,j - 1)) - t2;
182 }
183 }
184 /* update the number of constraints added*/
185 iq++;
186 /* To update R we have to put the iq components of the d vector
187 into column iq - 1 of R
188 */
189 R.col(iq-1).head(iq) = d.head(iq);
190#ifdef TRACE_SOLVER
191 std::cerr << iq << std::endl;
192#endif
193
194 if (std::abs(d(iq - 1)) <= std::numeric_limits<double>::epsilon() * R_norm)
195 {
196 // problem degenerate
197 return false;
198 }
199 R_norm = std::max<double>(R_norm, std::abs(d(iq - 1)));
200 return true;
201 };
202
203 const auto delete_constraint = [&distance](
204 MatrixXd& R,
205 MatrixXd& J,
206 VectorXi& A,
207 VectorXd& u,
208 int p,
209 int& iq,
210 int l)
211 {
212 int n = R.rows();
213#ifdef TRACE_SOLVER
214 std::cerr << "Delete constraint " << l << ' ' << iq;
215#endif
216 int i, j, k, qq;
217 double cc, ss, h, xny, t1, t2;
218
219 /* Find the index qq for active constraint l to be removed */
220 for (i = p; i < iq; i++)
221 if (A(i) == l)
222 {
223 qq = i;
224 break;
225 }
226
227 /* remove the constraint from the active set and the duals */
228 for (i = qq; i < iq - 1; i++)
229 {
230 A(i) = A(i + 1);
231 u(i) = u(i + 1);
232 R.col(i) = R.col(i+1);
233 }
234
235 A(iq - 1) = A(iq);
236 u(iq - 1) = u(iq);
237 A(iq) = 0;
238 u(iq) = 0.0;
239 for (j = 0; j < iq; j++)
240 R(j,iq - 1) = 0.0;
241 /* constraint has been fully removed */
242 iq--;
243#ifdef TRACE_SOLVER
244 std::cerr << '/' << iq << std::endl;
245#endif
246
247 if (iq == 0)
248 return;
249
250 for (j = qq; j < iq; j++)
251 {
252 cc = R(j,j);
253 ss = R(j + 1,j);
254 h = distance(cc, ss);
255 if (h == 0.0)
256 continue;
257 cc = cc / h;
258 ss = ss / h;
259 R(j + 1,j) = 0.0;
260 if (cc < 0.0)
261 {
262 R(j,j) = -h;
263 cc = -cc;
264 ss = -ss;
265 }
266 else
267 R(j,j) = h;
268
269 xny = ss / (1.0 + cc);
270 for (k = j + 1; k < iq; k++)
271 {
272 t1 = R(j,k);
273 t2 = R(j + 1,k);
274 R(j,k) = t1 * cc + t2 * ss;
275 R(j + 1,k) = xny * (t1 + R(j,k)) - t2;
276 }
277 for (k = 0; k < n; k++)
278 {
279 t1 = J(k,j);
280 t2 = J(k,j + 1);
281 J(k,j) = t1 * cc + t2 * ss;
282 J(k,j + 1) = xny * (J(k,j) + t1) - t2;
283 }
284 }
285 };
286
287 int i, j, k, l; /* indices */
288 int ip, me, mi;
289 int n=g0.size(); int p=ce0.size(); int m=ci0.size();
290 MatrixXd R(G.rows(),G.cols()), J(G.rows(),G.cols());
291
292 LLT<MatrixXd,Lower> chol(G.cols());
293
294 VectorXd s(m+p), z(n), r(m + p), d(n), np(n), u(m + p);
295 VectorXd x_old(n), u_old(m + p);
296 double f_value, psi, c1, c2, sum, ss, R_norm;
297 const double inf = std::numeric_limits<double>::infinity();
298 double t, t1, t2; /* t is the step length, which is the minimum of the partial step length t1
299 * and the full step length t2 */
300 VectorXi A(m + p), A_old(m + p), iai(m + p);
301 int q;
302 int iq, iter = 0;
303 std::vector<bool> iaexcl(m + p);
304
305 me = p; /* number of equality constraints */
306 mi = m; /* number of inequality constraints */
307 q = 0; /* size of the active set A (containing the indices of the active constraints) */
308
309 /*
310 * Preprocessing phase
311 */
312
313 /* compute the trace of the original matrix G */
314 c1 = G.trace();
315
316 /* decompose the matrix G in the form LL^T */
317 chol.compute(G);
318
319 /* initialize the matrix R */
320 d.setZero();
321 R.setZero();
322 R_norm = 1.0; /* this variable will hold the norm of the matrix R */
323
324 /* compute the inverse of the factorized matrix G^-1, this is the initial value for H */
325 // J = L^-T
326 J.setIdentity();
327 J = chol.matrixU().solve(J);
328 c2 = J.trace();
329#ifdef TRACE_SOLVER
330 print_matrix("J", J, n);
331#endif
332
333 /* c1 * c2 is an estimate for cond(G) */
334
335 /*
336 * Find the unconstrained minimizer of the quadratic form 0.5 * x G x + g0 x
337 * this is a feasible point in the dual space
338 * x = G^-1 * g0
339 */
340 x = chol.solve(g0);
341 x = -x;
342 /* and compute the current solution value */
343 f_value = 0.5 * g0.dot(x);
344#ifdef TRACE_SOLVER
345 std::cerr << "Unconstrained solution: " << f_value << std::endl;
346 print_vector("x", x, n);
347#endif
348
349 /* Add equality constraints to the working set A */
350 iq = 0;
351 for (i = 0; i < me; i++)
352 {
353 np = CE.col(i);
354 compute_d(d, J, np);
355 update_z(z, J, d, iq);
356 update_r(R, r, d, iq);
357#ifdef TRACE_SOLVER
358 print_matrix("R", R, iq);
359 print_vector("z", z, n);
360 print_vector("r", r, iq);
361 print_vector("d", d, n);
362#endif
363
364 /* compute full step length t2: i.e., the minimum step in primal space s.t. the contraint
365 becomes feasible */
366 t2 = 0.0;
367 if (std::abs(z.dot(z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
368 t2 = (-np.dot(x) - ce0(i)) / z.dot(np);
369
370 x += t2 * z;
371
372 /* set u = u+ */
373 u(iq) = t2;
374 u.head(iq) -= t2 * r.head(iq);
375
376 /* compute the new solution value */
377 f_value += 0.5 * (t2 * t2) * z.dot(np);
378 A(i) = -i - 1;
379
380 if (!add_constraint(R, J, d, iq, R_norm))
381 {
382 // FIXME: it should raise an error
383 // Equality constraints are linearly dependent
384 return false;
385 }
386 }
387
388 /* set iai = K \ A */
389 for (i = 0; i < mi; i++)
390 iai(i) = i;
391
392l1: iter++;
393#ifdef TRACE_SOLVER
394 print_vector("x", x, n);
395#endif
396 /* step 1: choose a violated constraint */
397 for (i = me; i < iq; i++)
398 {
399 ip = A(i);
400 iai(ip) = -1;
401 }
402
403 /* compute s(x) = ci^T * x + ci0 for all elements of K \ A */
404 ss = 0.0;
405 psi = 0.0; /* this value will contain the sum of all infeasibilities */
406 ip = 0; /* ip will be the index of the chosen violated constraint */
407 for (i = 0; i < mi; i++)
408 {
409 iaexcl[i] = true;
410 sum = CI.col(i).dot(x) + ci0(i);
411 s(i) = sum;
412 psi += std::min(0.0, sum);
413 }
414#ifdef TRACE_SOLVER
415 print_vector("s", s, mi);
416#endif
417
418
419 if (std::abs(psi) <= mi * std::numeric_limits<double>::epsilon() * c1 * c2* 100.0)
420 {
421 /* numerically there are not infeasibilities anymore */
422 q = iq;
423 return true;
424 }
425
426 /* save old values for u, x and A */
427 u_old.head(iq) = u.head(iq);
428 A_old.head(iq) = A.head(iq);
429 x_old = x;
430
431l2: /* Step 2: check for feasibility and determine a new S-pair */
432 for (i = 0; i < mi; i++)
433 {
434 if (s(i) < ss && iai(i) != -1 && iaexcl[i])
435 {
436 ss = s(i);
437 ip = i;
438 }
439 }
440 if (ss >= 0.0)
441 {
442 q = iq;
443 return true;
444 }
445
446 /* set np = n(ip) */
447 np = CI.col(ip);
448 /* set u = (u 0)^T */
449 u(iq) = 0.0;
450 /* add ip to the active set A */
451 A(iq) = ip;
452
453#ifdef TRACE_SOLVER
454 std::cerr << "Trying with constraint " << ip << std::endl;
455 print_vector("np", np, n);
456#endif
457
458l2a:/* Step 2a: determine step direction */
459 /* compute z = H np: the step direction in the primal space (through J, see the paper) */
460 compute_d(d, J, np);
461 update_z(z, J, d, iq);
462 /* compute N* np (if q > 0): the negative of the step direction in the dual space */
463 update_r(R, r, d, iq);
464#ifdef TRACE_SOLVER
465 std::cerr << "Step direction z" << std::endl;
466 print_vector("z", z, n);
467 print_vector("r", r, iq + 1);
468 print_vector("u", u, iq + 1);
469 print_vector("d", d, n);
470 print_ivector("A", A, iq + 1);
471#endif
472
473 /* Step 2b: compute step length */
474 l = 0;
475 /* Compute t1: partial step length (maximum step in dual space without violating dual feasibility */
476 t1 = inf; /* +inf */
477 /* find the index l s.t. it reaches the minimum of u+(x) / r */
478 for (k = me; k < iq; k++)
479 {
480 double tmp;
481 if (r(k) > 0.0 && ((tmp = u(k) / r(k)) < t1) )
482 {
483 t1 = tmp;
484 l = A(k);
485 }
486 }
487 /* Compute t2: full step length (minimum step in primal space such that the constraint ip becomes feasible */
488 if (std::abs(z.dot(z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
489 t2 = -s(ip) / z.dot(np);
490 else
491 t2 = inf; /* +inf */
492
493 /* the step is chosen as the minimum of t1 and t2 */
494 t = std::min(t1, t2);
495#ifdef TRACE_SOLVER
496 std::cerr << "Step sizes: " << t << " (t1 = " << t1 << ", t2 = " << t2 << ") ";
497#endif
498
499 /* Step 2c: determine new S-pair and take step: */
500
501 /* case (i): no step in primal or dual space */
502 if (t >= inf)
503 {
504 /* QPP is infeasible */
505 // FIXME: unbounded to raise
506 q = iq;
507 return false;
508 }
509 /* case (ii): step in dual space */
510 if (t2 >= inf)
511 {
512 /* set u = u + t * [-r 1) and drop constraint l from the active set A */
513 u.head(iq) -= t * r.head(iq);
514 u(iq) += t;
515 iai(l) = l;
516 delete_constraint(R, J, A, u, p, iq, l);
517#ifdef TRACE_SOLVER
518 std::cerr << " in dual space: "
519 << f_value << std::endl;
520 print_vector("x", x, n);
521 print_vector("z", z, n);
522 print_ivector("A", A, iq + 1);
523#endif
524 goto l2a;
525 }
526
527 /* case (iii): step in primal and dual space */
528
529 x += t * z;
530 /* update the solution value */
531 f_value += t * z.dot(np) * (0.5 * t + u(iq));
532
533 u.head(iq) -= t * r.head(iq);
534 u(iq) += t;
535#ifdef TRACE_SOLVER
536 std::cerr << " in both spaces: "
537 << f_value << std::endl;
538 print_vector("x", x, n);
539 print_vector("u", u, iq + 1);
540 print_vector("r", r, iq + 1);
541 print_ivector("A", A, iq + 1);
542#endif
543
544 if (t == t2)
545 {
546#ifdef TRACE_SOLVER
547 std::cerr << "Full step has taken " << t << std::endl;
548 print_vector("x", x, n);
549#endif
550 /* full step has taken */
551 /* add constraint ip to the active set*/
552 if (!add_constraint(R, J, d, iq, R_norm))
553 {
554 iaexcl[ip] = false;
555 delete_constraint(R, J, A, u, p, iq, ip);
556#ifdef TRACE_SOLVER
557 print_matrix("R", R, n);
558 print_ivector("A", A, iq);
559#endif
560 for (i = 0; i < m; i++)
561 iai(i) = i;
562 for (i = 0; i < iq; i++)
563 {
564 A(i) = A_old(i);
565 iai(A(i)) = -1;
566 u(i) = u_old(i);
567 }
568 x = x_old;
569 goto l2; /* go to step 2 */
570 }
571 else
572 iai(ip) = -1;
573#ifdef TRACE_SOLVER
574 print_matrix("R", R, n);
575 print_ivector("A", A, iq);
576#endif
577 goto l1;
578 }
579
580 /* a patial step has taken */
581#ifdef TRACE_SOLVER
582 std::cerr << "Partial step has taken " << t << std::endl;
583 print_vector("x", x, n);
584#endif
585 /* drop constraint l */
586 iai(l) = l;
587 delete_constraint(R, J, A, u, p, iq, l);
588#ifdef TRACE_SOLVER
589 print_matrix("R", R, n);
590 print_ivector("A", A, iq);
591#endif
592
593 s(ip) = CI.col(ip).dot(x) + ci0(ip);
594
595#ifdef TRACE_SOLVER
596 print_vector("s", s, mi);
597#endif
598 goto l2a;
599}
Standard Cholesky decomposition (LL^T) of a matrix and associated features.
Definition LLT.h:57
@ Upper
Definition Constants.h:206
std::ostream & print_matrix(std::ostream &s, const Derived &_m, const IOFormat &fmt)
Definition IO.h:129
T l2(const boost::geometry::model::d2::point_xy< T > &v)
Definition ExtrusionSimulator.cpp:166
IGL_INLINE void sum(const Eigen::SparseMatrix< T > &X, const int dim, Eigen::SparseVector< T > &S)
Definition sum.cpp:12
IGL_INLINE void print_vector(std::vector< T > &v)
Definition print_vector.cpp:14
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329

References Eigen::LLT< _MatrixType, _UpLo >::compute(), Eigen::LLT< _MatrixType, _UpLo >::matrixU(), igl::print_vector(), Eigen::LLT< _MatrixType, _UpLo >::solve(), and igl::sum().

Referenced by progressive_hulls_cost_and_placement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ swept_volume()

IGL_INLINE void igl::copyleft::swept_volume ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const std::function< Eigen::Affine3d(const double t)> &  transform,
const size_t  steps,
const size_t  grid_res,
const size_t  isolevel,
Eigen::MatrixXd &  SV,
Eigen::MatrixXi &  SF 
)
17{
18 using namespace std;
19 using namespace Eigen;
20 using namespace igl;
21 using namespace igl::copyleft;
22
23 const auto & Vtransform =
24 [&V,&transform](const size_t vi,const double t)->RowVector3d
25 {
26 Vector3d Vvi = V.row(vi).transpose();
27 return (transform(t)*Vvi).transpose();
28 };
29 AlignedBox3d Mbox;
30 swept_volume_bounding_box(V.rows(),Vtransform,steps,Mbox);
31
32 // Amount of padding: pad*h should be >= isolevel
33 const int pad = isolevel_grid+1;
34 // number of vertices on the largest side
35 const int s = grid_res+2*pad;
36 const double h = Mbox.diagonal().maxCoeff()/(double)(s-2.*pad-1.);
37 const double isolevel = isolevel_grid*h;
38
39 // create grid
40 RowVector3i res;
41 MatrixXd GV;
42 voxel_grid(Mbox,s,pad,GV,res);
43
44 // compute values
45 VectorXd S;
46 swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S);
47 S.array()-=isolevel;
48 marching_cubes(S,GV,res(0),res(1),res(2),SV,SF);
49}
Definition assign.h:17
Definition AABB.cpp:1014
IGL_INLINE void swept_volume_bounding_box(const size_t &n, const std::function< Eigen::RowVector3d(const size_t vi, const double t)> &V, const size_t &steps, Eigen::AlignedBox3d &box)
Definition swept_volume_bounding_box.cpp:11
IGL_INLINE void swept_volume_signed_distance(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const std::function< Eigen::Affine3d(const double t)> &transform, const size_t &steps, const Eigen::MatrixXd &GV, const Eigen::RowVector3i &res, const double h, const double isolevel, const Eigen::VectorXd &S0, Eigen::VectorXd &S)
Definition swept_volume_signed_distance.cpp:21

References marching_cubes(), igl::swept_volume_bounding_box(), igl::swept_volume_signed_distance(), and igl::voxel_grid().

+ Here is the call graph for this function: