Update eigen to v5.0.1 and libigl to v2.6.0. (#11311)

* Update eigen from v3.3.7 to v5.0.1.

This updates eigen from v3.3.7 released on  December 11, 2018-12-11 to v5.0.1
released on 2025-11-11. There have be a large number of bug-fixes,
optimizations, and improvements between these releases. See the details at;

https://gitlab.com/libeigen/eigen/-/releases

It retains the previous custom minimal `CMakeLists.txt`, and adds a
README-OrcaSlicer.md that explains what version and parts of the upstream
eigen release have been included, and where the full release can be found.

* Update libigl from v2.0.0 (or older) to v2.6.0.

This updates libigl from what was probably v2.0.0 released on 2018-10-16 to
v2.6.0 released on 2025-05-15. It's possible the old version was even older
than that but there is no version indicators in the code and I ran out of
patience identifying missing changes and only went back as far as v2.0.0.

There have been a large number of bug-fixes, optimizations, and improvements
between these versions. See the following for details;

https://github.com/libigl/libigl/releases

I retained the minimal custom `CMakeLists.txt`, added `README.md` from the
libigl distribution which identifies the version, and added a
README-OrcaSlicer.md that details the version and parts that have been
included.

* Update libslic3r for libigl v2.6.0 changes.

This updates libslic3r for all changes moving to eigen v5.0.1 and libigl
v2.6.0. Despite the large number of updates to both dependencies, no changes
were required for the eigen update, and only one change was required for the
libigl update.

For libigl, `igl::Hit` was changed to a template taking the Scalar type to
use. Previously it was hard-coded to `float`, so to minimize possible impact
I've updated all places it is used from `igl::Hit` to `igl::Hit<float>`.

* Add compiler option `-DNOMINMAX` for libigl with MSVC.

MSVC by default defines `min(()` and `max()` macros that break
`std::numeric_limits<>::max()`. The upstream cmake that we don't include
adds `-DNOMINMAX` for the libigl module when compiling with MSVC, so we need
to add the same thing here.

* Fix src/libslic3r/TriangleMeshDeal.cpp for the unmodified upstream libigl.

This fixes `TriangleMeshDeal.cpp` to work with the unmodified upstream
libigl v2.6.0. loop.{h,cpp} implementation.

This file and feature was added in PR "BBS Port: Mesh Subdivision" (#12150)
which included changes to `loop.{h,cpp}` in the old version of libigl. This PR
avoids modifying the included dependencies, and uses the updated upstream
versions of those files without any modifications, which requires fixing
TriangleMeshDeal.cpp to work with them.

In particular, the modifications made to `loop.{h,cpp}` included changing the
return type from void to bool, adding additional validation checking of the
input meshes, and returning false if they failed validation. These added
checks looked unnecessary and would only have caught problems if the input
mesh was very corrupt.

To make `TriangleMeshDeal.cpp` work without this built-in checking
functionality, I removed checking/handling of any `false` return value.

There was also a hell of a lot of redundant copying and casting back and forth
between float and double, so I cleaned that up. The input and output meshs use
floats for the vertexes, and there would be no accuracy benefits from casting
to and from doubles for the simple weighted average operations done by
igl::loop(). So this just uses `Eigen:Map` to use the original input mesh
vertex data directly without requiring any copy or casting.

* Move eigen from included `deps_src` to externaly fetched `deps`.

This copys what PrusaSlicer did and moved it from an included dependency under
`deps_src` to an externaly fetched dependency under `deps`. This requires
updating some `CMakeList.txt` configs and removing the old and obsolete
`cmake/modules/FindEigen3.cmake`. The details of when this was done in
PrusaSlicer and the followup fixes are at;

* 21116995d7
* https://github.com/prusa3d/PrusaSlicer/issues/13608
* https://github.com/prusa3d/PrusaSlicer/pull/13609
* e3c277b9ee

For some reason I don't fully understand this also required fixing
`src/slic3r/GUI/GUI_App.cpp` by adding `#include <boost/nowide/cstdio.hpp>` to
fix an `error: ‘remove’ is not a member of ‘boost::nowide'`. The main thing I
don't understand is how it worked before. Note that this include is in the
PrusaSlicer version of this file, but it also significantly deviates from what
is currently in OrcaSlicer in many other ways.

* Whups... I missed adding the deps/Eigen/Eigen.cmake file...

* Tidy some whitespace indenting in CMakeLists.txt.

* Ugh... tabs indenting needing fixes.

* Change the include order of deps/Eigen.

It turns out that although Boost includes some references to Eigen, Eigen also
includes some references to Boost for supporting some of it's additional
numeric types.

I don't think it matters much since we are not using these features, but I
think technically its more correct to say Eigen depends on Boost than the
other way around, so I've re-ordered them.

* Add source for Eigen 5.0.1 download to flatpak yml config.

* Add explicit `DEPENDS dep_Boost to deps/Eigen.

I missed this before. This ensures we don't rely on include orders to make
sure Boost is installed before we configure Eigen.

* Add `DEPENDS dep_Boost dep_GMP dep_MPFR` to deps/Eigen.

It turns out Eigen can also use GMP and MPFR for multi-precision and
multi-precision-rounded numeric types if they are available.

Again, I don't think we are using these so it doesn't really matter, but it is
technically correct and ensures they are there if we ever do need them.

* Fix deps DEPENDENCY ordering for GMP, MPFR, Eigen, and CGAL.

I think this is finally correct. Apparently CGAL also optionally depends on
Eigen, so the correct dependency order from lowest to highest is GMP, MPFR, Eigen, and CGAL.

---------

Co-authored-by: Donovan Baarda <dbaarda@google.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
Donovan Baarda
2026-05-12 17:09:13 +10:00
committed by GitHub
parent 797ee70b0b
commit dc5897d7b5
1573 changed files with 63323 additions and 161343 deletions

View File

@@ -8,7 +8,6 @@
#include "bbw.h"
#include "mosek_quadprog.h"
#include "../harmonic.h"
#include "../slice_into.h"
#include <Eigen/Sparse>
#include <iostream>
#include <cstdio>
@@ -21,10 +20,10 @@ template <
typename Derivedbc,
typename DerivedW>
IGL_INLINE bool igl::mosek::bbw(
const Eigen::PlainObjectBase<DerivedV> & V,
const Eigen::PlainObjectBase<DerivedEle> & Ele,
const Eigen::PlainObjectBase<Derivedb> & b,
const Eigen::PlainObjectBase<Derivedbc> & bc,
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedEle> & Ele,
const Eigen::MatrixBase<Derivedb> & b,
const Eigen::MatrixBase<Derivedbc> & bc,
igl::BBWData & data,
igl::mosek::MosekData & mosek_data,
Eigen::PlainObjectBase<DerivedW> & W
@@ -60,8 +59,8 @@ IGL_INLINE bool igl::mosek::bbw(
VectorXd bci = bc.col(i);
VectorXd Wi;
// impose boundary conditions via bounds
slice_into(bci,b,ux);
slice_into(bci,b,lx);
ux(b) = bci;
lx(b) = bci;
bool r = mosek_quadprog(Q,c,0,A,lc,uc,lx,ux,mosek_data,Wi);
if(!r)
{
@@ -83,6 +82,6 @@ IGL_INLINE bool igl::mosek::bbw(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
template bool igl::mosek::bbw<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<double, -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<double, -1, -1, 0, -1, -1> > const&, igl::BBWData&, igl::mosek::MosekData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
template bool igl::mosek::bbw<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<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::BBWData&, igl::mosek::MosekData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
#endif

View File

@@ -16,26 +16,23 @@ namespace igl
{
namespace mosek
{
// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
// set of boundary conditions
//
// Templates
// DerivedV derived type of eigen matrix for V (e.g. MatrixXd)
// DerivedF derived type of eigen matrix for F (e.g. MatrixXi)
// Derivedb derived type of eigen matrix for b (e.g. VectorXi)
// Derivedbc derived type of eigen matrix for bc (e.g. MatrixXd)
// DerivedW derived type of eigen matrix for W (e.g. MatrixXd)
// Inputs:
// V #V by dim vertex positions
// Ele #Elements by simplex-size list of element indices
// b #b boundary indices into V
// bc #b by #W list of boundary values
// data object containing options, initial guess --> solution and results
// mosek_data object containing mosek options
// Outputs:
// W #V by #W list of *unnormalized* weights to normalize use
// igl::normalize_row_sums(W,W);
// Returns true on success, false on failure
/// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
/// set of boundary conditions
///
/// @tparam DerivedV derived type of eigen matrix for V (e.g. MatrixXd)
/// @tparam DerivedF derived type of eigen matrix for F (e.g. MatrixXi)
/// @tparam Derivedb derived type of eigen matrix for b (e.g. VectorXi)
/// @tparam Derivedbc derived type of eigen matrix for bc (e.g. MatrixXd)
/// @tparam DerivedW derived type of eigen matrix for W (e.g. MatrixXd)
/// @param[in] V #V by dim vertex positions
/// @param[in] Ele #Elements by simplex-size list of element indices
/// @param[in] b #b boundary indices into V
/// @param[in] bc #b by #W list of boundary values
/// @param[in] data object containing options, initial guess --> solution and results
/// @param[in] mosek_data object containing mosek options
/// @param[out] W #V by #W list of *unnormalized* weights to normalize use
/// igl::normalize_row_sums(W,W);
/// @return true on success, false on failure
template <
typename DerivedV,
typename DerivedEle,
@@ -43,10 +40,10 @@ namespace igl
typename Derivedbc,
typename DerivedW>
IGL_INLINE bool bbw(
const Eigen::PlainObjectBase<DerivedV> & V,
const Eigen::PlainObjectBase<DerivedEle> & Ele,
const Eigen::PlainObjectBase<Derivedb> & b,
const Eigen::PlainObjectBase<Derivedbc> & bc,
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedEle> & Ele,
const Eigen::MatrixBase<Derivedb> & b,
const Eigen::MatrixBase<Derivedbc> & bc,
igl::BBWData & data,
igl::mosek::MosekData & mosek_data,
Eigen::PlainObjectBase<DerivedW> & W);

View File

@@ -9,16 +9,15 @@
#define IGL_MOSEK_MOSEK_GUARDED_H
#include "../igl_inline.h"
#include "mosek.h"
#include <mosek.h>
namespace igl
{
namespace mosek
{
// Little function to wrap around mosek call to handle errors
//
// Inputs:
// r mosek error code returned from mosek call
// Returns r untouched
/// Little function to wrap around mosek call to handle errors
///
/// @param[in] r mosek error code returned from mosek call
/// @return r untouched
IGL_INLINE MSKrescodee mosek_guarded(const MSKrescodee r);
}
}

View File

@@ -140,7 +140,9 @@ IGL_INLINE bool igl::mosek::mosek_linprog(
switch(solsta)
{
case MSK_SOL_STA_OPTIMAL:
#if MSK_VERSION_MAJOR <= 8
case MSK_SOL_STA_NEAR_OPTIMAL:
#endif
x.resize(n);
/* Request the basic solution. */
MSK_getxx(task,MSK_SOL_BAS,x.data());
@@ -148,8 +150,10 @@ IGL_INLINE bool igl::mosek::mosek_linprog(
break;
case MSK_SOL_STA_DUAL_INFEAS_CER:
case MSK_SOL_STA_PRIM_INFEAS_CER:
#if MSK_VERSION_MAJOR <= 8
case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
#endif
//printf("Primal or dual infeasibility certificate found.\n");
break;
case MSK_SOL_STA_UNKNOWN:

View File

@@ -15,22 +15,20 @@ namespace igl
{
namespace mosek
{
// Solve a linear program using mosek:
//
// min c'x
// s.t. lc <= A x <= uc
// lx <= x <= ux
//
// Inputs:
// c #x list of linear objective coefficients
// A #A by #x matrix of linear inequality constraint coefficients
// lc #A list of lower constraint bounds
// uc #A list of upper constraint bounds
// lx #x list of lower variable bounds
// ux #x list of upper variable bounds
// Outputs:
// x #x list of solution values
// Returns true iff success.
/// Solve a linear program using mosek. Given in the form:
///
/// min c'x
/// s.t. lc <= A x <= uc
/// lx <= x <= ux
///
/// @param[in] c #x list of linear objective coefficients
/// @param[in] A #A by #x matrix of linear inequality constraint coefficients
/// @param[in] lc #A list of lower constraint bounds
/// @param[in] uc #A list of upper constraint bounds
/// @param[in] lx #x list of lower variable bounds
/// @param[in] ux #x list of upper variable bounds
/// @param[out] x #x list of solution values
/// @return true iff success.
IGL_INLINE bool mosek_linprog(
const Eigen::VectorXd & c,
const Eigen::SparseMatrix<double> & A,
@@ -39,8 +37,12 @@ namespace igl
const Eigen::VectorXd & lx,
const Eigen::VectorXd & ux,
Eigen::VectorXd & x);
// Wrapper that keeps mosek environment alive (if licence checking is
// becoming a bottleneck)
/// \overload
///
/// \brief Wrapper that keeps mosek environment alive (if licence checking is
/// becoming a bottleneck)
///
/// @param[in] env mosek environment
IGL_INLINE bool mosek_linprog(
const Eigen::VectorXd & c,
const Eigen::SparseMatrix<double> & A,

View File

@@ -164,34 +164,27 @@ IGL_INLINE bool igl::mosek::mosek_quadprog(
// Set constant bounds on variable j
if(lx[j] == ux[j])
{
#if MSK_VERSION_MAJOR <=8
mosek_guarded(MSK_putbound(task,MSK_ACC_VAR,j,MSK_BK_FX,lx[j],ux[j]));
#else
mosek_guarded(MSK_putvarbound(task,j,MSK_BK_FX,lx[j],ux[j]));
#endif
}else
{
#if MSK_VERSION_MAJOR <=8
mosek_guarded(MSK_putbound(task,MSK_ACC_VAR,j,MSK_BK_RA,lx[j],ux[j]));
#else
mosek_guarded(MSK_putvarbound(task,j,MSK_BK_RA,lx[j],ux[j]));
#endif
}
if(m>0)
{
// Input column j of A
#if MSK_VERSION_MAJOR >= 7
mosek_guarded(
MSK_putacol(
task,
j,
Acp[j+1]-Acp[j],
&Ari[Acp[j]],
&Av[Acp[j]])
);
mosek_guarded( MSK_putacol( task, j, Acp[j+1]-Acp[j], &Ari[Acp[j]], &Av[Acp[j]]));
#elif MSK_VERSION_MAJOR == 6
mosek_guarded(
MSK_putavec(
task,
MSK_ACC_VAR,
j,
Acp[j+1]-Acp[j],
&Ari[Acp[j]],
&Av[Acp[j]])
);
mosek_guarded( MSK_putavec( task, MSK_ACC_VAR, j, Acp[j+1]-Acp[j], &Ari[Acp[j]], &Av[Acp[j]]));
#endif
}
}
@@ -200,7 +193,11 @@ IGL_INLINE bool igl::mosek::mosek_quadprog(
for(int i = 0;i<m;i++)
{
// put bounds on constraints
#if MSK_VERSION_MAJOR <=8
mosek_guarded(MSK_putbound(task,MSK_ACC_CON,i,MSK_BK_RA,lc[i],uc[i]));
#else
mosek_guarded(MSK_putconbound(task,i,MSK_BK_RA,lc[i],uc[i]));
#endif
}
// Input Q for the objective (REMEMBER Q SHOULD ONLY BE LOWER TRIANGLE)
@@ -243,7 +240,9 @@ IGL_INLINE bool igl::mosek::mosek_quadprog(
switch(solsta)
{
case MSK_SOL_STA_OPTIMAL:
#if MSK_VERSION_MAJOR <= 8
case MSK_SOL_STA_NEAR_OPTIMAL:
#endif
MSK_getsolutionslice(task,MSK_SOL_ITR,MSK_SOL_ITEM_XX,0,n,&x[0]);
//printf("Optimal primal solution\n");
//for(size_t j=0; j<n; ++j)
@@ -254,8 +253,10 @@ IGL_INLINE bool igl::mosek::mosek_quadprog(
break;
case MSK_SOL_STA_DUAL_INFEAS_CER:
case MSK_SOL_STA_PRIM_INFEAS_CER:
#if MSK_VERSION_MAJOR <= 8
case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
#endif
//printf("Primal or dual infeasibility certificate found.\n");
break;
case MSK_SOL_STA_UNKNOWN:

View File

@@ -21,28 +21,29 @@ namespace igl
{
namespace mosek
{
/// Structure for holding MOSEK data for solving a quadratic program
struct MosekData
{
// Integer parameters
/// Integer parameters
std::map<MSKiparame,int> intparam;
// Double parameters
/// Double parameters
std::map<MSKdparame,double> douparam;
// Default values
/// Default values
IGL_INLINE MosekData();
};
// Solve a convex quadratic optimization problem with linear and constant
// bounds, that is:
// bounds. Given in the form:
//
// Minimize: ½ * xT * Q⁰ * x + cT * x + cf
// Minimize: ½ * xT * Q⁰ * x + cT * x + cf
//
// Subject to: lc ≤ Ax ≤ uc
// lx ≤ x ≤ ux
// Subject to: lc ≤ Ax ≤ uc
// lx ≤ x ≤ ux
//
// where we are trying to find the optimal vector of values x.
//
// Note: Q⁰ must be symmetric and the ½ is a convention of MOSEK
// \note Q⁰ must be symmetric
//
// Note: Because of how MOSEK accepts different parts of the system, Q
// \note Because of how MOSEK accepts different parts of the system, Q
// should be stored in IJV (aka Coordinate) format and should only include
// entries in the lower triangle. A should be stored in Column compressed
// (aka Harwell Boeing) format. As described:
@@ -52,43 +53,38 @@ namespace igl
// #Compressed_sparse_column_.28CSC_or_CCS.29
//
//
// Templates:
// Index type for index variables
// Scalar type for floating point variables (gets cast to double?)
// Input:
// n number of variables, i.e. size of x
// Qi vector of qnnz row indices of non-zeros in LOWER TRIANGLE ONLY of
// @tparam Index type for index variables
// @tparam Scalar type for floating point variables (gets cast to double?)
// @param[in] n number of variables, i.e. size of x
// @param[in] Qi vector of qnnz row indices of non-zeros in LOWER TRIANGLE ONLY of
// Q⁰
// Qj vector of qnnz column indices of non-zeros in LOWER TRIANGLE ONLY
// @param[in] Qj vector of qnnz column indices of non-zeros in LOWER TRIANGLE ONLY
// of Q⁰
// Qv vector of qnnz values of non-zeros in LOWER TRIANGLE ONLY of Q⁰,
// @param[in] Qv vector of qnnz values of non-zeros in LOWER TRIANGLE ONLY of Q⁰,
// such that:
//
// Q⁰(Qi[k],Qj[k]) = Qv[k] for k ∈ [0,Qnnz-1], where Qnnz is the
//
// number of non-zeros in Q⁰
// c (optional) vector of n values of c, transpose of coefficient row
// @param[in] c (optional) vector of n values of c, transpose of coefficient row
// vector of linear terms, EMPTY means c == 0
// cf (ignored) value of constant term in objective, 0 means cf == 0, so
// @param[in] cf (ignored) value of constant term in objective, 0 means cf == 0, so
// optional only in the sense that it is mandatory
// m number of constraints, therefore also number of rows in linear
// @param[in] m number of constraints, therefore also number of rows in linear
// constraint coefficient matrix A, and in linear constraint bound
// vectors lc and uc
// Av vector of non-zero values of A, in column compressed order
// Ari vector of row indices corresponding to non-zero values of A,
// Acp vector of indices into Ari and Av of the first entry for each
// @param[in] Av vector of non-zero values of A, in column compressed order
// @param[in] Ari vector of row indices corresponding to non-zero values of A,
// @param[in] Acp vector of indices into Ari and Av of the first entry for each
// column of A, size(Acp) = (# columns of A) + 1 = n + 1
// lc vector of m linear constraint lower bounds
// uc vector of m linear constraint upper bounds
// lx vector of n constant lower bounds
// ux vector of n constant upper bounds
// Output:
// x vector of size n to hold output of optimization
// Return:
// true only if optimization was successful with no errors
// @param[in] lc vector of m linear constraint lower bounds
// @param[in] uc vector of m linear constraint upper bounds
// @param[in] lx vector of n constant lower bounds
// @param[in] ux vector of n constant upper bounds
// @param[out] x vector of size n to hold output of optimization
// @return true only if optimization was successful with no errors
//
// Note: All indices are 0-based
//
// \note All indices are 0-based
template <typename Index, typename Scalar>
IGL_INLINE bool mosek_quadprog(
const Index n,
@@ -107,23 +103,21 @@ namespace igl
const std::vector<Scalar> & ux,
MosekData & mosek_data,
std::vector<Scalar> & x);
// Wrapper with Eigen elements
//
// Inputs:
// Q n by n square quadratic coefficients matrix **only lower triangle
// is used**.
// c n-long vector of linear coefficients
// cf constant coefficient
// A m by n square linear coefficienst matrix of inequality constraints
// lc m-long vector of lower bounds for linear inequality constraints
// uc m-long vector of upper bounds for linear inequality constraints
// lx n-long vector of lower bounds
// ux n-long vector of upper bounds
// mosek_data parameters struct
// Outputs:
// x n-long solution vector
// Returns true only if optimization finishes without error
//
/// \overload
///
/// @param[in] Q n by n square quadratic coefficients matrix **only lower triangle
/// is used**.
/// @param[in] c n-long vector of linear coefficients
/// @param[in] cf constant coefficient
/// @param[in] A m by n square linear coefficienst matrix of inequality constraints
/// @param[in] lc m-long vector of lower bounds for linear inequality constraints
/// @param[in] uc m-long vector of upper bounds for linear inequality constraints
/// @param[in] lx n-long vector of lower bounds
/// @param[in] ux n-long vector of upper bounds
/// @param[in] mosek_data parameters struct
/// @param[out] x n-long solution vector
/// @return true only if optimization finishes without error
///
IGL_INLINE bool mosek_quadprog(
const Eigen::SparseMatrix<double> & Q,
const Eigen::VectorXd & c,