3#include <wmtk/Types.hpp>
4#include <wmtk/envelope/Envelope.hpp>
6#include <wmtk/threading/enumerable_thread_specific.hpp>
7#include "SimplicialComplexBVH.hpp"
9#include <polysolve/nonlinear/Problem.hpp>
16namespace wmtk::components::topological_offset {
38 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
41 using VecD = Eigen::Matrix<double, DIM, 1>;
42 using MatD = Eigen::Matrix<double, DIM, DIM>;
53 double delta()
const {
return m_delta; }
57 double dhat()
const {
return m_dhat; }
73 virtual double value(
const VecD& p)
const = 0;
76 virtual VecD gradient(
const VecD& p)
const = 0;
77 virtual MatD hessian(
const VecD& p)
const = 0;
161 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
164 using VecD =
typename OffsetPotential<DIM>::VecD;
165 using MatD =
typename OffsetPotential<DIM>::MatD;
189 const std::vector<int>& P,
195 double value(
const VecD& p)
const override;
196 VecD gradient(
const VecD& p)
const override;
197 MatD hessian(
const VecD& p)
const override;
229 void build(
const MatrixXd& V,
const MatrixXi& E,
const MatrixXi& F,
const std::vector<int>& P);
234 std::unique_ptr<Impl> m_impl;
237using SmoothOffsetPotential2D = SmoothOffsetPotential<2>;
238using SmoothOffsetPotential3D = SmoothOffsetPotential<3>;
272 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
276 using VecD =
typename OffsetPotential<DIM>::VecD;
277 using MatD =
typename OffsetPotential<DIM>::MatD;
299 double value(
const VecD& p)
const override;
300 VecD gradient(
const VecD& p)
const override;
301 MatD hessian(
const VecD& p)
const override;
322 void nearest_feature(
const VecD& p, VecD& foot,
int& dim, VecD& dir)
const;
332 std::shared_ptr<SimplicialComplexBVH> m_bvh;
365 using typename polysolve::nonlinear::Problem::Scalar;
366 using typename polysolve::nonlinear::Problem::THessian;
367 using typename polysolve::nonlinear::Problem::TVector;
369 using VecD = Eigen::Matrix<double, DIM, 1>;
370 using MatD = Eigen::Matrix<double, DIM, DIM>;
380 bool gauss_newton =
true,
381 bool distance_residual =
false);
383 double value(
const TVector& x)
override;
384 void gradient(
const TVector& x, TVector& gradv)
override;
385 void hessian(
const TVector& x, THessian& hessian)
override
387 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
389 void hessian(
const TVector& x, MatrixXd& hessian)
override;
391 void solution_changed(
const TVector& new_x)
override {}
394 std::shared_ptr<const OffsetPotential<DIM>> m_potential;
397 bool m_distance_residual;
404 void residual(
const VecD& p,
double& r, VecD& dr)
const;
406 mutable bool m_cache_valid =
false;
407 mutable VecD m_cache_p;
408 mutable double m_cache_r = 0.;
409 mutable VecD m_cache_dr;
435 using typename polysolve::nonlinear::Problem::Scalar;
436 using typename polysolve::nonlinear::Problem::THessian;
437 using typename polysolve::nonlinear::Problem::TVector;
451 const std::shared_ptr<const OffsetPotential2D>& potential,
452 std::vector<Edge> edges,
456 void residual(
const Eigen::Vector2d& x,
const Edge& e,
double& r, Eigen::Vector2d& J)
const;
457 double value(
const TVector& x)
override;
458 void gradient(
const TVector& x, TVector& gradv)
override;
459 void hessian(
const TVector& x, THessian& hessian)
override
461 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
463 void hessian(
const TVector& x, MatrixXd& hessian)
override;
464 void solution_changed(
const TVector& new_x)
override {}
467 std::shared_ptr<const OffsetPotential2D> m_potential;
468 std::vector<Edge> m_edges;
469 double m_sign, m_weight;
471using OffsetEnergy3D = OffsetEnergy<3>;
494 using typename polysolve::nonlinear::Problem::Scalar;
495 using typename polysolve::nonlinear::Problem::THessian;
496 using typename polysolve::nonlinear::Problem::TVector;
499 Eigen::Vector2d q1,
q2;
504 double value(
const TVector& x)
override;
505 void gradient(
const TVector& x, TVector& gradv)
override;
506 void hessian(
const TVector& x, THessian& hessian)
override
508 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
510 void hessian(
const TVector& x, MatrixXd& hessian)
override;
511 void solution_changed(
const TVector& new_x)
override {}
512 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
516 bool cell_F(
const Eigen::Vector2d& x,
const Cell& c, Eigen::Matrix2d& F,
double& d)
const;
517 std::vector<Cell> m_cells;
First-order offset term: each front edge at the vertex against the field.
Definition OffsetPotential.hpp:433
void residual(const Eigen::Vector2d &x, const Edge &e, double &r, Eigen::Vector2d &J) const
r_e and its derivative for one edge; r = 0 with J = 0 where grad Phi vanishes.
Definition OffsetPotential.cpp:726
The Euclidean offset: Phi = d(p, input complex), level set d = delta.
Definition OffsetPotential.hpp:271
std::string describe_active(const VecD &p) const override
Diagnostic: what the field is made of at p, one contribution per line.
Definition OffsetPotential.cpp:1099
bool is_euclidean() const override
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:275
std::shared_ptr< SampleEnvelope > m_envelope
Definition OffsetPotential.hpp:331
bool is_inside_offset(const VecD &p) const override
Definition OffsetPotential.hpp:315
void nearest_feature(const VecD &p, VecD &foot, int &dim, VecD &dir) const
Definition OffsetPotential.cpp:994
bool within_support(const VecD &p) const override
Everywhere. d has no compact support.
Definition OffsetPotential.hpp:311
double residual_length(const VecD &p) const override
Definition OffsetPotential.hpp:305
The offset term of the smoothing objective: w * (Phi(x) - c)^2.
Definition OffsetPotential.hpp:363
void residual(const VecD &p, double &r, VecD &dr) const
Definition OffsetPotential.cpp:878
bool root_distance(const VecD &p, double &s, VecD &n) const
Definition OffsetPotential.cpp:793
double m_last_root
warm start for root_distance(), see there
Definition OffsetPotential.hpp:405
The offset potential: the scalar field on space whose level set the front is placed on.
Definition OffsetPotential.hpp:37
double delta() const
The offset distance the field is calibrated to.
Definition OffsetPotential.hpp:53
virtual bool is_inside_offset(const VecD &p) const =0
Whether p lies inside the offset region – on the complex's side of the level set.
virtual std::string describe_active(const VecD &p) const =0
Diagnostic: what the field is made of at p, one contribution per line.
double m_grad_ref
Definition OffsetPotential.hpp:114
double level_set_slope() const
|d(field)/d(distance)| at the level set on a flat stretch of input.
Definition OffsetPotential.hpp:71
OffsetPotential(const double delta, const double dhat)
Definition OffsetPotential.hpp:104
virtual double residual_length(const VecD &p) const =0
Distance from p to the level set, in length units.
double dhat() const
Definition OffsetPotential.hpp:57
virtual bool is_euclidean() const
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:75
virtual ~OffsetPotential()
double target_level() const
The level value the offset boundary is placed on.
Definition OffsetPotential.hpp:50
virtual bool within_support(const VecD &p) const =0
Whether p is somewhere the field can give a direction to the level set at all.
AMIPS against a rest shape, for deform_others: the smoothing term of a deformable region's faces.
Definition OffsetPotential.hpp:492
bool cell_F(const Eigen::Vector2d &x, const Cell &c, Eigen::Matrix2d &F, double &d) const
e = tr(F^T F), d = det F at x for one cell; false when d <= 0.
Definition OffsetPotential.cpp:1133
The smooth offset potential Phi, and the offset defined as its level set Phi = c.
Definition OffsetPotential.hpp:160
std::string describe_active(const VecD &p) const override
Definition OffsetPotential.cpp:652
bool within_support(const VecD &p) const override
Whether p is inside the support at all, i.e. Phi(p) > 0.
Definition OffsetPotential.hpp:209
double residual_length(const VecD &p) const override
First-order distance from p to the level set Phi = c, in length units.
Definition OffsetPotential.cpp:687
bool is_inside_offset(const VecD &p) const override
Phi decreases with distance, so the offset region is where it is still above the level.
Definition OffsetPotential.hpp:212
Definition OffsetPotential.hpp:439
Eigen::Vector2d q
the other endpoint
Definition OffsetPotential.hpp:440
double agree
Definition OffsetPotential.hpp:448
double sigma
Definition OffsetPotential.hpp:441
Definition OffsetPotential.hpp:498
Eigen::Matrix2d rest_inv
inverse rest Jacobian [r1-r0, r2-r0]^-1, same corner order
Definition OffsetPotential.hpp:500
Eigen::Vector2d q2
the fixed endpoints, current positions
Definition OffsetPotential.hpp:499