CGAL学习记录——Geometry Processing(几何处理篇)-3D Point Set

一、用户手册

链接:3D Point Set

功能如下:

在这里插入图片描述

二、代码实现

点的设置(插入点、法线、删除点等)

point_set.cpp

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <fstream>
#include <limits>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;

void print_point_set_initial(const Point_set& point_set)
{
    std::cerr << "Content of point set:" << std::endl;
    for (Point_set::const_iterator it = point_set.begin();
        it != point_set.end(); ++it)
        std::cerr << "* Point " << *it
        << ": " << point_set.point(*it) // or point_set[it]
        << std::endl;
}

void print_point_set(const Point_set& point_set)
{
    std::cerr << "Content of point set:" << std::endl;
    for (Point_set::const_iterator it = point_set.begin();
        it != point_set.end(); ++it)
        std::cerr << "* Point " << *it
        << ": " << point_set.point(*it) // or point_set[it]
        << " with normal " << point_set.normal(*it)
        << std::endl;
}
int main(int, char**)
{
    Point_set point_set;

    //添加点
    point_set.insert(Point(0., 0., 0.));
    point_set.insert(Point(0., 0., 1.));
    point_set.insert(Point(0., 1., 0.));
    
    print_point_set_initial(point_set);

    //初始化法线
    point_set.add_normal_map();
    print_point_set(point_set); 

    //改变法线
    Point_set::iterator it = point_set.begin();
    point_set.normal(*(it++)) = Vector(1., 0., 0.);
    point_set.normal(*(it++)) = Vector(0., 1., 0.);
    point_set.normal(*(it++)) = Vector(0., 0., 1.);
    

    //增加法线的点
    point_set.insert(Point(1., 2., 3.), Vector(4., 5., 6.));
    print_point_set(point_set);

    // Add new item
    Point_set::iterator new_item = point_set.insert(Point(7., 8., 9.));
    point_set.normal(*new_item) = Vector(10., 11., 12.);
    print_point_set(point_set); // New item has default values


    //剔除[1,4)的点,左闭右开
    point_set.remove(point_set.begin() + 1,point_set.begin() + 4);
    print_point_set(point_set); // New item has default values
    // 显示信息
    std::cerr << "Number of removed points: " << point_set.number_of_removed_points() << std::endl;

    //清理garbage
    point_set.collect_garbage();
    std::cerr << "After garbage collection: " << point_set.number_of_removed_points() << std::endl;

    std::system("pause");
    return 0;
}

点的属性设置(增肌颜色、强度信息)

point_set_property.cpp

//设置点的属性,包括颜色信息与强度信息

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Random.h>
#include <fstream>
#include <limits>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef std::array<unsigned char, 3> Color;
typedef CGAL::Point_set_3<Point> Point_set;
typedef Point_set::Property_map<Color> Color_map;
typedef Point_set::Property_map<FT> FT_map;

void print_point_set(const Point_set& point_set)
{
    Color_map color;
    boost::tie(color, boost::tuples::ignore) = point_set.property_map<Color>("color");
    FT_map intensity;
    boost::tie(intensity, boost::tuples::ignore) = point_set.property_map<FT>("intensity");
    std::cerr << "Content of point set:" << std::endl;
    for (Point_set::const_iterator it = point_set.begin(); it != point_set.end(); ++it)
    {
        std::cerr << "* Point " << point_set.point(*it) // or point_set[it]
            << " with color [" << static_cast<int>(color[*it][0])
            << " " << static_cast<int>(color[*it][1])
            << " " << static_cast<int>(color[*it][2])
            << "] and intensity " << intensity[*it]
            << std::endl;
    }
}
int main(int, char**)
{
    Point_set point_set;
    Color black = { { 0, 0, 0 } };
    bool success = false;
    Color_map color;
    boost::tie(color, success) = point_set.add_property_map<Color>("color", black);
    assert(success);
    FT_map intensity;
    boost::tie(intensity, success) = point_set.add_property_map<FT>("intensity", 0.);
    assert(success);
    point_set.reserve(10); // 点云个数

    for (std::size_t i = 0; i < 10; ++i)
    {
        Point_set::iterator it = point_set.insert(Point(double(i), double(i), double(i)));
        Color c = { { static_cast<unsigned char>(CGAL::get_default_random().get_int(0, 255)),
                     static_cast<unsigned char>(CGAL::get_default_random().get_int(0, 255)),
                     static_cast<unsigned char>(CGAL::get_default_random().get_int(0, 255)) } };
        color[*it] = c;
        intensity[*it] = rand() / static_cast<double>(RAND_MAX);
    }
    print_point_set(point_set);

    // 剔除强度小于 0.5的点
    Point_set::iterator it = point_set.begin();
    while (it != point_set.end())
    {
        if (intensity[*it] < 0.5)
            point_set.remove(it);
        else
            ++it;
    }
    print_point_set(point_set); // point set is filtered
    std::system("pause");
    return 0;
}

