From dceddbe418b73003499b4e3f3ef9fc8c49ee13b6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Jan 2017 15:25:43 +0100 Subject: [PATCH] Rework reference manual --- .../CGAL/Classification/Attribute_base.h | 9 +- .../Classification/Local_eigen_analysis.h | 12 +- .../CGAL/Classification/Planimetric_grid.h | 12 +- .../Classification/Point_set_neighborhood.h | 10 +- .../include/CGAL/Classification/Type.h | 12 +- Classification/include/CGAL/Classifier.h | 156 +++-- .../include/CGAL/Point_set_classifier.h | 648 +++++++++--------- .../Scene_point_set_classification_item.h | 2 +- 8 files changed, 430 insertions(+), 431 deletions(-) diff --git a/Classification/include/CGAL/Classification/Attribute_base.h b/Classification/include/CGAL/Classification/Attribute_base.h index 33ab061c67c..f62f719645d 100644 --- a/Classification/include/CGAL/Classification/Attribute_base.h +++ b/Classification/include/CGAL/Classification/Attribute_base.h @@ -60,13 +60,14 @@ public: /*! \brief Returns `abstract_attribute` and should be overloaded - by a inherited class with a specific name. + by an inherited class with a specific name. */ virtual std::string name() { return "abstract_attribute"; } /*! - \brief Returns the value taken by the attribute at the given - index. This method must be implemented by inherited classes. + \brief Returns the value taken by the attribute for at the item at + position `index`. This method must be implemented by inherited + classes. */ virtual double value (std::size_t index) = 0; @@ -106,7 +107,7 @@ public: /*! \ingroup PkgClassification - \brief Handle to a classification `Attribute_base`. + \brief Handle to an `Attribute_base`. \cgalModels Handle */ diff --git a/Classification/include/CGAL/Classification/Local_eigen_analysis.h b/Classification/include/CGAL/Classification/Local_eigen_analysis.h index 828339536da..0864af22dd6 100644 --- a/Classification/include/CGAL/Classification/Local_eigen_analysis.h +++ b/Classification/include/CGAL/Classification/Local_eigen_analysis.h @@ -63,9 +63,9 @@ public: on a local neighborhood. \tparam NeighborQuery model of `NeighborQuery` - \param input Input range. + \param input input range. \param point_map property map to access the input points - \param neighbor_query object used to access neighborhoods of points + \param neighbor_query object used to access neighborhoods of points. */ template Local_eigen_analysis (const Range& input, @@ -99,22 +99,22 @@ public: } /*! - \brief Returns the estimated unoriented normal vector of the indexed point. + \brief Returns the estimated unoriented normal vector of the point at position `index`. */ const Vector& normal_vector (std::size_t index) const { return m_smallest_eigenvectors[index]; } /*! - \brief Returns the estimated local tangent plane of the index point. + \brief Returns the estimated local tangent plane of the point at position `index`. */ Plane plane (std::size_t index) const { return Plane (m_centroids[index], m_smallest_eigenvectors[index]); } /*! - \brief Returns the normalized eigenvalues of the index point. + \brief Returns the normalized eigenvalues of the point at position `index`. */ const Eigenvalues& eigenvalue (std::size_t index) const { return m_eigenvalues[index]; } /*! - \brief Returns the sum of eigenvalues of the index point. + \brief Returns the sum of eigenvalues of the point at position `index`. */ const double& sum_of_eigenvalues (std::size_t index) const { return m_sum_eigenvalues[index]; } diff --git a/Classification/include/CGAL/Classification/Planimetric_grid.h b/Classification/include/CGAL/Classification/Planimetric_grid.h index e1384f3a435..fad4283b94c 100644 --- a/Classification/include/CGAL/Classification/Planimetric_grid.h +++ b/Classification/include/CGAL/Classification/Planimetric_grid.h @@ -14,10 +14,10 @@ namespace Classification { \brief Class that precomputes a 2D planimetric grid. - The grid is composed of squared cells with a user defined size, + The grid is composed of squared cells with a user-defined size, each cell containing the list of indices of the points whose projection along the Z-axis lies within this cell. The mapping - from each point to the its cell is also stored. + from each point to the cell it lies in is also stored. \tparam Kernel model of \cgal Kernel. \tparam Range range of items, model of `ConstRange`. Its iterator type @@ -85,21 +85,21 @@ public: std::size_t height() const { return m_grid.height(); } /*! - \brief Returns the indices of points lying in the given indexed cell. + \brief Returns the indices of the points lying in the cell at position `(x,y)`. */ const std::vector& indices(std::size_t x, std::size_t y) const { return m_grid(x,y); } /*! - \brief Returns `false` if the cell indexed by `(x,y)` is empty, `true` otherwise. + \brief Returns `false` if the cell at position `(x,y)` is empty, `true` otherwise. */ bool mask(std::size_t x, std::size_t y) const { return (!(m_grid(x,y).empty())); } /*! - \brief Returns the `x` coordinate of the indexed point in the grid. + \brief Returns the `x` grid coordinate of the point at position `index`. */ std::size_t x(std::size_t index) const { return m_x[index]; } /*! - \brief Returns the `y` coordinate of the indexed point in the grid. + \brief Returns the `y` grid coordinate of the point at position `index`. */ std::size_t y(std::size_t index) const { return m_y[index]; } }; diff --git a/Classification/include/CGAL/Classification/Point_set_neighborhood.h b/Classification/include/CGAL/Classification/Point_set_neighborhood.h index 0505cc743d2..74247c81bc8 100644 --- a/Classification/include/CGAL/Classification/Point_set_neighborhood.h +++ b/Classification/include/CGAL/Classification/Point_set_neighborhood.h @@ -94,8 +94,8 @@ public: public: /*! \brief Constructs a K neighbor query object. - \param neighborhood The point set neighborhood structure. - \param k The number of neighbors per query. + \param neighborhood point set neighborhood object. + \param k number of neighbors per query. */ K_neighbor_query (const Point_set_neighborhood& neighborhood, std::size_t k) : neighborhood (neighborhood), k(k) { } @@ -126,8 +126,8 @@ public: public: /*! \brief Constructs a range neighbor query object. - \param neighborhood The point set neighborhood structure. - \param radius The radius of the neighbor query. + \param neighborhood point set neighborhood object. + \param radius radius of the neighbor query sphere. */ Range_neighbor_query (const Point_set_neighborhood& neighborhood, double radius) : neighborhood (neighborhood), radius(radius) { } @@ -242,7 +242,6 @@ private: *(output ++) = it->first; } - /// \cond SKIP_IN_MANUAL template void voxelize_point_set (std::vector& indices, Map point_map, double voxel_size) @@ -285,7 +284,6 @@ private: indices.push_back (chosen); } } - /// \endcond }; diff --git a/Classification/include/CGAL/Classification/Type.h b/Classification/include/CGAL/Classification/Type.h index 2a82a9c877c..44fe7371529 100644 --- a/Classification/include/CGAL/Classification/Type.h +++ b/Classification/include/CGAL/Classification/Type.h @@ -13,7 +13,7 @@ namespace Classification { \ingroup PkgClassification \brief %Classification type (for example: vegetation, ground, etc.) -defined as a set of relationship with classification attributes. +defined as a set of relationships with classification attributes. */ class Type @@ -29,18 +29,12 @@ private: public: /*! - \param name The name of the classification type - (e.g. vegetation). + \param name name of the classification type (e.g. vegetation). */ Type (std::string name) : m_name (name) { } /*! - \brief Sets how an attribute affects the classification type. - - \param att Attribute whose effect on the classification type is set - - \param effect The effect the attribute has on the classification type - + \brief Sets the effect of attribute `att` on the classification type. */ void set_attribute_effect (Attribute_handle att, Attribute::Effect effect) { diff --git a/Classification/include/CGAL/Classifier.h b/Classification/include/CGAL/Classifier.h index 5289635c63b..aef83a589bc 100644 --- a/Classification/include/CGAL/Classifier.h +++ b/Classification/include/CGAL/Classifier.h @@ -58,7 +58,8 @@ namespace CGAL { /*! \ingroup PkgClassification -\brief Classifies a data set based on a set of attribute and a set of classification types. +\brief Classifies a data set based on a set of attributes and a set of +classification types. This class implements the core of the classification algorithm \cgalCite{cgal:lm-clscm-12}. It uses a data set as input and assignes @@ -67,26 +68,23 @@ defined classification types. To achieve this classification algorithm, a set of local geometric attributes are used, such as planarity, elevation or vertical -dispersion. - -The user must define a set of classification types such as building, -ground or vegetation. +dispersion. In addition, the user must define a set of classification +types such as building, ground or vegetation. Each pair of attribute and type must be assigned an [Attribute::Effect](@ref CGAL::Classification::Attribute::Effect) (for example, vegetation has a low planarity and a high vertical dispersion) and each attribute must be assigned a weight. These -parameters can be set up by hand or by providing a training set for -each classification type. +parameters can be set up by hand or by automatic training, provided a +small user defined set of inlier is given for each classification +type. \tparam Range range of items, model of `ConstRange`. Its iterator type is `RandomAccessIterator`. \tparam ItemMap model of `ReadablePropertyMap` whose key type is the value type of the iterator of `Range` and value type is -`Point_3`. - - +the type of the items that are classified. */ template @@ -133,18 +131,22 @@ public: /*! \brief Initializes a classification object. - \param input input range - - \param item_map property map to access the input items + \param input input range. + \param item_map property map to access the input items. */ Classifier (const Range& input, ItemMap item_map) : m_input (input), m_item_map (item_map) { } + /// @} + /// \cond SKIP_IN_MANUAL + virtual ~Classifier() { } + /// \endcond + /// \name Classification /// @{ @@ -197,8 +199,8 @@ public: local neighborhood of items. This method is a compromise between efficiency and reliability. - \tparam NeighborQuery model of `NeighborQuery` - \param neighbor_query used to access neighborhoods of items + \tparam NeighborQuery model of `NeighborQuery`. + \param neighbor_query used to access neighborhoods of items. */ template void run_with_local_smoothing (const NeighborQuery& neighbor_query) @@ -260,8 +262,8 @@ public: an alpha-expansion algorithm. This method is slow but provides the user with good quality results. - \tparam NeighborQuery model of `NeighborQuery` - \param neighbor_query used to access neighborhoods of items + \tparam NeighborQuery model of `NeighborQuery`. + \param neighbor_query used to access neighborhoods of items. \param weight weight of the regularization with respect to the classification energy. Higher values produce more regularized output but may result in a loss of details. @@ -323,7 +325,7 @@ public: /// @{ /*! - \brief Instantiates and adds a classification type. + \brief Adds a classification type. \param name name of the classification type. @@ -336,24 +338,13 @@ public: return out; } - - /*! - \brief Adds a classification type. - - \param type the handle to the classification type that must be added. - */ - void add_classification_type (Type_handle type) - { - m_types.push_back (type); - } - /*! \brief Removes a classification type. \param type the handle to the classification type that must be removed. \return `true` if the classification type was correctly removed, - `false` if its handle was not found inside the object. + `false` if its handle was not found. */ bool remove_classification_type (Type_handle type) { @@ -388,12 +379,15 @@ public: return true; } - /// \cond SKIP_IN_MANUAL + /*! + \brief Returns how many classification types are defined. + */ std::size_t number_of_classification_types () const { return m_types.size(); } - + + /// \cond SKIP_IN_MANUAL Type_handle get_classification_type (std::size_t idx) { return m_types[idx]; @@ -419,7 +413,19 @@ public: \param attribute %Handle of the attribute to add. */ -#if !defined(CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES) && !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) + /*! + \brief Adds an attribute. + + \tparam Attribute type of the attribute, inherited from + `Classification::Attribute_base`. + + \tparam T types of the parameters of the attribute's constructor. + + \param t parameters of the attribute's constructor. + + \return a handle to the newly added attribute. + */ +#if (!defined(CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES) && !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE)) || DOXYGEN_RUNNING template Attribute_handle add_attribute (T&& ... t) { @@ -465,6 +471,33 @@ public: } #endif + /*! + \brief Removes an attribute. + + \param attribute the handle to attribute type that must be removed. + + \return `true` if the attribute was correctly removed, `false` if + its handle was not found. + */ + bool remove_attribute (Attribute_handle attribute) + { + for (std::size_t i = 0; i < m_attributes.size(); ++ i) + if (m_attributes[i] == attribute) + { + m_attributes.erase (m_attributes.begin() + i); + return true; + } + return false; + } + + /*! + \brief Returns how many attributes are defined. + */ + std::size_t number_of_attributes() const + { + return m_attributes.size(); + } + /*! \brief Removes all attributes. */ @@ -473,12 +506,9 @@ public: m_attributes.clear(); } - /// \cond SKIP_IN_MANUAL - std::size_t number_of_attributes() const - { - return m_attributes.size(); - } + + /// \cond SKIP_IN_MANUAL Attribute_handle get_attribute(std::size_t idx) { return m_attributes[idx]; @@ -491,15 +521,12 @@ public: /// @{ /*! - \brief Gets the classification type of an indexed item. + \brief Returns the classification type of the item at position + `index`. \note If classification was not performed (using `run()`, `run_with_local_smoothing()` or `run_with_graphcut()`), this function always returns the default `Type_handle`. - - \param index index of the input item - - \return handle to the classification type */ Type_handle classification_type_of (std::size_t index) const { @@ -529,14 +556,16 @@ public: /// \endcond /*! - \brief Gets the confidence of the classification type of an indexed item. + + \brief Returns the confidence of the classification type of the + item at position `index`. \note If classification was not performed (using `run()`, `run_with_local_smoothing()` or `run_with_graphcut()`), this function always returns 0. - \param index index of the input item - \return confidence ranging from 0 (not confident at all) to 1 (very confident). + \return confidence ranging from 0 (not confident at all) to 1 + (very confident). */ double confidence_of (std::size_t index) const { @@ -555,8 +584,8 @@ public: \brief Runs the training algorithm. All the `Classification::Type` and `Classification::Attribute` - necessary for the classification should have been registered in - the object before running this function. + necessary for the classification should have been added before + running this function. Each classification type must be given a small set of user-defined inliers to provide the training algorithm with a ground truth. @@ -774,20 +803,24 @@ public: /*! - \brief Resets training sets. + \brief Resets inlier sets used for training. */ - void reset_training_sets() + void reset_inlier_sets() { std::vector(m_input.size(), (std::size_t)(-1)).swap (m_training_type); } /*! - \brief Adds the input item specified by index `idx` as an inlier - of `class_type` for the training algorithm. + \brief Adds the item at position `idx` as an inlier of + `class_type` for the training algorithm. - \param class_type handle to the classification type. + \note This inlier is only used for training. There is no guarantee + that the item at position `idx` will be classified as `class_type` + after calling `run()`, `run_with_local_smoothing()` or + `run_with_graphcut()`. - \param idx index of the input item. + \return `true` if the inlier was correctly added, `false` + otherwise (if `class_type` was not found). */ bool set_inlier (Type_handle class_type, std::size_t idx) { @@ -802,18 +835,21 @@ public: return false; if (m_training_type.empty()) - reset_training_sets(); + reset_inlier_sets(); m_training_type[idx] = type_idx; return true; } /*! - \brief Adds input items specified by a range of indices as - inliers of `class_type` for the training algorithm. - \param class_type handle to the classification type. - \param indices Set of incides to add as inliers. + \brief Adds the items at positions `indices` as inliers of + `class_type` for the training algorithm. + + \note These inliers are only used for training. There is no + guarantee that the items at positions `indices` will be classified + as `class_type` after calling `run()`, + `run_with_local_smoothing()` or `run_with_graphcut()`. \tparam IndexRange range of `std::size_t`, model of `ConstRange`. */ @@ -832,7 +868,7 @@ public: return false; if (m_training_type.empty()) - reset_training_sets(); + reset_inlier_sets(); for (typename IndexRange::const_iterator it = indices.begin(); it != indices.end(); ++ it) diff --git a/Classification/include/CGAL/Point_set_classifier.h b/Classification/include/CGAL/Point_set_classifier.h index eefb4ef399c..066048c16d3 100644 --- a/Classification/include/CGAL/Point_set_classifier.h +++ b/Classification/include/CGAL/Point_set_classifier.h @@ -50,7 +50,13 @@ namespace CGAL { /*! \ingroup PkgClassification - \brief TODO + \brief Classifies a point set based on a set of attributes and a set + of classification types. + + This class specializes `Classifier` to point sets. It takes care of + generating necessary data structures and automatically generate a + set of generic attributes. Attributes can be generated at multiple + scales to increase the reliability of the classification. \tparam Kernel model of \cgal Kernel. \tparam Range range of items, model of `ConstRange`. Its iterator type @@ -183,19 +189,93 @@ private: public: - /// \cond SKIP_IN_MANUAL + /// \name Constructor + /// @{ + + /*! + \brief Initializes a classification object. + + \param input input range. + + \param item_map property map to access the input points. + */ Point_set_classifier(const Range& input, PointMap point_map) : Base (input, point_map) { + m_bbox = CGAL::bounding_box + (boost::make_transform_iterator (m_input.begin(), CGAL::Property_map_to_unary_function(m_item_map)), + boost::make_transform_iterator (m_input.end(), CGAL::Property_map_to_unary_function(m_item_map))); + } + + /// @} + + /// \cond SKIP_IN_MANUAL + virtual ~Point_set_classifier() + { + clear(); } /// \endcond + /// \name Attributes + /// @{ - template - const T& get_parameter (const T& t) - { - return t; - } + + /*! + \brief Generate all possible attributes from an input range. + The smallest scale is automatically estimated and the data + structures needed (`Neighborhood`, `Planimetric_grid` and + `Local_eigen_analysis`) are computed at `nb_scales` recursively + larger scales. At each scale, the following attributes are + generated: + + - `CGAL::Classification::Attribute::Anisotropy` + - `CGAL::Classification::Attribute::Distance_to_plane` + - `CGAL::Classification::Attribute::Eigentropy` + - `CGAL::Classification::Attribute::Elevation` + - `CGAL::Classification::Attribute::Linearity` + - `CGAL::Classification::Attribute::Omnivariance` + - `CGAL::Classification::Attribute::Planarity` + - `CGAL::Classification::Attribute::Sphericity` + - `CGAL::Classification::Attribute::Sum_eigenvalues` + - `CGAL::Classification::Attribute::Surface_variation` + - `CGAL::Classification::Attribute::Vertical_dispersion` + + If normal vectors are provided (if `VectorMap` is different from + `CGAL::Default`), the following attribute is generated at each + scale: + + - `CGAL::Classification::Attribute::Vertical_dispersion` + + If colors are provided (if `ColorMap` is different from + `CGAL::Default`), the following attributes are generated at each + scale: + + - 9 attributes `CGAL::Classification::Attribute::Hsv` on + channel 0 (hue) with mean ranging from 0° to 360° and standard + deviation of 22.5. + + - 5 attributes `CGAL::Classification::Attribute::Hsv` on + channel 1 (saturation) with mean ranging from 0 to 100 and standard + deviation of 12.5. + + - 5 attributes `CGAL::Classification::Attribute::Hsv` on channel 2 + (value) with mean ranging from 0 to 100 and standard deviation + of 12.5. + + If echo numbers are provided (if `EchoMap` is different from + `CGAL::Default`), the following attribute is computed at each + scale: + + - `CGAL::Classification::Attribute::Echo_scatter` + + \tparam VectorMap model of `ReadablePropertyMap` with value type `Vector_3`. + \tparam ColorMap model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. + \tparam EchoMap model of `ReadablePropertyMap` with value type `std::size_t`. + \param nb_scales number of scales to compute. + \param normal_map property map to access the normal vectors of the input points (if any). + \param color_map property map to access the colors of the input points (if any). + \param echo_map property map to access the echo values of the input points (if any). + */ template @@ -217,83 +297,75 @@ public: get_parameter(echo_map)); } + /// @} - template - Default_property_map - get_parameter (const Default&) - { - return Default_property_map(); - } - - template - void generate_attributes_impl (std::size_t nb_scales, - VectorMap normal_map, - ColorMap color_map, - EchoMap echo_map) - { - m_bbox = CGAL::bounding_box - (boost::make_transform_iterator (m_input.begin(), - CGAL::Property_map_to_unary_function(m_item_map)), - boost::make_transform_iterator (m_input.end(), - CGAL::Property_map_to_unary_function(m_item_map))); - - CGAL::Timer t; t.start(); - - m_scales.reserve (nb_scales); - double voxel_size = - 1.; - - m_scales.push_back (new Scale (m_input, m_item_map, m_bbox, voxel_size)); - voxel_size = m_scales[0]->grid_resolution(); - - for (std::size_t i = 1; i < nb_scales; ++ i) - { - voxel_size *= 2; - m_scales.push_back (new Scale (m_input, m_item_map, m_bbox, voxel_size)); - } - - generate_point_based_attributes (); - generate_normal_based_attributes (normal_map); - generate_color_based_attributes (color_map); - generate_echo_based_attributes (echo_map); - } - - - /// \cond SKIP_IN_MANUAL - virtual ~Point_set_classifier() - { - clear(); - } - /// \endcond - + /// \name Data Structures and Parameters + /// @{ + /*! \brief Returns the bounding box of the input point set. */ const Iso_cuboid_3& bbox() const { return m_bbox; } /*! \brief Returns the neighborhood structure at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ const Neighborhood& neighborhood(std::size_t scale = 0) const { return (*m_scales[scale]->neighborhood); } /*! \brief Returns the planimetric grid structure at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ const Planimetric_grid& grid(std::size_t scale = 0) const { return *(m_scales[scale]->grid); } /*! \brief Returns the local eigen analysis structure at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ const Local_eigen_analysis& eigen(std::size_t scale = 0) const { return *(m_scales[scale]->eigen); } /*! \brief Returns the grid resolution at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ double grid_resolution(std::size_t scale = 0) const { return m_scales[scale]->grid_resolution(); } /*! \brief Returns the radius used for neighborhood queries at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ double radius_neighbors(std::size_t scale = 0) const { return m_scales[scale]->radius_neighbors(); } /*! \brief Returns the radius used for digital terrain modeling at scale `scale`. + + \note `generate_attributes()` must have been called before calling + this method. */ double radius_dtm(std::size_t scale = 0) const { return m_scales[scale]->radius_dtm(); } + /// @} + + /*! + \brief Clears all computed data structures. + */ + void clear() + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + delete m_scales[i]; + m_scales.clear(); + + this->clear_classification_types(); + this->clear_attributes(); + } + + /// @} + /// \cond SKIP_IN_MANUAL void info() const { @@ -314,69 +386,7 @@ public: << " (weight = " << m_scales[i]->attributes[j]->weight() << ")" << std::endl; } } - /// \endcond - /*! - \brief Clears all computed data structures. - */ - void clear() - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - delete m_scales[i]; - m_scales.clear(); - - this->clear_classification_types(); - this->clear_attributes(); - } - - /*! - \brief Generate all possible attributes from an input range. - - This method calls `generate_point_based_attributes()`, - `generate_normal_based_attributes()`, - `generate_color_based_attributes()` and - `generate_echo_based_attributes()`. - - If a property map is left to its default - `CGAL::Default_property_map` type, the corresponding attributes are - not computed (this method can thus be called even if a point set - does not have associated normal, color or echo properties). - - \tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3`. - \tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. - \tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_`. - \param psc The classification object where to store the attributes - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param point_map Property map to access the input points - \param normal_map Property map to access the normal vectors of the input points (if any). - \param color_map Property map to access the colors of the input points (if any). - \param echo_map Property map to access the echo values of the input points (if any). - */ - - - /*! - \brief Generate all points attributes from an input range. - - Generate, for all precomputed scales, the following attributes: - - - `CGAL::Classification::Attribute::Anisotropy` - - `CGAL::Classification::Attribute::Distance_to_plane` - - `CGAL::Classification::Attribute::Eigentropy` - - `CGAL::Classification::Attribute::Elevation` - - `CGAL::Classification::Attribute::Linearity` - - `CGAL::Classification::Attribute::Omnivariance` - - `CGAL::Classification::Attribute::Planarity` - - `CGAL::Classification::Attribute::Sphericity` - - `CGAL::Classification::Attribute::Sum_eigenvalues` - - `CGAL::Classification::Attribute::Surface_variation` - - `CGAL::Classification::Attribute::Vertical_dispersion` - - \param psc The classification object where to store the attributes - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param point_map Property map to access the input points - */ void generate_point_based_attributes () { CGAL::Timer teigen, tpoint; @@ -400,35 +410,9 @@ public: std::cerr << "Eigen based attributes computed in " << teigen.time() << " second(s)" << std::endl; } - /*! - \brief Generate all normal attributes from an input range. - Generate, for all precomputed scales, the following attribute: - - - `CGAL::Classification::Attribute::Verticality` - - If the normal map is left to its default type - `CGAL::Default_property_map`, then the verticality attributes are - still computed by using an approximation of the normal vector - provided by the corresponding `Local_eigen_analysis` object. - - \tparam VectorMap Property map to access the normal vectors of the input points (if any). - \param psc The classification object where to store the attributes - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param normal_map Property map to access the normal vectors of the input points (if any). - */ - #ifdef DOXYGEN_RUNNING - template > - #else template - #endif - void generate_normal_based_attributes( -#ifdef DOXYGEN_RUNNING - VectorMap normal_map = VectorMap()) -#else - VectorMap normal_map) -#endif + void generate_normal_based_attributes(VectorMap normal_map) { CGAL::Timer t; t.start(); this->template add_attribute (normal_map); @@ -437,42 +421,12 @@ public: std::cerr << "Normal based attributes computed in " << t.time() << " second(s)" << std::endl; } - /// \cond SKIP_IN_MANUAL - void generate_normal_based_attributes(const CGAL::Default_property_map& - = CGAL::Default_property_map()) + void generate_normal_based_attributes(const CGAL::Default_property_map&) { CGAL::Timer t; t.start(); generate_multiscale_attribute_variant_0 (); std::cerr << "Normal based attributes computed in " << t.time() << " second(s)" << std::endl; } - /// \endcond - - /*! - \brief Generate a set of color attributes from an input range. - - Generate the following attributes: - - - 9 attributes `CGAL::Classification::Attribute::Hsv` on - channel 0 (hue) with mean ranging from 0° to 360° and standard - deviation of 22.5. - - - 5 attributes `CGAL::Classification::Attribute::Hsv` on - channel 1 (saturation) with mean ranging from 0 to 100 and standard - deviation of 12.5 - - - 5 attributes `CGAL::Classification::Attribute::Hsv` on - channel 2 (value) with mean ranging from 0 to 100 and standard - deviation of 12.5 - - This decomposition allows to handle all the color spectrum with a - usually sufficiently accurate precision. - - \tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. - \param psc The classification object where to store the attributes - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param color_map Property map to access the colors of the input points. - */ template void generate_color_based_attributes(ColorMap color_map) { @@ -498,25 +452,10 @@ public: std::cerr << "Color based attributes computed in " << t.time() << " second(s)" << std::endl; } - /// \cond SKIP_IN_MANUAL void generate_color_based_attributes(const CGAL::Default_property_map&) { } - /// \endcond - /*! - \brief Generate all echo attributes from an input range. - - Generate, for all precomputed scales, the following attribute: - - - `CGAL::Classification::Attribute::Echo_scatter` - - \tparam EchoMap Property map to access the echo values of the input points (if any). - \param psc The classification object where to store the attributes - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param echo_map Property map to access the echo values of the input points (if any). - */ template void generate_echo_based_attributes(EchoMap echo_map) { @@ -533,7 +472,6 @@ public: std::cerr << "Echo based attributes computed in " << t.time() << " second(s)" << std::endl; } - /// \cond SKIP_IN_MANUAL void generate_echo_based_attributes(const CGAL::Default_property_map&) { } @@ -563,6 +501,8 @@ public: } /// \endcond + /// \name Input/Output + /// @{ /*! \brief Saves the current configuration in the stream `output`. @@ -570,16 +510,12 @@ public: This allows to easily save and recover a specific classification configuration, that is to say: - - The smallest voxel size defined + - The computed scales - The attributes and their respective weights - The classification types and the effect the attributes have on them The output file is written in an XML format that is readable by - the `load()` method and the constructor that takes a file name - as parameter. - - \param output Output stream - \param psc Classification object whose attributes and types must be saved + the `load_configuration()` method. */ void save_configuration (std::ostream& output) { @@ -636,26 +572,23 @@ public: /*! - \brief Load a configuration from the stream `input`. + \brief Loads a configuration from the stream `input`. All data structures, attributes and types specified in the input stream `input` are instantiated if possible (in particular, - property maps needed should be provided). + property maps needed should be provided), similarly to what is + done in `generate_attributes()`. - The input file is written in an XML format written by the `save()` - method. + The input file should be in the XML format written by the + `save_configuration()` method. - \tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3`. - \tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. - \tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_`. - \param input Input stream - \param psc Classification object where to store attributes and types - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param point_map Property map to access the input points - \param normal_map Property map to access the normal vectors of the input points (if any). - \param color_map Property map to access the colors of the input points (if any). - \param echo_map Property map to access the echo values of the input points (if any). + \tparam VectorMap model of `ReadablePropertyMap` with value type `Vector_3`. + \tparam ColorMap model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. + \tparam EchoMap model of `ReadablePropertyMap` with value type `std::size_t`. + \param input input stream. + \param normal_map property map to access the normal vectors of the input points (if any). + \param color_map property map to access the colors of the input points (if any). + \param echo_map property map to access the echo values of the input points (if any). */ template(echo_map)); } + + + /*! + + \brief Writes a classification in a colored and labeled PLY format + in the stream `output`. + + The input point set is written in a PLY format with the addition + of several PLY properties: + + - a property `label` that indicates which classification type is + assigned to the point. The types are indexed from 0 to N (the + correspondancy is given as comments in the PLY header). + + - 3 properties `red`, `green` and `blue` to associate each label + to a color (this is useful to visualize the classification in a + viewer that supports PLY colors). Colors are picked randomly. + + \param stream The output stream where to write the content + \param begin Iterator to the first input object + \param end Past-the-end iterator + \param point_map Property map to access the input points + \param psc The classification object to write from + \param colors A set of colors to be used to represent the + different classification types. If none is given, random colors + are picked. + */ + void write_classification_to_ply (std::ostream& output) + { + output << "ply" << std::endl + << "format ascii 1.0" << std::endl + << "comment Generated by the CGAL library www.cgal.org" << std::endl + << "element vertex " << m_input.size() << std::endl + << "property double x" << std::endl + << "property double y" << std::endl + << "property double z" << std::endl + << "property uchar red" << std::endl + << "property uchar green" << std::endl + << "property uchar blue" << std::endl + << "property int label" << std::endl; + + std::vector colors; + + std::map map_types; + output << "comment label -1 is (unclassified)" << std::endl; + + for (std::size_t i = 0; i < this->number_of_classification_types(); ++ i) + { + map_types.insert (std::make_pair (this->get_classification_type(i), i)); + output << "comment label " << i << " is " << this->get_classification_type(i)->name() << std::endl; + RGB_Color c = {{ (unsigned char)(64 + rand() % 128), + (unsigned char)(64 + rand() % 128), + (unsigned char)(64 + rand() % 128) }}; + colors.push_back (c); + } + map_types.insert (std::make_pair (Type_handle(), this->number_of_classification_types())); + + output << "end_header" << std::endl; + + std::size_t i = 0; + for (Iterator it = m_input.begin(); it != m_input.end(); ++ it) + { + Type_handle t = this->classification_type_of(i); + std::size_t idx = map_types[t]; + + if (idx == this->number_of_classification_types()) + output << get(m_item_map, *it) << " 0 0 0 -1" << std::endl; + else + output << get(m_item_map, *it) << " " + << (int)(colors[idx][0]) << " " + << (int)(colors[idx][1]) << " " + << (int)(colors[idx][2]) << " " + << idx << std::endl; + ++ i; + } + } + + /// @} + +private: + template + const T& get_parameter (const T& t) + { + return t; + } + + template + Default_property_map + get_parameter (const Default&) + { + return Default_property_map(); + } + + template + void generate_attributes_impl (std::size_t nb_scales, + VectorMap normal_map, + ColorMap color_map, + EchoMap echo_map) + { + CGAL::Timer t; t.start(); + + m_scales.reserve (nb_scales); + double voxel_size = - 1.; + + m_scales.push_back (new Scale (m_input, m_item_map, m_bbox, voxel_size)); + voxel_size = m_scales[0]->grid_resolution(); + + for (std::size_t i = 1; i < nb_scales; ++ i) + { + voxel_size *= 2; + m_scales.push_back (new Scale (m_input, m_item_map, m_bbox, voxel_size)); + } + + generate_point_based_attributes (); + generate_normal_based_attributes (normal_map); + generate_color_based_attributes (color_map); + generate_echo_based_attributes (echo_map); + } + + template + void generate_multiscale_attribute_variant_0 () + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + { + this->template add_attribute(*(m_scales[i]->eigen)); + m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); + } + } + + template + void generate_multiscale_attribute_variant_1 () + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + { + this->template add_attribute(m_item_map, *(m_scales[i]->eigen)); + m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); + } + } + + template + void generate_multiscale_attribute_variant_2 () + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + { + this->template add_attribute(m_item_map, + *(m_scales[i]->grid), + m_scales[i]->grid_resolution(), + m_scales[i]->radius_neighbors()); + m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); + } + } + + template + void generate_multiscale_attribute_variant_3 () + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + { + this->template add_attribute(m_item_map, + *(m_scales[i]->grid), + m_scales[i]->grid_resolution(), + m_scales[i]->radius_dtm()); + m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); + } + } + template bool load_configuration_impl (std::istream& input, VectorMap normal_map, @@ -689,10 +787,6 @@ public: clear(); - m_bbox = CGAL::bounding_box - (boost::make_transform_iterator (m_input.begin(), CGAL::Property_map_to_unary_function(m_item_map)), - boost::make_transform_iterator (m_input.end(), CGAL::Property_map_to_unary_function(m_item_map))); - boost::property_tree::ptree tree; boost::property_tree::read_xml(input, tree); @@ -840,130 +934,6 @@ public: return true; } - - - /*! - \brief Writes a classification in a colored and labeled PLY format. - - The input point set is written in a PLY format with the addition - of several PLY properties: - - - a property `label` to indicate which classification type is - assigned to the point. The types are indexed from 0 to N (the - correspondancy is given as comments in the PLY header). - - - 3 properties `red`, `green` and `blue` to associate each label - to a color (this is useful to visualize the classification in a - viewer that supports PLY colors) - - \param stream The output stream where to write the content - \param begin Iterator to the first input object - \param end Past-the-end iterator - \param point_map Property map to access the input points - \param psc The classification object to write from - \param colors A set of colors to be used to represent the - different classification types. If none is given, random colors - are picked. - */ - void write_classification_to_ply (std::ostream& stream) - { - stream << "ply" << std::endl - << "format ascii 1.0" << std::endl - << "comment Generated by the CGAL library www.cgal.org" << std::endl - << "element vertex " << m_input.size() << std::endl - << "property double x" << std::endl - << "property double y" << std::endl - << "property double z" << std::endl - << "property uchar red" << std::endl - << "property uchar green" << std::endl - << "property uchar blue" << std::endl - << "property int label" << std::endl; - - std::vector colors; - - std::map map_types; - stream << "comment label -1 is (unclassified)" << std::endl; - - for (std::size_t i = 0; i < this->number_of_classification_types(); ++ i) - { - map_types.insert (std::make_pair (this->get_classification_type(i), i)); - stream << "comment label " << i << " is " << this->get_classification_type(i)->name() << std::endl; - RGB_Color c = {{ (unsigned char)(64 + rand() % 128), - (unsigned char)(64 + rand() % 128), - (unsigned char)(64 + rand() % 128) }}; - colors.push_back (c); - } - map_types.insert (std::make_pair (Type_handle(), this->number_of_classification_types())); - - stream << "end_header" << std::endl; - - std::size_t i = 0; - for (Iterator it = m_input.begin(); it != m_input.end(); ++ it) - { - Type_handle t = this->classification_type_of(i); - std::size_t idx = map_types[t]; - - if (idx == this->number_of_classification_types()) - stream << get(m_item_map, *it) << " 0 0 0 -1" << std::endl; - else - stream << get(m_item_map, *it) << " " - << (int)(colors[idx][0]) << " " - << (int)(colors[idx][1]) << " " - << (int)(colors[idx][2]) << " " - << idx << std::endl; - ++ i; - } - } - -private: - /// \cond SKIP_IN_MANUAL - template - void generate_multiscale_attribute_variant_0 () - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - { - this->template add_attribute(*(m_scales[i]->eigen)); - m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); - } - } - - template - void generate_multiscale_attribute_variant_1 () - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - { - this->template add_attribute(m_item_map, *(m_scales[i]->eigen)); - m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); - } - } - - template - void generate_multiscale_attribute_variant_2 () - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - { - this->template add_attribute(m_item_map, - *(m_scales[i]->grid), - m_scales[i]->grid_resolution(), - m_scales[i]->radius_neighbors()); - m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); - } - } - - template - void generate_multiscale_attribute_variant_3 () - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - { - this->template add_attribute(m_item_map, - *(m_scales[i]->grid), - m_scales[i]->grid_resolution(), - m_scales[i]->radius_dtm()); - m_scales[i]->attributes.push_back (this->get_attribute (this->number_of_attributes() - 1)); - } - } - - /// \endcond }; } // namespace CGAL diff --git a/Polyhedron/demo/Polyhedron/Scene_point_set_classification_item.h b/Polyhedron/demo/Polyhedron/Scene_point_set_classification_item.h index 22da4645bb5..4600600edc4 100644 --- a/Polyhedron/demo/Polyhedron/Scene_point_set_classification_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_point_set_classification_item.h @@ -143,7 +143,7 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_ void reset_training_sets() { m_psc->prepare_classification(); - m_psc->reset_training_sets(); + m_psc->reset_inlier_sets(); invalidateOpenGLBuffers(); Q_EMIT itemChanged(); }