# 二、代码实现

## 点的设置（插入点、法线、删除点等）

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);

//初始化法线
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);

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;
assert(success);
FT_map intensity;
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;

//计算法线
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
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
std::system("pause");
return 0;
}

``````

## 读取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");
Point_set point_set;
{
std::cerr << "Can't read input file " << std::endl;
return EXIT_FAILURE;
}
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 <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;
// Reading input in OFF format
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;
{
std::cerr << "Can't read input file " << filename << std::endl;
return EXIT_FAILURE;
}
CGAL::draw(point_set);
return EXIT_SUCCESS;
}
``````