Medusa  1.1
Coordinate Free Mehless Method implementation
PUApproximant.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_INTERPOLANTS_PUAPPROXIMANT_HPP_
2 #define MEDUSA_BITS_INTERPOLANTS_PUAPPROXIMANT_HPP_
3 
12 
13 #include "PUApproximant_fwd.hpp"
14 
15 namespace mm {
16 
18 template <typename vec_t>
19 template <typename scalar_t, typename engine_t>
20 Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> PUApproximant<vec_t>::evaluate(
21  const DomainDiscretization<vec_t>& domain, const eigen_vt<scalar_t>& values,
22  const Range<vec_t>& query_points, d_scalar_t radius_factor, const engine_t& engine) {
23  KDTree<vec_t> tree(query_points); // Build KDTree.
24 
25  return evaluate(domain, values, tree, radius_factor, engine);
26 }
27 
28 template <typename vec_t>
29 template <typename scalar_t, typename engine_t>
30 Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> PUApproximant<vec_t>::evaluate(
31  const DomainDiscretization<vec_t>& domain, const eigen_vt<scalar_t>& values,
32  const KDTree<vec_t>& query_points_tree, d_scalar_t radius_factor, const engine_t& engine) {
33  int N = domain.size();
34  assert_msg(N >= 0, "Missing domain positions.");
35  for (int i = 0; i < domain.size(); i++) {
36  int support_size = domain.supportSize(i);
37  if (support_size <= 0) {
38  assert_msg(support_size >= 0,
39  "Expected support size >= 0. Node %d has support size %d. Did you forget "
40  "to call findSupport()?",
41  i, support_size);
42  }
43  }
44  int M = values.size();
45  assert_msg(M == N,
46  "Number of function values given different from number of "
47  "nodes in the domain. Got %d function values and %d nodes.",
48  M, N);
49  assert_msg(radius_factor >= 0 && radius_factor <= 1,
50  "Effective radius must be "
51  "larger than 0 and smaller than 1, got %g",
52  radius_factor);
53 
54  int Nq = query_points_tree.size(); // Number of query points.
55  eigen_vt<scalar_t> result_num(Nq);
56  result_num.setConstant(0);
57  eigen_vt<d_scalar_t> result_den(Nq);
58  result_den.setConstant(0);
59  Eigen::VectorXi count(Nq);
60  count.setConstant(0);
61 
62  for (int i = 0; i < N; ++i) {
63  if (domain.supportSize(i) <= 0) continue; // Check i-th support size.
64 
65  const vec_t& p = domain.pos(i); // Central node.
66  auto appr = engine.getApproximant(p, domain.supportNodes(i), values(domain.support(i)));
67 
68  // Evaluate PU interpolant.
69  Range<vec_t> sup = domain.supportNodes(i); // Support nodes.
70  auto dr = (sup[0] - sup[sup.size() - 1]).norm();
71  d_scalar_t radius = radius_factor * dr;
72  d_scalar_t radius2 = ipow<2>(radius);
73  Range<int> idx;
74  Range<double> dist2;
75  std::tie(idx, dist2) =
76  query_points_tree.query(p, radius2); // Query for close enough nodes.
77  int n = idx.size();
78  for (int j = 0; j < n; ++j) {
79  const int& k = idx[j];
80  ++count[k];
81  d_scalar_t w = weight(std::sqrt(dist2[j] / radius2));
82  result_num[k] += w * appr(query_points_tree.get(k));
83  result_den[k] += w;
84  }
85  }
86 
87  // Check if all query nodes are covered.
88  for (int i = 0; i < Nq; ++i) {
89  assert_msg(count[i] > 0,
90  "Query point %d has an undefined value. Point %s is not covered by any of "
91  "the balls with centers in discretization nodes. Consider increasing the "
92  "ball radius.",
93  i, query_points_tree.get(i));
94  }
95 
96  return result_num.cwiseQuotient(result_den);
97 }
99 } // namespace mm
100 
101 #endif // MEDUSA_BITS_INTERPOLANTS_PUAPPROXIMANT_HPP_
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
mm::PUApproximant::evaluate
static eigen_vt< scalar_t > evaluate(const DomainDiscretization< vec_t > &domain, const eigen_vt< scalar_t > &values, const Range< vec_t > &query_points, d_scalar_t radius_factor, const engine_t &engine)
Evaluates the Partion-of-unity approximant at points 'query_points' constructed on given pairs.
PUApproximant_fwd.hpp
numutils.hpp
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
KDTree.hpp
assert.hpp