【问题标题】:CGAL 3D Function InterpolationCGAL 3D 函数插值
【发布时间】:2014-09-06 03:30:11
【问题描述】:

在 CGAL 手册中,它说here

分散数据插值解决了以下问题:给定函数对一组数据点的度量,任务是在任意查询点上对该函数进行插值。更正式地说,令 P={p1,…,pn} 是 R2 或 R3 中的 n 个点的集合,Φ 是定义在 P 的凸包上的标量函数。我们假设函数值在 P 的点处是已知的,即对于每个 pi∈P,我们关联 zi=Φ(pi)。

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

我是否可以采取后续步骤在 3D 中的任意查询点找到 内插函数值? (特别是在一个球体上?)

【问题讨论】:

  • 从 7 月中旬开始,您找到解决方案了吗?
  • 基本上,我现在的解决方案是:3D Delaunay 三角剖分,将凸包转换为多面体,制作一棵树,然后在树中使用“closest_point_and_primitive”查找任何查询点。之后,我使用该点周围的 3 个邻居进行自己的球面三角形面积计算,并根据这些子区域占据的整个球面面积的百分比对这三个数据值进行加权。 3D 插值。制作...简单...
  • 关于Stack Overflow的知识库,能否请您自答一下并接受?

标签: 3d interpolation cgal


【解决方案1】:

same page you quote, at the section "3 Interpolation Methods"中有插值方法的说明,有两个例子。这可能是您正在寻找的。不过,您必须将这些示例调整为 3D。

【讨论】:

    【解决方案2】:

    将 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%
    

    【讨论】:

    • 非常感谢您的建议!我会看看它,我已经放弃了这个问题,因为我受到时间限制,不得不继续前进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 2014-08-10
    • 1970-01-01
    相关资源
    最近更新 更多