点的基本算法运用(体素采样,法线估计,球形检测)

point_set_algo.cpp

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/jet_estimate_normals.h>
#include <CGAL/grid_simplify_point_set.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/Shape_detection/Efficient_RANSAC.h>
#include <fstream>
#include <limits>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Random_points_on_sphere_3<Point> Point_generator;
typedef CGAL::Point_set_3<Point> Point_set;
typedef CGAL::Shape_detection::Efficient_RANSAC_traits
<Kernel, Point_set, Point_set::Point_map, Point_set::Vector_map> Traits;
typedef CGAL::Shape_detection::Efficient_RANSAC<Traits>          Efficient_ransac;
typedef CGAL::Shape_detection::Sphere<Traits>                    Sphere;
int main(int, char**)
{
    Point_set point_set;
    // 生成一个球
    Point_generator generator(1.);
    std::size_t nb_pts = 10000;
    point_set.reserve(nb_pts);
    for (std::size_t i = 0; i < nb_pts; ++i) point_set.insert(*(generator++));
    if (!CGAL::IO::write_OFF("rst1.off", point_set, CGAL::parameters::stream_precision(17)))
        return EXIT_FAILURE;

    //体素采样
    point_set.remove(CGAL::grid_simplify_point_set(point_set, 0.1), point_set.end());
    if (!CGAL::IO::write_OFF("rst_grid.off", point_set, CGAL::parameters::stream_precision(17)))
        return EXIT_FAILURE;

    //计算法线
    point_set.add_normal_map();
    CGAL::jet_estimate_normals<CGAL::Sequential_tag>
        (point_set, 12, // Number of neighbors
            point_set.parameters(). // Named parameters provided by Point_set_3
            degree_fitting(2));     // additional named parameter specific to jet_estimate_normals

    if (!CGAL::IO::write_OFF("rst_normals.off", point_set, CGAL::parameters::stream_precision(17)))
        return EXIT_FAILURE;

     // point_set.parameters() can be omitted if no additional named parameter is needed
    std::vector<std::string> properties = point_set.properties();
    std::cerr << "Properties:" << std::endl;
    for (std::size_t i = 0; i < properties.size(); ++i)
        std::cerr << " * " << properties[i] << std::endl;

    //球形检测
    Efficient_ransac ransac;
    ransac.set_input(point_set,
        point_set.point_map(), // Call built-in property map
        point_set.normal_map()); // Call built-in property map
    ransac.add_shape_factory<Sphere>();
    Efficient_ransac::Parameters parameters;
    parameters.probability = 0.05;
    parameters.min_points = std::size_t(point_set.size() / 3);
    parameters.epsilon = 0.01;
    parameters.cluster_epsilon = 0.5;
    parameters.normal_threshold = 0.9;
    ransac.detect(parameters);
    for (boost::shared_ptr<Efficient_ransac::Shape> shape : ransac.shapes())
        if (Sphere* sphere = dynamic_cast<Sphere*>(shape.get()))
            std::cerr << "Detected sphere of center " << sphere->center() // Center should be approx 0, 0, 0
            << " and of radius " << sphere->radius() << std::endl; // Radius should be approx 1
    std::system("pause");
    return 0;
}

