8 Eigen::MatrixXd corner_val(4, 1);
9 Eigen::MatrixXd corner_grad(4, 2);
10 Eigen::MatrixXd corner_grad_grad(4, 1);
11 for (
int i = 0; i < 4; ++i)
20 corner_grad(i, 0) = mixed_grads(0);
21 corner_grad(i, 1) = mixed_grads(1);
22 corner_grad_grad(i, 0) = mixed_grads(2);
26 Eigen::MatrixXd
x(16, 1);
27 x << corner_val(0), corner_val(1), corner_val(2), corner_val(3),
34 auto bar_x = [&corner_point](
double x_) {
return (x_ - corner_point(0, 0)) / (corner_point(1, 0) - corner_point(0, 0)); };
35 auto bar_y = [&corner_point](
double y_) {
return (y_ - corner_point(0, 1)) / (corner_point(2, 1) - corner_point(0, 1)); };
39 for (
int i = 0; i < 4; ++i)
40 for (
int j = 0; j < 4; ++j)
42 val += coeffs(i + j * 4) * pow(bar_x(point(0)), i) * pow(bar_y(point(1)), j);
43 grad(0) += i == 0 ? 0 : (coeffs(i + j * 4) * i * pow(bar_x(point(0)), i - 1) * pow(bar_y(point(1)), j));
44 grad(1) += j == 0 ? 0 : coeffs(i + j * 4) * pow(bar_x(point(0)), i) * j * pow(bar_y(point(1)), j - 1);
47 grad(0) /= (corner_point(1, 0) - corner_point(0, 0));
48 grad(1) /= (corner_point(2, 1) - corner_point(0, 1));
50 assert(!std::isnan(grad(0)) && !std::isnan(grad(1)));
55 Eigen::MatrixXd corner_val(8, 1);
56 Eigen::MatrixXd corner_grad(8, 3);
57 Eigen::MatrixXd corner_grad_grad(8, 3);
58 Eigen::MatrixXd corner_grad_grad_grad(8, 1);
59 for (
int i = 0; i < 8; ++i)
68 corner_grad(i, 0) = mixed_grads(0);
69 corner_grad(i, 1) = mixed_grads(1);
70 corner_grad(i, 2) = mixed_grads(2);
71 corner_grad_grad(i, 0) = mixed_grads(3);
72 corner_grad_grad(i, 1) = mixed_grads(4);
73 corner_grad_grad(i, 2) = mixed_grads(5);
74 corner_grad_grad_grad(i, 0) = mixed_grads(6);
77 Eigen::MatrixXd
x(64, 1);
78 x << corner_val(0), corner_val(1), corner_val(2), corner_val(3), corner_val(4), corner_val(5), corner_val(6), corner_val(7),
79 delta_ * corner_grad(0, 0),
delta_ * corner_grad(1, 0),
delta_ * corner_grad(2, 0),
delta_ * corner_grad(3, 0),
delta_ * corner_grad(4, 0),
delta_ * corner_grad(5, 0),
delta_ * corner_grad(6, 0),
delta_ * corner_grad(7, 0),
80 delta_ * corner_grad(0, 1),
delta_ * corner_grad(1, 1),
delta_ * corner_grad(2, 1),
delta_ * corner_grad(3, 1),
delta_ * corner_grad(4, 1),
delta_ * corner_grad(5, 1),
delta_ * corner_grad(6, 1),
delta_ * corner_grad(7, 1),
81 delta_ * corner_grad(0, 2),
delta_ * corner_grad(1, 2),
delta_ * corner_grad(2, 2),
delta_ * corner_grad(3, 2),
delta_ * corner_grad(4, 2),
delta_ * corner_grad(5, 2),
delta_ * corner_grad(6, 2),
delta_ * corner_grad(7, 2),
82 delta_ *
delta_ * corner_grad_grad(0, 0),
delta_ *
delta_ * corner_grad_grad(1, 0),
delta_ *
delta_ * corner_grad_grad(2, 0),
delta_ *
delta_ * corner_grad_grad(3, 0),
delta_ *
delta_ * corner_grad_grad(4, 0),
delta_ *
delta_ * corner_grad_grad(5, 0),
delta_ *
delta_ * corner_grad_grad(6, 0),
delta_ *
delta_ * corner_grad_grad(7, 0),
83 delta_ *
delta_ * corner_grad_grad(0, 1),
delta_ *
delta_ * corner_grad_grad(1, 1),
delta_ *
delta_ * corner_grad_grad(2, 1),
delta_ *
delta_ * corner_grad_grad(3, 1),
delta_ *
delta_ * corner_grad_grad(4, 1),
delta_ *
delta_ * corner_grad_grad(5, 1),
delta_ *
delta_ * corner_grad_grad(6, 1),
delta_ *
delta_ * corner_grad_grad(7, 1),
84 delta_ *
delta_ * corner_grad_grad(0, 2),
delta_ *
delta_ * corner_grad_grad(1, 2),
delta_ *
delta_ * corner_grad_grad(2, 2),
delta_ *
delta_ * corner_grad_grad(3, 2),
delta_ *
delta_ * corner_grad_grad(4, 2),
delta_ *
delta_ * corner_grad_grad(5, 2),
delta_ *
delta_ * corner_grad_grad(6, 2),
delta_ *
delta_ * corner_grad_grad(7, 2),
85 delta_ *
delta_ *
delta_ * corner_grad_grad_grad(0, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(1, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(2, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(3, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(4, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(5, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(6, 0),
delta_ *
delta_ *
delta_ * corner_grad_grad_grad(7, 0);
89 auto bar_x = [&corner_point](
double x_) {
return (x_ - corner_point(0, 0)) / (corner_point(1, 0) - corner_point(0, 0)); };
90 auto bar_y = [&corner_point](
double y_) {
return (y_ - corner_point(0, 1)) / (corner_point(2, 1) - corner_point(0, 1)); };
91 auto bar_z = [&corner_point](
double z_) {
return (z_ - corner_point(0, 2)) / (corner_point(4, 2) - corner_point(0, 2)); };
95 for (
int i = 0; i < 4; ++i)
96 for (
int j = 0; j < 4; ++j)
97 for (
int l = 0; l < 4; ++l)
99 val += coeffs(i + j * 4 + l * 16) * pow(bar_x(point(0)), i) * pow(bar_y(point(1)), j) * pow(bar_z(point(2)), l);
100 grad(0) += i == 0 ? 0 : (coeffs(i + j * 4 + l * 16) * i * pow(bar_x(point(0)), i - 1) * pow(bar_y(point(1)), j)) * pow(bar_z(point(2)), l);
101 grad(1) += j == 0 ? 0 : coeffs(i + j * 4 + l * 16) * pow(bar_x(point(0)), i) * j * pow(bar_y(point(1)), j - 1) * pow(bar_z(point(2)), l);
102 grad(2) += l == 0 ? 0 : coeffs(i + j * 4 + l * 16) * pow(bar_x(point(0)), i) * pow(bar_y(point(1)), j) * l * pow(bar_z(point(2)), l - 1);
105 grad(0) /= (corner_point(1, 0) - corner_point(0, 0));
106 grad(1) /= (corner_point(2, 1) - corner_point(0, 1));
107 grad(2) /= (corner_point(4, 2) - corner_point(0, 2));
109 assert(!std::isnan(grad(0)) && !std::isnan(grad(1)) && !std::isnan(grad(2)));
114 Eigen::MatrixXi keys;
116 std::vector<std::string> keys_string;
118 auto safe_compute_distance = [
this, compute_distance](
const Eigen::MatrixXd &clamped_point,
const std::string &key_string) {
123 auto safe_distance = [
this, safe_compute_distance](
const Eigen::VectorXi &key) {
124 Eigen::MatrixXd point;
125 std::string key_string;
128 safe_compute_distance(point, key_string);
135 auto centered_fd = [
this, safe_distance](
const Eigen::VectorXi &key,
const int k) {
136 Eigen::MatrixXi key_plus, key_minus;
137 double distance_plus, distance_minus;
140 distance_plus = safe_distance(key_plus);
143 distance_minus = safe_distance(key_minus);
144 return (1. / 2. /
delta_) * (distance_plus - distance_minus);
146 auto centered_mixed_fd = [
this, centered_fd](
const Eigen::VectorXi &key,
const int k1,
const int k2) {
147 Eigen::VectorXi key_plus, key_minus;
152 return (1. / 2. /
delta_) * (centered_fd(key_plus, k2) - centered_fd(key_minus, k2));
154 auto centered_mixed_fd_3d = [
this, centered_mixed_fd](
const Eigen::VectorXi &key) {
155 Eigen::VectorXi key_plus, key_minus;
160 return (1. / 2. /
delta_) * (centered_mixed_fd(key_plus, 1, 2) - centered_mixed_fd(key_minus, 1, 2));
162 auto compute_grad = [
this, centered_fd, centered_mixed_fd, centered_mixed_fd_3d](
const Eigen::VectorXi &key) {
163 Eigen::VectorXd mixed_grads(
dim_ == 2 ? 3 : 7);
166 mixed_grads(0) = centered_fd(key, 0);
167 mixed_grads(1) = centered_fd(key, 1);
168 mixed_grads(2) = centered_mixed_fd(key, 0, 1);
172 mixed_grads(0) = centered_fd(key, 0);
173 mixed_grads(1) = centered_fd(key, 1);
174 mixed_grads(2) = centered_fd(key, 2);
175 mixed_grads(3) = centered_mixed_fd(key, 0, 1);
176 mixed_grads(4) = centered_mixed_fd(key, 0, 2);
177 mixed_grads(5) = centered_mixed_fd(key, 1, 2);
178 mixed_grads(6) = centered_mixed_fd_3d(key);
182 auto safe_compute_grad = [
this, compute_grad](
const Eigen::VectorXi &key) {
183 std::string key_string;
184 Eigen::MatrixXd point;
190 Eigen::MatrixXd grad = compute_grad(key);
195 Eigen::MatrixXd corner_point(keys.rows(),
dim_);
196 for (
int i = 0; i < keys.rows(); ++i)
198 std::string key_string;
199 Eigen::MatrixXd clamped_point;
200 setup_key(keys.row(i), key_string, clamped_point);
201 safe_compute_distance(clamped_point, key_string);
202 keys_string.push_back(key_string);
203 corner_point.row(i) = clamped_point.transpose();
204 safe_compute_grad(keys.row(i));