CGAL 3D函数插值

时间:2014-07-15 19:31:21

标签: 3d interpolation cgal

在CGAL手册中,它说here

  

分散数据插值解决了以下问题:给定一组数据点上的函数测量,任务是在任意查询点上插入此函数。更正式地,让P = {p1,...,pn}是R2或R3中的n个点的集合,并且Φ是在P的凸包上定义的标量函数。我们假设函数值在P的点处是已知的。 ,即对每个pi∈P,我们将zi =Φ(pi)。

联系起来

然后它继续显示示例,但我找到的最接近 3D 插值的示例是示例Interpolation/surface_neighbor_coordinates_3.cpp。据我所知,这只能找到一个点的邻居顶点。

我是否可以采取后续步骤在3D中的任意查询点找到插值函数值? (具体来说,在球体上?)

2 个答案:

答案 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%