问题:
在这里插入图片描述
解决方案:
在这里插入图片描述
需要添加依赖库Eigen,我直接添加了PCL属性表,测试OK。

在这里插入图片描述

读取XYZ文件

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <fstream>
#include <limits>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main(int argc, char** argv)
{
    const std::string fname = argc > 1 ? argv[1] : CGAL::data_file_path("test.xyz");
    // Reading input
    Point_set point_set;
    if (!CGAL::IO::read_XYZ(fname, point_set))
    {
        std::cerr << "Can't read input file " << std::endl;
        return EXIT_FAILURE;
    }
    point_set.add_normal_map();
    if (point_set.has_normal_map())
    {
        // 法线归一化并反转
        for (Point_set::iterator it = point_set.begin(); it != point_set.end(); ++it)
        {
            Vector n = point_set.normal(*it);
            n = -n / std::sqrt(n * n);
            point_set.normal(*it) = n;
        }
    }
    // Writing result in OFF format
    if (!CGAL::IO::write_OFF("cloud_normals.off", point_set))
        return EXIT_FAILURE;

    //CGAL::parameters::stream_precision(17) 表示小数点精度
    if (!CGAL::IO::write_OFF("normalized_normals.off", point_set, CGAL::parameters::stream_precision(17)))
        return EXIT_FAILURE;
    return EXIT_SUCCESS;
}

读取PLY文件

ply

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <fstream>
#include <limits>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main(int argc, char** argv)
{
    std::ifstream f(argc > 1 ? argv[1] : CGAL::data_file_path("bunny.ply"),
        std::ios_base::binary); // Mandatory on Windows if input is binary PLY
    Point_set point_set;
    if (!CGAL::IO::read_PLY(f, point_set)) // same as `f >> point_set`
    {
        std::cerr << "Can't read input file " << std::endl;
        return EXIT_FAILURE;
    }
    // Shows which properties are defined
    std::vector<std::string> properties = point_set.properties();
    std::cerr << "Properties:" << std::endl;
    for (std::size_t i = 0; i < properties.size(); ++i)
        std::cerr << " * " << properties[i] << std::endl;
    // Recover "label" property of type int
    Point_set::Property_map<boost::int32_t> label_prop;
    bool found = false;
    boost::tie(label_prop, found) = point_set.property_map<boost::int32_t>("label");
    if (found)
    {
        std::cerr << "Point set has an integer \\"label\\" property with values:" << std::endl;
        for (Point_set::iterator it = point_set.begin(); it != point_set.end(); ++it)
            std::cerr << " * " << label_prop[*it] << std::endl;
    }
    if (argc > 2 && strcmp(argv[2], "-b") == 0) // Optional binary output
    {
        CGAL::IO::write_PLY("out.ply", point_set, CGAL::parameters::stream_precision(17));
    }
    else // ASCII output
    {
        CGAL::IO::write_PLY("out.ply", point_set, CGAL::parameters::stream_precision(17)
            .use_binary_mode(false));
    }
    return 0;
}

读取OFF格式文件


#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/IO/read_points.h>
#include <fstream>
#include <limits>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main(int argc, char** argv)
{
    const std::string filename = argc > 1 ? argv[1] : CGAL::data_file_path("test.off");
    Point_set point_set;
    point_set.add_normal_map();
    // Reading input in OFF format
    if (!CGAL::IO::read_points(filename, point_set.index_back_inserter(),
        CGAL::parameters::point_map(point_set.point_push_map())
        .normal_map(point_set.normal_push_map())))
    {
        std::cerr << "Can't read input file " << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

点云显示

已在上一篇博客写出:点云显示

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/draw_point_set_3.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main (int argc, char** argv)
{
  const std::string filename = argc > 1 ? argv[1] : CGAL::data_file_path("points_3/oni.pwn");
  Point_set point_set;
  if(!CGAL::IO::read_point_set(filename, point_set))
  {
    std::cerr << "Can't read input file " << filename << std::endl;
    return EXIT_FAILURE;
  }
  CGAL::draw(point_set);
  return EXIT_SUCCESS;
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片