在CGAL手册中,它说here:
分散数据插值解决了以下问题:给定一组数据点上的函数测量,任务是在任意查询点上插入此函数。更正式地,让P = {p1,...,pn}是R2或R3中的n个点的集合,并且Φ是在P的凸包上定义的标量函数。我们假设函数值在P的点处是已知的。 ,即对每个pi∈P,我们将zi =Φ(pi)。
联系起来
然后它继续显示示例,但我找到的最接近 3D 插值的示例是示例Interpolation/surface_neighbor_coordinates_3.cpp
。据我所知,这只能找到一个点的邻居顶点。
我是否可以采取后续步骤在3D中的任意查询点找到插值函数值? (具体来说,在球体上?)
答案 0 :(得分:2)
在same page you quote, at the section "3 Interpolation Methods"中,有插值方法的描述,有两个例子。这可能就是你要找的东西。但是,您必须将这些示例调整为3D。
答案 1 :(得分:0)
将2D示例传输到3D确实不是一件容易的事;我会试试这个
#include <stdexcept> // std::logic_error
#include <iterator> // back_inserter
#include <algorithm> // copy_n
#include <functional> // function<R(A)>
#include <map> // map, pair
#include <cmath> // abs()
#include <string> // string, stoul
#include <limits> // numeric_limits<size_t>::max
#include <iostream>
#include <vector>
const long MIN_SAMPLE_SIZE = 10;
const long DEFAULT_SAMPLE_SIZE = 1000;
const long MAX_SAMPLE_SIZE = 100000;
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/natural_neighbor_coordinates_3.h>
#include <CGAL/interpolation_functions.h>
#include <CGAL/surface_neighbor_coordinates_3.h>
///@TODO check if using Delaunay tesselation could make it faster
//#include <CGAL/Delaunay_triangulation_3.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using real_t = Kernel::FT;
using point3_t = Kernel::Point_3;
using vec3_t = Kernel::Vector_3;
using value_map_t = std::map<point3_t, real_t, Kernel::Less_xyz_3>;
using value_access_t = CGAL::Data_access<value_map_t>;
using distance_vec_t = std::vector<std::pair<point3_t, real_t>>;
using ScalarR3Field = std::function<real_t(point3_t)>;
const ScalarR3Field maxN = [] (const point3_t& p) {
std::vector<real_t> v {
std::abs(p.x()),
std::abs(p.y()),
std::abs(p.z())
};
return *std::max_element(v.begin(),v.end());
//return std::max(v.begin(), v.end());
};
const ScalarR3Field l1N = [] (const point3_t& p) {
return std::abs(p.x()) +
std::abs(p.y()) +
std::abs(p.z());
};
std::map<std::string, ScalarR3Field> TESTS {
{"maximum norm", maxN},
{"l_1 norm", l1N}
};
int main(int argc, char* argv[]) {
auto sample_size = DEFAULT_SAMPLE_SIZE;
if (argc > 1) {
try {
auto val = std::stol(argv[1]);
if (val < MIN_SAMPLE_SIZE) {
throw std::logic_error("sample size suppplied is too small");
} else if (val > MAX_SAMPLE_SIZE) {
throw std::logic_error("sample size suppplied is too large");
}
sample_size = val;
} catch (const std::logic_error& e) {
std::cerr << e.what() << ";"
<< " using default sample size of "
<< (sample_size = DEFAULT_SAMPLE_SIZE)
<< "." << std::endl;
} // try/catch for argv[1] conversion
} // if (argc > 1)
std::vector<point3_t> points;
points.reserve(sample_size);
CGAL::Random_points_on_sphere_3<point3_t> gen (1.0);
std::copy_n(gen, sample_size, std::back_inserter(points));
auto point = *(++gen);
auto vec = point - CGAL::ORIGIN;
std::cout << std::endl;
for (auto& test : TESTS) {
value_map_t F;
auto& f = test.second;
for (auto& p: points)
F.emplace(std::make_pair(p, f(p)));
distance_vec_t coords;
auto triple = CGAL::surface_neighbor_coordinates_3(
points.begin(), points.end(),
point, vec,
std::back_inserter(coords),
Kernel()
);
auto intp = CGAL::linear_interpolation(
coords.begin(), coords.end(),
triple.second,
value_access_t(F)
);
auto nomn = f(point);
std::cout << test.first << "([" << point << "])"
<< "\tnominal: " << nomn
<< "\tinterpolated: " << intp
<< "\t\tΔ=" << (intp-nomn)*real_t(100.0)/nomn
<< "%\n";
} // for (auto& test : TESTS)
std::cout << std::endl;
return EXIT_SUCCESS;
} // int main
方式;似乎并不太遥远:
./ cgal_test 10000
l_1 norm([-0.689748 -0.39429 -0.607274]) nominal: 1.69131 interpolated: 1.69079 Δ=-0.0309701%
maximum norm([-0.689748 -0.39429 -0.607274]) nominal: 0.689748 interpolated: 0.689535 Δ=-0.0309701%