mirror of https://github.com/CGAL/cgal
added documentation
renamed weight_functor to weight_function changed some default values of named parameters
This commit is contained in:
parent
d23fb525e5
commit
bc97771d6a
|
|
@ -75,6 +75,7 @@ format.
|
|||
- `CGAL::vcm_estimate_normals()`
|
||||
- `CGAL::vcm_is_on_feature_edge()`
|
||||
- `CGAL::structure_point_set()`
|
||||
- `CGAL::poisson_eliminate()`
|
||||
|
||||
\cgalCRPSection{I/O (All Formats)}
|
||||
|
||||
|
|
|
|||
|
|
@ -650,7 +650,7 @@ functions in this component.)
|
|||
\section Point_set_processing_3Simplification Simplification
|
||||
|
||||
|
||||
Four simplification functions are devised to reduce an input point set.
|
||||
Five simplification functions are devised to reduce an input point set.
|
||||
|
||||
Function `random_simplify_point_set()` randomly deletes a
|
||||
user-specified fraction of points from the input point set. This
|
||||
|
|
@ -674,6 +674,10 @@ Function `wlop_simplify_and_regularize_point_set()` not only simplifies,
|
|||
but also regularizes downsampled points. This is an implementation of
|
||||
the Weighted Locally Optimal Projection (WLOP) algorithm \cgalCite{wlop-2009}.
|
||||
|
||||
Function `poisson_eliminate()` is a greedy down sampling method that generates
|
||||
a subset of the input points with poisson disk property. This is an implementation of the
|
||||
Sample Elimination for Generating Poisson Disk Sample Sets \cgalCite{cgal:y-sefpdss}.
|
||||
|
||||
|
||||
\subsection Point_set_processing_3Example_grid_simplification Grid Simplification Example
|
||||
|
||||
|
|
@ -755,6 +759,37 @@ for more details. We provide below a speed-up chart generated using the parallel
|
|||
Parallel WLOP speed-up, compared to the sequential version of the algorithm.
|
||||
\cgalFigureEnd
|
||||
|
||||
\subsection Point_set_processing_3PoissonElimination Poisson Sample Elimination
|
||||
The poisson sample elimination is a greedy downsampling method that calculates a weight for each input point based on the density of its local neighborhood. Subsequently, the point with the highest weight is removed and the weights of the remaining points around it are updated until the target size is reached. A custom function to calculate the weight of a point can be provided.
|
||||
|
||||
The poisson sample elimination has the following parameters:
|
||||
- *dimensions*: The dimensions parameter specifies the dimension of the sampling domain of the point cloud, e.g., 2 if the point cloud is sampled from a surface, while the ambient dimension is typically 3. The default value is 2.
|
||||
- *weight_function*: A custom *weight_function* can be provided to calculate the weight between two points. The type of the functor is as follows:
|
||||
\code{.cpp}
|
||||
double(*func)(const Point &p, const Point &n, double squared_distance, double r_max)
|
||||
\endcode
|
||||
The default weight is \f$\left(1 - \frac{d_{p,n}}{2r_{max}}\right)^8\f$ with \f$d_{p,n}\f$ being the distance between the point p and its neighbor n.
|
||||
- \f$r_{max}\f$: The \f$r_{max}\f$ parameter specifies the radius of the neighborhood, i.e., the neighboring points that are used to calculate the weight of a point. r_max has to be provided if a custom *weight_function* is used. Only points within a distance of \f$r_{max}\f$ is used to calculate the weight of a point. A large value can thus cause a large running time. The default is calculated based in the bounding volume \f$V\f$ of the input points, the *dimensions* parameter and the number of input points \f$N\f$:
|
||||
|
||||
\f$dimensions = 2:\qquad\f$ \f$r_{max} = \sqrt{\frac{V}{2\sqrt{3}N}}\f$
|
||||
|
||||
\f$dimensions = 3:\qquad\f$ \f$r_{max} = \sqrt{\frac{V}{4\sqrt{2}N}}\f$
|
||||
|
||||
- *progressive*: The output points of the function can be reordered to be progressive. A progressive ordering will increase the running time by at most 2 as the function is internally applied several times on increasingly smaller subsets. The default value is false.
|
||||
|
||||
\cgalFigureAnchor{Point_set_processing_3figPoisson_elimination}
|
||||
<center>
|
||||
<img src="poisson_elimination.png" style="max-width:80%;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{Point_set_processing_3figPoisson_elimination}
|
||||
Poisson elimination on point cloud with 21k points and results with \f$\frac{1}{2}\f$, \f$\frac{1}{4}\f$ and \f$\frac{1}{8}\f$ of the input size.
|
||||
\cgalFigureCaptionEnd
|
||||
|
||||
\subsection Point_set_processing_3Example_poisson_elimination Poisson Sample Elimination Example
|
||||
|
||||
The following example reads a point cloud, applies poisson elimination to reduce the point cloud to \f$\frac{1}{5}\f$ of its size and saves it into a file.
|
||||
|
||||
\cgalExample{Point_set_processing_3/poisson_eliminate_example.cpp}
|
||||
|
||||
\section Point_set_processing_3Smoothing Smoothing
|
||||
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@
|
|||
\example Point_set_processing_3/edges_example.cpp
|
||||
\example Point_set_processing_3/structuring_example.cpp
|
||||
\example Point_set_processing_3/callback_example.cpp
|
||||
\example Point_set_processing_3/poisson_eliminate_example.cpp
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 38 KiB |
|
|
@ -141,13 +141,3 @@ if(TARGET CGAL::Eigen3_support)
|
|||
else()
|
||||
message(STATUS "NOTICE: Some of the executables in this directory require Eigen 3.1 (or greater), and will not be compiled.")
|
||||
endif()
|
||||
|
||||
find_path(CYCODEBASE_INCLUDE "cySampleElim.h" DOC "Path to the cyCodeBase directory (https://github.com/cemyuksel/cyCodeBase)")
|
||||
|
||||
if(NOT CYCODEBASE_INCLUDE)
|
||||
message( STATUS "poisson_eliminate_example will be compiled without the cyCodeBase library (https://github.com/cemyuksel/cyCodeBase)")
|
||||
else()
|
||||
message(CYCODEBASE_INCLUDE="${CYCODEBASE_INCLUDE}")
|
||||
target_compile_definitions( poisson_eliminate_example PRIVATE CGAL_USE_CY )
|
||||
target_include_directories( poisson_eliminate_example AFTER PRIVATE ${CYCODEBASE_INCLUDE} )
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -8,12 +8,15 @@
|
|||
#include <CGAL/poisson_eliminate.h>
|
||||
#include <CGAL/IO/write_points.h>
|
||||
#include <CGAL/IO/read_points.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> K;
|
||||
typedef K::Point_3 Point_3;
|
||||
|
||||
void sampling(const std::string& filename) {
|
||||
void sampling(const std::string& filename, double size_factor = 0.2) {
|
||||
if (size_factor >= 1.0) {
|
||||
std::cout << "usage poisson_eliminate_example filename size_factor" << std::endl << "0 < size_factor < 1" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::vector<Point_3> points;
|
||||
|
||||
if (!CGAL::IO::read_points(
|
||||
|
|
@ -24,54 +27,13 @@ void sampling(const std::string& filename) {
|
|||
return;
|
||||
}
|
||||
|
||||
std::size_t target_size = points.size() / 5;
|
||||
|
||||
bool progressive = true;
|
||||
bool weight_limiting = false;
|
||||
bool tiling = false;
|
||||
std::size_t target_size = std::size_t(points.size() * size_factor);
|
||||
std::vector<Point_3> output;
|
||||
|
||||
#ifdef CGAL_USE_CY
|
||||
std::vector<cy::Vec3d> inputPoints, outputPoints;
|
||||
std::vector<Point_3> out;
|
||||
|
||||
for (int i = 0; i < points.size(); ++i)
|
||||
inputPoints.push_back(cy::Vec3d(CGAL::to_double(points[i].x()), CGAL::to_double(points[i].y()), CGAL::to_double(points[i].z())));
|
||||
|
||||
outputPoints.resize(target_size);
|
||||
|
||||
CGAL::Bbox_3 bb = CGAL::bbox_3(points.begin(), points.end());
|
||||
cy::Vec3d bl(bb.xmin(), bb.ymin(), bb.zmin());
|
||||
cy::Vec3d tr(bb.xmax(), bb.ymax(), bb.zmax());
|
||||
|
||||
cy::WeightedSampleElimination< cy::Vec3d, double, 3, int > wse;
|
||||
wse.SetBoundsMin(bl);
|
||||
wse.SetBoundsMax(tr);
|
||||
wse.SetTiling(tiling);
|
||||
#endif
|
||||
|
||||
output.reserve(target_size);
|
||||
CGAL::Real_timer timer;
|
||||
timer.start();
|
||||
CGAL::poisson_eliminate(points, target_size, std::back_inserter(output), CGAL::parameters::progressive(progressive).weight_limiting(weight_limiting).tiling(tiling));
|
||||
timer.stop();
|
||||
std::cout << std::endl << timer.time() << std::endl;
|
||||
|
||||
CGAL::poisson_eliminate(points, target_size, std::back_inserter(output));
|
||||
|
||||
CGAL::IO::write_points("out.xyz", output, CGAL::parameters::stream_precision(17));
|
||||
|
||||
#ifdef CGAL_USE_CY
|
||||
timer.reset();
|
||||
timer.start();
|
||||
wse.SetWeightLimiting(weight_limiting);
|
||||
wse.Eliminate(inputPoints.data(), int(inputPoints.size()),
|
||||
outputPoints.data(), int(outputPoints.size()), progressive);
|
||||
timer.stop();
|
||||
std::cout << timer.time() << std::endl;
|
||||
|
||||
for (const cy::Vec3d& p : outputPoints) {
|
||||
out.push_back(Point_3(p.x, p.y, p.z));
|
||||
}
|
||||
CGAL::IO::write_points("out_ref.xyz", out, CGAL::parameters::stream_precision(17));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -79,8 +41,10 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
if (argc < 2)
|
||||
sampling(CGAL::data_file_path("points_3/radar.xyz"));
|
||||
else
|
||||
else if (argc < 3)
|
||||
sampling(argv[1]);
|
||||
else if (argc < 4)
|
||||
sampling(argv[1], std::atof(argv[2]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,11 +118,12 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<class Point>
|
||||
class Weight_functor {
|
||||
public:
|
||||
Weight_functor(double r_min = 0, double alpha = 8) : r_min(CGAL::to_double(r_min)), alpha(CGAL::to_double(alpha)) {}
|
||||
|
||||
double operator()(double d2, double r_max) {
|
||||
double operator()(const Point &, const Point &, double d2, double r_max) {
|
||||
double d = CGAL::sqrt(d2);
|
||||
if (d < r_min) d = r_min;
|
||||
return std::pow(double(1) - d / r_max, alpha);
|
||||
|
|
@ -197,6 +198,12 @@ void pop_heap(std::vector<std::size_t>& heap, std::vector<std::size_t>& heap_pos
|
|||
\cgalParamDefault{`CGAL::Identity_property_map<geom_traits::Point_3>`}
|
||||
\cgalParamNEnd
|
||||
|
||||
\cgalParamNBegin{dimension}
|
||||
\cgalParamDescription{The sampling domain of `points`, e.g., 2 if the points have been sampled from a 2d surface.}
|
||||
\cgalParamType{unsigned integer}
|
||||
\cgalParamDefault{2}
|
||||
\cgalParamNEnd
|
||||
|
||||
\cgalParamNBegin{progressive}
|
||||
\cgalParamDescription{reorders the points in `output` in a progressive way, i.e., the first n points in `output` with n < `number_of_points` have a poisson disk distribution with a larger radius. }
|
||||
\cgalParamType{Boolean}
|
||||
|
|
@ -206,11 +213,13 @@ void pop_heap(std::vector<std::size_t>& heap, std::vector<std::size_t>& heap_pos
|
|||
\cgalParamNBegin{maximum_radius}
|
||||
\cgalParamDescription{radius of the poisson disk in which the neighboring points are taken into account for elimination.}
|
||||
\cgalParamType{double}
|
||||
\cgalParamDefault{the default is calculated from the `dimension`, the volume of the bounding box and the `number_of_points`. For more details, see \ref Point_set_processing_3PoissonElimination.}
|
||||
\cgalParamNEnd
|
||||
|
||||
\cgalParamNBegin{weight_functor}
|
||||
\cgalParamDescription{a weight functor that calculates the weight of a neighbor point based on its squared distance and the `maximum_radius`.}
|
||||
\cgalParamType{an instance of `std::function<double(double,double)>`.}
|
||||
\cgalParamNBegin{weight_function}
|
||||
\cgalParamDescription{a weight function that calculates the weight of a neighbor point based on its squared distance and the `maximum_radius`.}
|
||||
\cgalParamType{an instance of `std::function<double(const Point&, const Point&, double,double)>`.}
|
||||
\cgalParamDefault{See \ref Point_set_processing_3PoissonElimination.}
|
||||
\cgalParamNEnd
|
||||
|
||||
\cgalParamNBegin{geom_traits}
|
||||
|
|
@ -227,8 +236,8 @@ void poisson_eliminate(PointRange points, std::size_t number_of_points, OutputIt
|
|||
|
||||
using NP_helper = Point_set_processing_3_np_helper<PointRange, NamedParameters>;
|
||||
using PointMap = typename NP_helper::Point_map;
|
||||
using Point = typename boost::property_traits<PointMap>::value_type;
|
||||
using GeomTraits = typename Kernel_traits<Point>::Kernel;
|
||||
using Point = typename NP_helper::Point;
|
||||
using GeomTraits = typename NP_helper::Geom_traits;
|
||||
using FT = typename GeomTraits::FT;
|
||||
using IPM = internal::Indexed_extended_point_map<PointRange, PointMap>;
|
||||
PointMap point_map = NP_helper::get_point_map(points, np);
|
||||
|
|
@ -255,13 +264,13 @@ void poisson_eliminate(PointRange points, std::size_t number_of_points, OutputIt
|
|||
// named parameter for tiling
|
||||
const bool tiling = parameters::choose_parameter(parameters::get_parameter(np, internal_np::tiling), false);
|
||||
const unsigned int ambient_dimension = CGAL::Ambient_dimension<Point>::value;
|
||||
const unsigned int dimension = parameters::choose_parameter(parameters::get_parameter(np, internal_np::dimension), ambient_dimension);
|
||||
const unsigned int dimension = parameters::choose_parameter(parameters::get_parameter(np, internal_np::dimension), 2);
|
||||
|
||||
// named parameter for r_max
|
||||
double r_max = CGAL::to_double(parameters::choose_parameter(parameters::get_parameter(np, internal_np::maximum_radius), 2 * internal::get_maximum_radius(dimension, number_of_points, domain_size)));
|
||||
double r_min = CGAL::to_double(weight_limiting ? internal::get_minimum_radius(points.size(), number_of_points, beta, gamma, r_max) : 0);
|
||||
|
||||
auto weight_functor = parameters::choose_parameter(parameters::get_parameter(np, internal_np::weight_functor), internal::Weight_functor(r_min, alpha));
|
||||
auto weight_functor = parameters::choose_parameter(parameters::get_parameter(np, internal_np::weight_function), internal::Weight_functor<Point>(r_min, alpha));
|
||||
|
||||
std::size_t heap_size = points.size();
|
||||
std::vector<Point> tiling_points;
|
||||
|
|
@ -325,7 +334,7 @@ void poisson_eliminate(PointRange points, std::size_t number_of_points, OutputIt
|
|||
|
||||
const Point p2 = get(ipm, res[n]);
|
||||
double d2 = CGAL::to_double((p - p2).squared_length());
|
||||
weights[i] += weight_functor(d2, r_max);
|
||||
weights[i] += weight_functor(p, p2, d2, r_max);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +365,7 @@ void poisson_eliminate(PointRange points, std::size_t number_of_points, OutputIt
|
|||
const Point p2 = get(point_map, points[res[n]]);
|
||||
double d2 = CGAL::to_double((p - p2).squared_length());
|
||||
|
||||
weights[res[n]] -= weight_functor(d2, r_max);
|
||||
weights[res[n]] -= weight_functor(p2, p, d2, r_max);
|
||||
|
||||
internal::move_down(heap, heap_pos, heap_size, weights, heap_pos[res[n]]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <CGAL/poisson_eliminate.h>
|
||||
#include <CGAL/compute_average_spacing.h>
|
||||
#include <CGAL/IO/read_points.h>
|
||||
#include <CGAL/IO/write_points.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
template<class K>
|
||||
|
|
@ -49,17 +50,24 @@ void sampling(const std::string& filename, Check_distance_functor check_average_
|
|||
|
||||
std::cout << " " << points.size() << " input points" << std::endl;
|
||||
|
||||
std::size_t target_size = points.size() / 5;
|
||||
std::size_t target_size = points.size() / 3;
|
||||
|
||||
bool progressive = true;
|
||||
bool weight_limiting = false;
|
||||
bool tiling = false;
|
||||
std::vector<Point_3> output;
|
||||
|
||||
CGAL::Real_timer timer;
|
||||
|
||||
output.reserve(target_size);
|
||||
CGAL::poisson_eliminate(points, target_size, std::back_inserter(output), CGAL::parameters::progressive(progressive).weight_limiting(weight_limiting).tiling(tiling));
|
||||
timer.start();
|
||||
CGAL::poisson_eliminate(points, target_size, std::back_inserter(output), CGAL::parameters::dimension(2).progressive(progressive).weight_limiting(weight_limiting).tiling(tiling));
|
||||
timer.stop();
|
||||
std::cout << timer.time() << std::endl;
|
||||
std::cout << " " << output.size() << " points after elimination" << std::endl;
|
||||
|
||||
CGAL::IO::write_points("radar" + std::to_string(target_size) + "_2d.xyz", output, CGAL::parameters::stream_precision(17));
|
||||
|
||||
assert(output.size() == target_size);
|
||||
|
||||
check_average_distance(points, output, progressive);
|
||||
|
|
@ -73,11 +81,11 @@ int main(int argc, char* argv[])
|
|||
std::cout << "testing Simple_cartesian<double>" << std::endl;
|
||||
sampling<CGAL::Simple_cartesian<double>>(CGAL::data_file_path("points_3/radar.xyz"), check< CGAL::Simple_cartesian<double>>);
|
||||
|
||||
std::cout << std::endl << "testing Exact_predicates_inexact_constructions_kernel" << std::endl;
|
||||
sampling<CGAL::Exact_predicates_inexact_constructions_kernel>(CGAL::data_file_path("points_3/radar.xyz"), check< CGAL::Exact_predicates_inexact_constructions_kernel>);
|
||||
std::cout << std::endl << "testing Exact_predicates_inexact_constructions_kernel" << std::endl;
|
||||
sampling<CGAL::Exact_predicates_inexact_constructions_kernel>(CGAL::data_file_path("points_3/radar.xyz"), check< CGAL::Exact_predicates_inexact_constructions_kernel>);
|
||||
|
||||
std::cout << std::endl << "testing Exact_predicates_exact_constructions_kernel" << std::endl;
|
||||
sampling<CGAL::Exact_predicates_exact_constructions_kernel>(CGAL::data_file_path("points_3/radar.xyz"), no_check);
|
||||
std::cout << std::endl << "testing Exact_predicates_exact_constructions_kernel" << std::endl;
|
||||
sampling<CGAL::Exact_predicates_exact_constructions_kernel>(CGAL::data_file_path("points_3/radar.xyz"), no_check);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ CGAL_add_named_parameter(region_primitive_map_t, region_primitive_map, region_pr
|
|||
CGAL_add_named_parameter(postprocess_regions_t, postprocess_regions, postprocess_regions)
|
||||
CGAL_add_named_parameter(sizing_function_t, sizing_function, sizing_function)
|
||||
CGAL_add_named_parameter(bbox_scaling_t, bbox_scaling, bbox_scaling)
|
||||
CGAL_add_named_parameter(weight_functor_t, weight_functor, weight_functor)
|
||||
CGAL_add_named_parameter(weight_function_t, weight_function, weight_function)
|
||||
CGAL_add_named_parameter(weight_limiting_t, weight_limiting, weight_limiting)
|
||||
CGAL_add_named_parameter(progressive_t, progressive, progressive)
|
||||
CGAL_add_named_parameter(tiling_t, tiling, tiling)
|
||||
|
|
|
|||
Loading…
Reference in New Issue