Update with first reviews

This commit is contained in:
Simon Giraudot 2017-01-05 10:25:32 +01:00
parent 2dbff97e6c
commit 37b29b0944
25 changed files with 542 additions and 478 deletions

View File

@ -4,18 +4,18 @@ namespace CGAL {
\mainpage User Manual \mainpage User Manual
\anchor Chapter_Classification \anchor Chapter_Classification
\cgalAutoToc \cgalAutoToc
\author Simon Giraudot \author Simon Giraudot, Florent Lafarge
This component implements a generalization of the algorithm described in \cgalCite{cgal:lm-clscm-12}. It classifies a data set into a user-defined set of classification types (such as ground, vegetation, buildings, etc.). A flexible API is provided so that the user can classify any type of data, compute its own local attributes on the point cloud and define its own classification types based on these attributes. This component implements a generalization of the algorithm described in \cgalCite{cgal:lm-clscm-12}. It classifies a data set into a user-defined set of classification types, such as ground, vegetation and buildings. A flexible API is provided so that the user can classify any type of data, compute its own local attributes on the point cloud and define its own classification types based on these attributes.
\section Classification_Organization Package Organization \section Classification_Organization Package Organization
%Classification of data sets is achieved as follows: %Classification of data sets is achieved as follows:
- some analysis is performed on the input data set; - some analysis is performed on the input data set
- attributes are computed based on this analysis; - attributes are computed based on this analysis
- a set of classification types (for example: ground, building, vegetation) is defined by the user; - a set of classification types (for example: ground, building, vegetation) is defined by the user
- attributes are given weights and each pair of attribute/type is assigned a relationship; - attributes are given weights and each pair of attribute/type is assigned a relationship
- classification is computed item-wise by minimizing an energy defined as the sum of the values taken by attributes on input items (which depend on the attribute/type relationship) - classification is computed item-wise by minimizing an energy defined as the sum of the values taken by attributes on input items (which depend on the attribute/type relationship)
- additional regularization can be used by smoothing either locally or globally through an Alpha Expansion approach. - additional regularization can be used by smoothing either locally or globally through an Alpha Expansion approach.
@ -35,8 +35,8 @@ Organization of the package.
\cgal provides the following structures: \cgal provides the following structures:
- [Point_set_neighborhood](@ref CGAL::Classification::Point_set_neighborhood) stores spatial searching structures and provides adapted queries for points; - [Point_set_neighborhood](@ref CGAL::Classification::Point_set_neighborhood) stores spatial searching structures and provides adapted queries for points
- [Local_eigen_analysis](@ref CGAL::Classification::Local_eigen_analysis) precomputes covariance matrices on local neighborhoods of points and stores the associated eigenvectors and eigenvalues; - [Local_eigen_analysis](@ref CGAL::Classification::Local_eigen_analysis) precomputes covariance matrices on local neighborhoods of points and stores the associated eigenvectors and eigenvalues
- [Planimetric_grid](@ref CGAL::Classification::Planimetric_grid) is a 2D grid used for digital terrain modeling. - [Planimetric_grid](@ref CGAL::Classification::Planimetric_grid) is a 2D grid used for digital terrain modeling.
The following code snippet shows how to instantiate such data structures from an input PLY point set (the full example is given at the end of the manual). The following code snippet shows how to instantiate such data structures from an input PLY point set (the full example is given at the end of the manual).
@ -45,34 +45,34 @@ The following code snippet shows how to instantiate such data structures from an
\subsection Classification_attributes Attributes \subsection Classification_attributes Attributes
Attributes are defined as scalar fields that associate each input point with a specific value. The attributes provided by \cgal are generally sufficient to handle most cases. However, the user may want to define its own attributes, especially if the input point set comes with additional properties that were not anticipated by \cgal. Attributes are defined as scalar fields that associate each input point with a specific value. The user may want to define its own attributes, especially if the input point set comes with additional properties that were not anticipated by \cgal.
A user-defined attribute must inherit `CGAL::Classification::Attribute` and provide a method `value()` that associate a scalar value to each input point. A user-defined attribute must inherit from `CGAL::Classification::Attribute` and provide a method [value()](@ref CGAL::Classification::Attribute_base::value) that associate a scalar value to each input point.
Attributes are accessed through `Handle` objects, `CGAL::Classification::Attribute_handle`. Attributes are accessed through `Handle` objects, `CGAL::Classification::Attribute_handle`.
\cgal provides some predefined attributes that are relevant for classification of urban scenes: \cgal provides some predefined attributes that are relevant for classification of urban scenes:
- [Attribute_distance_to_plane](@ref CGAL::Classification::Attribute_distance_to_plane) measures how far away a point is from a locally estimated plane - [Distance_to_plane](@ref CGAL::Classification::Attribute::Distance_to_plane) measures how far away a point is from a locally estimated plane
- [Attribute_elevation](@ref CGAL::Classification::Attribute_elevation) computes the local distance to an estimation of the ground - [Elevation](@ref CGAL::Classification::Attribute::Elevation) computes the local distance to an estimation of the ground
- [Attribute_vertical_dispersion](@ref CGAL::Classification::Attribute_vertical_dispersion) computes how noisy the point set is on a local Z-cylinder - [Vertical_dispersion](@ref CGAL::Classification::Attribute::Vertical_dispersion) computes how noisy the point set is on a local Z-cylinder
- [Attribute_verticality](@ref CGAL::Classification::Attribute_verticality) compares the local normal vector to the vertical vector. - [Verticality](@ref CGAL::Classification::Attribute::Verticality) compares the local normal vector to the vertical vector.
For more details about how these different attributes can help identifying one classification type or the other, please refer to their associated reference manual pages. In addition, \cgal also provides attributes solely based on the local eigen values \cgalCite{cgal:mbrsh-raofw-11}. Such attributes are more theoretical and harder to relate to a specific use case, but they can help differenciating some classification types: For more details about how these different attributes can help identifying one classification type or the other, please refer to their associated reference manual pages. In addition, \cgal also provides attributes solely based on the local eigen values \cgalCite{cgal:mbrsh-raofw-11}. Such attributes are more theoretical and harder to relate to a specific use case, but they can help differenciating some classification types:
- [Attribute_anisotropy](@ref CGAL::Classification::Attribute_anisotropy) - [Anisotropy](@ref CGAL::Classification::Attribute::Anisotropy)
- [Attribute_eigentropy](@ref CGAL::Classification::Attribute_eigentropy) - [Eigentropy](@ref CGAL::Classification::Attribute::Eigentropy)
- [Attribute_linearity](@ref CGAL::Classification::Attribute_linearity) - [Linearity](@ref CGAL::Classification::Attribute::Linearity)
- [Attribute_omnivariance](@ref CGAL::Classification::Attribute_omnivariance) - [Omnivariance](@ref CGAL::Classification::Attribute::Omnivariance)
- [Attribute_planarity](@ref CGAL::Classification::Attribute_planarity) - [Planarity](@ref CGAL::Classification::Attribute::Planarity)
- [Attribute_sphericity](@ref CGAL::Classification::Attribute_sphericity) - [Sphericity](@ref CGAL::Classification::Attribute::Sphericity)
- [Attribute_sum_eigenvalues](@ref CGAL::Classification::Attribute_sum_eigenvalues) - [Sum_eigenvalues](@ref CGAL::Classification::Attribute::Sum_eigenvalues)
- [Attribute_surface_variation](@ref CGAL::Classification::Attribute_surface_variation) - [Surface_variation](@ref CGAL::Classification::Attribute::Surface_variation)
Finally, if the input point set has additional properties, these can also be used as attributes. For example, \cgal provides the following attributes: Finally, if the input point set has additional properties, these can also be used as attributes. For example, \cgal provides the following attributes:
- [Attribute_echo_scatter](@ref CGAL::Classification::Attribute_echo_scatter) uses the number of returns (echo) provided by most LIDAR scanners if available - [Echo_scatter](@ref CGAL::Classification::Attribute::Echo_scatter) uses the number of returns (echo) provided by most LIDAR scanners if available
- [Attribute_hsv](@ref CGAL::Classification::Attribute_hsv) uses input color information if available. - [Hsv](@ref CGAL::Classification::Attribute::Hsv) uses input color information if available.
In the following code snippet, a subset of these attributes are instantiated, their weights are set and they are added to a newly created classifier: In the following code snippet, a subset of these attributes are instantiated, their weights are set and they are added to a newly created classifier:
@ -84,9 +84,9 @@ A classification type represents how a point should be classified, for example:
\cgal provides a class `CGAL::Classification::Type` to define such a set of attribute effects, along with the associated `Handle` object: `CGAL::Classification::Type_handle`. Each type may define how a specific attribute affects it: \cgal provides a class `CGAL::Classification::Type` to define such a set of attribute effects, along with the associated `Handle` object: `CGAL::Classification::Type_handle`. Each type may define how a specific attribute affects it:
- [FAVORED_ATT](@ref CGAL::Classification::Type::FAVORED_ATT): the type is favored by high values of the attribute - [FAVORING](@ref CGAL::Classification::Attribute::FAVORING): the type is favored by high values of the attribute
- [NEUTRAL_ATT](@ref CGAL::Classification::Type::NEUTRAL_ATT): the type is not affected by the attribute - [NEUTRAL](@ref CGAL::Classification::Attribute::NEUTRAL): the type is not affected by the attribute
- [PENALIZED_ATT](@ref CGAL::Classification::Type::PENALIZED_ATT): the type is favored by low values of the attribute - [PENALIZING](@ref CGAL::Classification::Attribute::PENALIZING): the type is favored by low values of the attribute
Let \f$x=(x_i)_{i=1..N_c}\f$ be a potential classification result with \f$N_c\f$ the number of input points and \f$x_i\f$ the class of the \f$i^{th}\f$ point (for example: vegetation, ground, etc.). Let \f$a_j(i)\f$ be the raw value of the \f$j^{th}\f$ attribute at the \f$i^{th}\f$ point and \f$w_j\f$ be the weight of this attribute. We define the normalized value of the \f$j^{th}\f$ attribute at the \f$i^{th}\f$ point as follows: Let \f$x=(x_i)_{i=1..N_c}\f$ be a potential classification result with \f$N_c\f$ the number of input points and \f$x_i\f$ the class of the \f$i^{th}\f$ point (for example: vegetation, ground, etc.). Let \f$a_j(i)\f$ be the raw value of the \f$j^{th}\f$ attribute at the \f$i^{th}\f$ point and \f$w_j\f$ be the weight of this attribute. We define the normalized value of the \f$j^{th}\f$ attribute at the \f$i^{th}\f$ point as follows:
@ -171,7 +171,7 @@ offers the best quality but requires longer computation time (see
Figure \cgalFigureRef{Classification_image}, bottom-right). The Figure \cgalFigureRef{Classification_image}, bottom-right). The
total energy that is minimized is the sum of the partial data term total energy that is minimized is the sum of the partial data term
\f$E_{di}(x_i)\f$ and of a pairwise interaction energy defined by the \f$E_{di}(x_i)\f$ and of a pairwise interaction energy defined by the
standard Potts model: standard Potts model \cgalCite{cgal:l-mrfmi-09} :
\f[ \f[
E(x) = \sum_{i = 1..N_c} E_{di}(x_i) + \gamma \sum_{i \sim j} \mathbf{1}_{x_i \neq x_j} E(x) = \sum_{i = 1..N_c} E_{di}(x_i) + \gamma \sum_{i \sim j} \mathbf{1}_{x_i \neq x_j}
@ -196,23 +196,23 @@ constant computation time.
The following example: The following example:
- reads an input file (LIDAR point set in PLY format); - reads an input file (LIDAR point set in PLY format)
- computes useful structures from this input; - computes useful structures from this input
- computes segmentation attributes from the input and the precomputed structures; - computes segmentation attributes from the input and the precomputed structures
- defines 3 classification types (vegetation, ground and roof) along with the effects of attributes on them; - defines 3 classification types (vegetation, ground and roof) along with the effects of attributes on them
- classifies the point set; - classifies the point set
- saves the result in a colored PLY format. - saves the result in a colored PLY format.
\cgalExample{Classification/example_point_set_classification.cpp} \cgalExample{Classification/example_point_set_classification.cpp}
\section Classification_helper Helper \section Classification_helper Helper
The classification algorithm is designed to be as flexible as possible: the user may define its own attributes and classification types. Nevertheless, \cgal provides a predefined framework that should work correctly on common urban point sets. The class `CGAL::Classification::Helper` is designed to make it easier for the user to classify its input point set: The classification algorithm is designed to be as flexible as possible: users may define their own attributes and classification types. Nevertheless, \cgal provides a predefined framework that should work correctly on common urban point sets. The class `CGAL::Classification::Helper` makes it easier for the user to classify its input point set:
- it takes care of generating all needed analysis structure; - it takes care of generating all needed analysis structures
- it generates all possible attributes (among all the \cgal predefined ones) based on which property maps are available (it uses colors if available, etc.); - it generates all possible attributes (among all the \cgal predefined ones) based on which property maps are available (it uses colors if available, etc.)
- multiple scales can be used to increase the quality of the results - multiple scales can be used to increase the quality of the results \cgalCite{cgal:hws-fsso3-16}
- input/ouput methods are provided to save and recover a specific configuration (with all attributes, types and relationships between them). - input/ouput methods are provided to save and recover a specific configuration (with all attributes, types and relationships between them)
- classification can be saved as a PLY format with colors and labels. - classification can be saved as a PLY format with colors and labels.
\section Classification_training Training \section Classification_training Training
@ -221,20 +221,20 @@ The classification algorithm is designed to be as flexible as possible: the user
Though it is possible to set them up one by one, \cgal also provides a training algorithm that requires a small set of ground truth points provided by the user. More specifically, the user must provide, for each classification type he/she wants to classify, a set of known inliers among the input point set (for example, selecting one roof, one tree and one section of the ground). The training algorithm works as follows: Though it is possible to set them up one by one, \cgal also provides a training algorithm that requires a small set of ground truth points provided by the user. More specifically, the user must provide, for each classification type he/she wants to classify, a set of known inliers among the input point set (for example, selecting one roof, one tree and one section of the ground). The training algorithm works as follows:
- for each attribute, a range of weights is tested: the effects each attribute have on each type is estimated. For a given weight, if an attribute has the same effect on each type, it is non-relevant for classification. The range of weights such that the attribute is relevant is estimated; - for each attribute, a range of weights is tested: the effect each attribute have on each type is estimated. For a given weight, if an attribute has the same effect on each type, it is non-relevant for classification. The range of weights such that the attribute is relevant is estimated
- for each attribute, uniformly picked weight values are tested and their effects estimated; - for each attribute, uniformly picked weight values are tested and their effects estimated
- each ground truth points provided by the user is classified using this set of weights and effects; - each ground truth point provided by the user is classified using this set of weights and effects
- for each classification type, the ratio of correctly classified ground truth points is computed. The minimum of these ratios is used as a score for this set of weights and effects: a ratio of 0.8 means that for each classification type, at least 80\% of the provided ground truth point were correctly classified; - for each classification type, the ratio of correctly classified ground truth points is computed. The minimum of these ratios is used as a score for this set of weights and effects: a ratio of 0.8 means that for each classification type, at least 80\% of the provided ground truth point were correctly classified
- the same mechanism is repeated until all attributes' ranges have been tested. Weights are only changed one by one, the other ones kept to the previous value that gave the best score. - the same mechanism is repeated until all attributes' ranges have been tested. Weights are only changed one by one, the other ones kept to the previous value that gave the best score.
This usually converges to a satisfying solution. The number of trials is user defined, set to 300 by default. Using at least 10 times the number of attributes is advised. If the solution is not satisfying, more ground truth points can be selected,for example, in a region that the user identifies as misclassified with the current configuration. The training algorithm keeps the best weights found as initialization and carries on trying new weights by taking new ground truth points into account. This usually converges to a satisfying solution. The number of trials is user defined, set to 300 by default. Using at least 10 times the number of attributes is advised. If the solution is not satisfying, more ground truth points can be selected,for example, in a region that the user identifies as misclassified with the current configuration. The training algorithm keeps the best weights found as initialization and carries on trying new weights by taking new ground truth points into account.
\cgalFigureBegin{Classification_training_fig,classif_training.png} \cgalFigureBegin{Classification_training_fig,classif_training.png}
Example of evolution of training score. Purple curve is the score computed at the current iteration, green curve is the best score found so far. Iterations where better solutions are found are marked by vertical gray lines. Example of evolution of training score. The purple curve is the score computed at the current iteration, green curve is the best score found so far. Iterations where better solutions are found are marked by vertical gray lines.
\cgalFigureEnd \cgalFigureEnd
@ -242,10 +242,10 @@ Example of evolution of training score. Purple curve is the score computed at th
The following example: The following example:
- reads a point set with a training set (embedded as a PLY attribute _label_); - reads a point set with a training set (embedded as a PLY attribute _label_)
- uses the helper to generate attributes on 5 scales; - uses the helper to generate attributes on 5 scales
- trains the algorithm using 800 trials; - trains the algorithm using 800 trials
- runs the algorithm using the graphcut regularization; - runs the algorithm using the graphcut regularization
- saves the output using the helper. - saves the output using the helper.
\cgalExample{Classification/example_helper.cpp} \cgalExample{Classification/example_helper.cpp}

View File

@ -1,5 +1,6 @@
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} @INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Classification" PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Classification"
INPUT = ${CMAKE_SOURCE_DIR}/Classification/doc/Classification/ \ INPUT = ${CMAKE_SOURCE_DIR}/Classification/doc/Classification/ \
${CMAKE_SOURCE_DIR}/Classification/include/CGAL/Classification/ \ ${CMAKE_SOURCE_DIR}/Classification/include/CGAL/Classifier.h \
${CMAKE_SOURCE_DIR}/Classification/include/CGAL/Classifier.h ${CMAKE_SOURCE_DIR}/Classification/include/CGAL/Classification/Attribute/ \
${CMAKE_SOURCE_DIR}/Classification/include/CGAL/Classification/

View File

@ -4,23 +4,27 @@
\defgroup PkgClassificationConcepts Concepts \defgroup PkgClassificationConcepts Concepts
\ingroup PkgClassification \ingroup PkgClassification
\defgroup PkgClassificationShapes Shapes \defgroup PkgClassificationDataStructures Data Structures
\ingroup PkgClassification \ingroup PkgClassification
\defgroup PkgClassificationAttributes Predefined Attributes
\ingroup PkgClassification
\addtogroup PkgClassification \addtogroup PkgClassification
\cgalPkgDescriptionBegin{Classification, PkgClassificationSummary} \cgalPkgDescriptionBegin{Classification, PkgClassificationSummary}
\cgalPkgPicture{data_classif.png} \cgalPkgPicture{data_classif.png}
\cgalPkgSummaryBegin \cgalPkgSummaryBegin
\cgalPkgAuthors{Simon Giraudot} \cgalPkgAuthors{Simon Giraudot, Florent Lafarge}
\cgalPkgDesc{This component implements an algorithm that classifies a data set into a user-defined set of classes (such as ground, vegetation, buildings, etc.). A flexible API is provided so that the user can classify any type of data, compute its own local attributes on the data set and define its own classes based on these attributes.} \cgalPkgDesc{This component implements an algorithm that classifies a data set into a user-defined set of classes (such as ground, vegetation, buildings, etc.). A flexible API is provided so that the user can classify any type of data, compute its own local attributes on the data set and define its own classes based on these attributes.}
\cgalPkgManuals{Chapter_Classification, PkgClassification} \cgalPkgManuals{Chapter_Classification, PkgClassification}
\cgalPkgSummaryEnd \cgalPkgSummaryEnd
\cgalPkgShortInfoBegin \cgalPkgShortInfoBegin
\cgalPkgSince{4.9} \cgalPkgSince{4.9}
\cgalPkgBib{cgal:ovja-pssd} \cgalPkgBib{cgal:lm-clscm-12}
\cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Operations on Polyhedra,polyhedron_3.zip} \cgalPkgDemo{Operations on Polyhedra,polyhedron_3.zip}
\cgalPkgShortInfoEnd \cgalPkgShortInfoEnd
@ -54,20 +58,20 @@
## Predefined Attributes ## ## Predefined Attributes ##
- `CGAL::Classification::Attribute_anisotropy<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Anisotropy<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_distance_to_plane<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Distance_to_plane<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap>` - `CGAL::Classification::Attribute::Echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap>`
- `CGAL::Classification::Attribute_eigentropy<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Eigentropy<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_elevation<Kernel, RandomAccessIterator, PointMap>` - `CGAL::Classification::Attribute::Elevation<Kernel, RandomAccessIterator, PointMap>`
- `CGAL::Classification::Attribute_hsv<Kernel, RandomAccessIterator, ColorMap>` - `CGAL::Classification::Attribute::Hsv<Kernel, RandomAccessIterator, ColorMap>`
- `CGAL::Classification::Attribute_linearity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Linearity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_omnivariance<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Omnivariance<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_planarity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Planarity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_sphericity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Sphericity<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_sum_eigenvalues<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Sum_eigenvalues<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_surface_variation<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Surface_variation<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Attribute_vertical_dispersion<Kernel, RandomAccessIterator, PointMap>` - `CGAL::Classification::Attribute::Vertical_dispersion<Kernel, RandomAccessIterator, PointMap>`
- `CGAL::Classification::Attribute_verticality<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Attribute::Verticality<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
*/ */

View File

@ -112,7 +112,7 @@ int main (int argc, char** argv)
} }
std::cerr << "Training" << std::endl; std::cerr << "Training" << std::endl;
psc.training(800); // 800 trials psc.train (800); // 800 trials
psc.run_with_graphcut (helper.neighborhood().k_neighbor_query(12), 0.5); psc.run_with_graphcut (helper.neighborhood().k_neighbor_query(12), 0.5);
@ -128,7 +128,8 @@ int main (int argc, char** argv)
helper.write_ply (f, pts.begin(), pts.end(), Pmap(), psc, &colors); helper.write_ply (f, pts.begin(), pts.end(), Pmap(), psc, &colors);
/// Save the configuration to be able to reload it later /// Save the configuration to be able to reload it later
helper.save ("config.xml", psc); std::ofstream fconfig ("config.xml");
helper.save (fconfig, psc);
std::cerr << "All done" << std::endl; std::cerr << "All done" << std::endl;

View File

@ -30,13 +30,13 @@ typedef CGAL::Classification::Local_eigen_analysis<Kernel, Iterator, Pmap> Loc
typedef CGAL::Classification::Type_handle Type_handle; typedef CGAL::Classification::Type_handle Type_handle;
typedef CGAL::Classification::Attribute_handle Attribute_handle; typedef CGAL::Classification::Attribute_handle Attribute_handle;
typedef CGAL::Classification::Attribute_distance_to_plane<Kernel, Iterator, Pmap> Distance_to_plane; typedef CGAL::Classification::Attribute::Distance_to_plane<Kernel, Iterator, Pmap> Distance_to_plane;
typedef CGAL::Classification::Attribute_linearity<Kernel, Iterator, Pmap> Linearity; typedef CGAL::Classification::Attribute::Linearity<Kernel, Iterator, Pmap> Linearity;
typedef CGAL::Classification::Attribute_omnivariance<Kernel, Iterator, Pmap> Omnivariance; typedef CGAL::Classification::Attribute::Omnivariance<Kernel, Iterator, Pmap> Omnivariance;
typedef CGAL::Classification::Attribute_planarity<Kernel, Iterator, Pmap> Planarity; typedef CGAL::Classification::Attribute::Planarity<Kernel, Iterator, Pmap> Planarity;
typedef CGAL::Classification::Attribute_surface_variation<Kernel, Iterator, Pmap> Surface_variation; typedef CGAL::Classification::Attribute::Surface_variation<Kernel, Iterator, Pmap> Surface_variation;
typedef CGAL::Classification::Attribute_elevation<Kernel, Iterator, Pmap> Elevation; typedef CGAL::Classification::Attribute::Elevation<Kernel, Iterator, Pmap> Elevation;
typedef CGAL::Classification::Attribute_vertical_dispersion<Kernel, Iterator, Pmap> Dispersion; typedef CGAL::Classification::Attribute::Vertical_dispersion<Kernel, Iterator, Pmap> Dispersion;
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
@ -89,13 +89,13 @@ int main (int argc, char** argv)
radius_dtm)); radius_dtm));
std::cerr << "Setting weights" << std::endl; std::cerr << "Setting weights" << std::endl;
d2p->weight = 6.75e-2; d2p->weight() = 6.75e-2;
lin->weight = 1.19; lin->weight() = 1.19;
omni->weight = 1.34e-1; omni->weight() = 1.34e-1;
plan->weight = 7.32e-1; plan->weight() = 7.32e-1;
surf->weight = 1.36e-1; surf->weight() = 1.36e-1;
disp->weight = 5.45e-1; disp->weight() = 5.45e-1;
elev->weight = 1.47e1; elev->weight() = 1.47e1;
// Add attributes to classification object // Add attributes to classification object
@ -118,31 +118,31 @@ int main (int argc, char** argv)
// Create classification type and define how attributes affect them // Create classification type and define how attributes affect them
Type_handle ground = psc.add_classification_type ("ground"); Type_handle ground = psc.add_classification_type ("ground");
ground->set_attribute_effect (d2p, CGAL::Classification::Type::NEUTRAL_ATT); ground->set_attribute_effect (d2p, CGAL::Classification::Attribute::NEUTRAL);
ground->set_attribute_effect (lin, CGAL::Classification::Type::PENALIZED_ATT); ground->set_attribute_effect (lin, CGAL::Classification::Attribute::PENALIZING);
ground->set_attribute_effect (omni, CGAL::Classification::Type::NEUTRAL_ATT); ground->set_attribute_effect (omni, CGAL::Classification::Attribute::NEUTRAL);
ground->set_attribute_effect (plan, CGAL::Classification::Type::FAVORED_ATT); ground->set_attribute_effect (plan, CGAL::Classification::Attribute::FAVORING);
ground->set_attribute_effect (surf, CGAL::Classification::Type::PENALIZED_ATT); ground->set_attribute_effect (surf, CGAL::Classification::Attribute::PENALIZING);
ground->set_attribute_effect (disp, CGAL::Classification::Type::NEUTRAL_ATT); ground->set_attribute_effect (disp, CGAL::Classification::Attribute::NEUTRAL);
ground->set_attribute_effect (elev, CGAL::Classification::Type::PENALIZED_ATT); ground->set_attribute_effect (elev, CGAL::Classification::Attribute::PENALIZING);
Type_handle vege = psc.add_classification_type ("vegetation"); Type_handle vege = psc.add_classification_type ("vegetation");
vege->set_attribute_effect (d2p, CGAL::Classification::Type::FAVORED_ATT); vege->set_attribute_effect (d2p, CGAL::Classification::Attribute::FAVORING);
vege->set_attribute_effect (lin, CGAL::Classification::Type::NEUTRAL_ATT); vege->set_attribute_effect (lin, CGAL::Classification::Attribute::NEUTRAL);
vege->set_attribute_effect (omni, CGAL::Classification::Type::FAVORED_ATT); vege->set_attribute_effect (omni, CGAL::Classification::Attribute::FAVORING);
vege->set_attribute_effect (plan, CGAL::Classification::Type::NEUTRAL_ATT); vege->set_attribute_effect (plan, CGAL::Classification::Attribute::NEUTRAL);
vege->set_attribute_effect (surf, CGAL::Classification::Type::NEUTRAL_ATT); vege->set_attribute_effect (surf, CGAL::Classification::Attribute::NEUTRAL);
vege->set_attribute_effect (disp, CGAL::Classification::Type::FAVORED_ATT); vege->set_attribute_effect (disp, CGAL::Classification::Attribute::FAVORING);
vege->set_attribute_effect (elev, CGAL::Classification::Type::NEUTRAL_ATT); vege->set_attribute_effect (elev, CGAL::Classification::Attribute::NEUTRAL);
Type_handle roof = psc.add_classification_type ("roof"); Type_handle roof = psc.add_classification_type ("roof");
roof->set_attribute_effect (d2p, CGAL::Classification::Type::NEUTRAL_ATT); roof->set_attribute_effect (d2p, CGAL::Classification::Attribute::NEUTRAL);
roof->set_attribute_effect (lin, CGAL::Classification::Type::PENALIZED_ATT); roof->set_attribute_effect (lin, CGAL::Classification::Attribute::PENALIZING);
roof->set_attribute_effect (omni, CGAL::Classification::Type::FAVORED_ATT); roof->set_attribute_effect (omni, CGAL::Classification::Attribute::FAVORING);
roof->set_attribute_effect (plan, CGAL::Classification::Type::FAVORED_ATT); roof->set_attribute_effect (plan, CGAL::Classification::Attribute::FAVORING);
roof->set_attribute_effect (surf, CGAL::Classification::Type::PENALIZED_ATT); roof->set_attribute_effect (surf, CGAL::Classification::Attribute::PENALIZING);
roof->set_attribute_effect (disp, CGAL::Classification::Type::NEUTRAL_ATT); roof->set_attribute_effect (disp, CGAL::Classification::Attribute::NEUTRAL);
roof->set_attribute_effect (elev, CGAL::Classification::Type::FAVORED_ATT); roof->set_attribute_effect (elev, CGAL::Classification::Attribute::FAVORING);
//! [Classification Types] //! [Classification Types]
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////

View File

@ -28,8 +28,10 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on local distance to a fitted plane. \brief Attribute based on local distance to a fitted plane.
@ -44,7 +46,7 @@ namespace Classification {
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_distance_to_plane : public Attribute class Distance_to_plane : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -60,12 +62,12 @@ public:
\param point_map Property map to access the input points \param point_map Property map to access the input points
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_distance_to_plane (RandomAccessIterator begin, Distance_to_plane (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
const Local_eigen_analysis& eigen) const Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
for(std::size_t i = 0; i < (std::size_t)(end - begin); i++) for(std::size_t i = 0; i < (std::size_t)(end - begin); i++)
distance_to_plane_attribute.push_back distance_to_plane_attribute.push_back
(CGAL::sqrt (CGAL::squared_distance (get(point_map, begin[i]), eigen.plane(i)))); (CGAL::sqrt (CGAL::squared_distance (get(point_map, begin[i]), eigen.plane(i))));
@ -84,6 +86,7 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification

View File

@ -8,13 +8,15 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on echo scatter. \brief Attribute based on echo scatter.
The number of returns (echo number) is a useful information The number of returns (echo number) is a useful information
provided by most LIDAR sensor. It can help identifying trees. provided by most LIDAR sensors. It can help identify trees.
\tparam Kernel The geometric kernel used. \tparam Kernel The geometric kernel used.
\tparam RandomAccessIterator Iterator over the input. \tparam RandomAccessIterator Iterator over the input.
@ -22,10 +24,13 @@ namespace Classification {
\tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_t`. \tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_t`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, typename EchoMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap, typename EchoMap>
class Attribute_echo_scatter : public Attribute class Echo_scatter : public Attribute_base
{ {
typedef Classification::Image<float> Image_float; public:
typedef Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap> Grid; typedef Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap> Grid;
private:
typedef Classification::Image<float> Image_float;
std::vector<double> echo_scatter; std::vector<double> echo_scatter;
@ -40,14 +45,14 @@ public:
\param grid_resolution Resolution of the planimetric grid \param grid_resolution Resolution of the planimetric grid
\param radius_neighbors Radius of local neighborhoods \param radius_neighbors Radius of local neighborhoods
*/ */
Attribute_echo_scatter (RandomAccessIterator begin, Echo_scatter (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
EchoMap echo_map, EchoMap echo_map,
Grid& grid, Grid& grid,
const double grid_resolution, const double grid_resolution,
double radius_neighbors = 1.) double radius_neighbors = 1.)
{ {
this->weight = 1.; this->weight() = 1.;
Image_float Scatter(grid.width(), grid.height()); Image_float Scatter(grid.width(), grid.height());
for (std::size_t j = 0; j < grid.height(); j++) for (std::size_t j = 0; j < grid.height(); j++)
for (std::size_t i = 0; i < grid.width(); i++) for (std::size_t i = 0; i < grid.width(); i++)
@ -117,6 +122,8 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification
} // namespace CGAL } // namespace CGAL

View File

@ -28,9 +28,10 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -48,7 +49,7 @@ namespace Classification {
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_linearity : public Attribute class Linearity : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -61,11 +62,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_linearity (RandomAccessIterator begin, Linearity (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -89,7 +90,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -107,7 +108,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_planarity : public Attribute class Planarity : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -120,11 +121,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_planarity (RandomAccessIterator begin, Planarity (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -148,7 +149,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -166,7 +167,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_sphericity : public Attribute class Sphericity : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -179,11 +180,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_sphericity (RandomAccessIterator begin, Sphericity (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -206,7 +207,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -224,7 +225,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_omnivariance : public Attribute class Omnivariance : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -237,11 +238,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_omnivariance (RandomAccessIterator begin, Omnivariance (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -261,7 +262,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -279,7 +280,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_anisotropy : public Attribute class Anisotropy : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -292,11 +293,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_anisotropy (RandomAccessIterator begin, Anisotropy (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -319,7 +320,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -337,7 +338,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_eigentropy : public Attribute class Eigentropy : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -350,11 +351,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_eigentropy (RandomAccessIterator begin, Eigentropy (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -381,7 +382,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -399,7 +400,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_sum_eigenvalues : public Attribute class Sum_eigenvalues : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -412,15 +413,15 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_sum_eigenvalues (RandomAccessIterator begin, Sum_eigenvalues (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
attrib.push_back (eigen.sum_eigenvalues(i)); attrib.push_back (eigen.sum_of_eigenvalues(i));
this->compute_mean_max (attrib, mean, this->max); this->compute_mean_max (attrib, mean, this->max);
} }
@ -434,7 +435,7 @@ public:
}; };
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on the eigenvalues of the covariance matrix \brief Attribute based on the eigenvalues of the covariance matrix
of a local neighborhood. of a local neighborhood.
@ -452,7 +453,7 @@ public:
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_surface_variation : public Attribute class Surface_variation : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -465,11 +466,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_surface_variation (RandomAccessIterator begin, Surface_variation (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
Local_eigen_analysis& eigen) Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
std::size_t size = (std::size_t)(end - begin); std::size_t size = (std::size_t)(end - begin);
attrib.reserve (size); attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i) for (std::size_t i = 0; i < size; ++ i)
@ -492,6 +493,7 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification

View File

@ -30,8 +30,10 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on local elevation. \brief Attribute based on local elevation.
@ -47,7 +49,7 @@ namespace Classification {
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap>
class Attribute_elevation : public Attribute class Elevation : public Attribute_base
{ {
typedef typename Kernel::Iso_cuboid_3 Iso_cuboid_3; typedef typename Kernel::Iso_cuboid_3 Iso_cuboid_3;
@ -68,14 +70,14 @@ public:
\param radius_dtm Radius for digital terrain modeling (must be bigger than the size of a building) \param radius_dtm Radius for digital terrain modeling (must be bigger than the size of a building)
*/ */
Attribute_elevation (RandomAccessIterator begin, Elevation (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
const Grid& grid, const Grid& grid,
const double grid_resolution, const double grid_resolution,
double radius_dtm = -1.) double radius_dtm = -1.)
{ {
this->weight = 1.; this->weight() = 1.;
if (radius_dtm < 0.) if (radius_dtm < 0.)
radius_dtm = 100. * grid_resolution; radius_dtm = 100. * grid_resolution;
@ -159,6 +161,8 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification

View File

@ -17,8 +17,8 @@
// //
// Author(s) : Simon Giraudot // Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_ATTRIBUTE_COLOR_H #ifndef CGAL_CLASSIFICATION_ATTRIBUTE_HSV_H
#define CGAL_CLASSIFICATION_ATTRIBUTE_COLOR_H #define CGAL_CLASSIFICATION_ATTRIBUTE_HSV_H
#include <vector> #include <vector>
@ -28,13 +28,15 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on HSV colorimetric information. \brief Attribute based on HSV colorimetric information.
If the input point cloud has colorimetric information, it can be If the input point cloud has colorimetric information, it can be
used for classification purposes. This attribute is based on used for classification purposes. This attribute is based on a
Gaussian probabilistic model on one of the three HSV channels Gaussian probabilistic model on one of the three HSV channels
(hue, saturation or value). (hue, saturation or value).
@ -43,15 +45,15 @@ namespace Classification {
deviation. deviation.
For example, such an attribute using the channel 0 (hue) with a For example, such an attribute using the channel 0 (hue) with a
mean of 90 (which corresponds to a green hue) can help identifying mean of 90 (which corresponds to a green hue) can help identify
trees. trees.
\tparam Kernel The geometric kernel used. \tparam Kernel The geometric kernel used.
\tparam RandomAccessIterator Iterator over the input. \tparam RandomAccessIterator Iterator over the input.
\tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`.A \tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename ColorMap> template <typename Kernel, typename RandomAccessIterator, typename ColorMap>
class Attribute_hsv : public Attribute class Hsv : public Attribute_base
{ {
typedef typename Classification::RGB_Color RGB_Color; typedef typename Classification::RGB_Color RGB_Color;
typedef typename Classification::HSV_Color HSV_Color; typedef typename Classification::HSV_Color HSV_Color;
@ -73,13 +75,13 @@ public:
\param mean Mean value of the specified channel \param mean Mean value of the specified channel
\param sd Standard deviation of the specified channel \param sd Standard deviation of the specified channel
*/ */
Attribute_hsv (RandomAccessIterator begin, Hsv (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
ColorMap color_map, ColorMap color_map,
std::size_t channel, std::size_t channel,
double mean, double sd) double mean, double sd)
{ {
this->weight = 1.; this->weight() = 1.;
for(std::size_t i = 0; i < (std::size_t)(end - begin);i++) for(std::size_t i = 0; i < (std::size_t)(end - begin);i++)
{ {
HSV_Color c = Classification::rgb_to_hsv (get(color_map, begin[i])); HSV_Color c = Classification::rgb_to_hsv (get(color_map, begin[i]));
@ -105,8 +107,10 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification
} // namespace CGAL } // namespace CGAL
#endif // CGAL_CLASSIFICATION_ATTRIBUTE_COLOR_H #endif // CGAL_CLASSIFICATION_ATTRIBUTE_HSV_H

View File

@ -29,8 +29,10 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on local vertical dispersion of points. \brief Attribute based on local vertical dispersion of points.
@ -46,7 +48,7 @@ namespace Classification {
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`. \tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap>
class Attribute_vertical_dispersion : public Attribute class Vertical_dispersion : public Attribute_base
{ {
typedef Classification::Image<float> Image_float; typedef Classification::Image<float> Image_float;
typedef Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap> Grid; typedef Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap> Grid;
@ -63,14 +65,14 @@ public:
\param grid_resolution Resolution of the planimetric grid \param grid_resolution Resolution of the planimetric grid
\param radius_neighbors Radius of local neighborhoods \param radius_neighbors Radius of local neighborhoods
*/ */
Attribute_vertical_dispersion (RandomAccessIterator begin, Vertical_dispersion (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
const Grid& grid, const Grid& grid,
const double grid_resolution, const double grid_resolution,
double radius_neighbors = -1.) double radius_neighbors = -1.)
{ {
this->weight = 1.; this->weight() = 1.;
if (radius_neighbors < 0.) if (radius_neighbors < 0.)
radius_neighbors = 5. * grid_resolution; radius_neighbors = 5. * grid_resolution;
@ -156,4 +158,6 @@ public:
} }
}
#endif // CGAL_CLASSIFICATION_ATTRIBUTE_VERTICAL_DISPERSION_H #endif // CGAL_CLASSIFICATION_ATTRIBUTE_VERTICAL_DISPERSION_H

View File

@ -28,8 +28,10 @@ namespace CGAL {
namespace Classification { namespace Classification {
namespace Attribute {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationAttributes
\brief Attribute based on local verticality. \brief Attribute based on local verticality.
@ -44,7 +46,7 @@ namespace Classification {
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
class Attribute_verticality : public Attribute class Verticality : public Attribute_base
{ {
typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, typedef Classification::Local_eigen_analysis<Kernel, RandomAccessIterator,
PointMap, DiagonalizeTraits> Local_eigen_analysis; PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -58,11 +60,11 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param eigen Class with precompute eigenvectors and eigenvalues \param eigen Class with precompute eigenvectors and eigenvalues
*/ */
Attribute_verticality (RandomAccessIterator begin, Verticality (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
const Local_eigen_analysis& eigen) const Local_eigen_analysis& eigen)
{ {
this->weight = 1.; this->weight() = 1.;
typename Kernel::Vector_3 vertical (0., 0., 1.); typename Kernel::Vector_3 vertical (0., 0., 1.);
for (std::size_t i = 0; i < (std::size_t)(end - begin); i++) for (std::size_t i = 0; i < (std::size_t)(end - begin); i++)
@ -85,11 +87,11 @@ public:
\param normal_map Property map to access the normal vectors of the input points. \param normal_map Property map to access the normal vectors of the input points.
*/ */
template <typename VectorMap> template <typename VectorMap>
Attribute_verticality (const RandomAccessIterator& begin, Verticality (const RandomAccessIterator& begin,
const RandomAccessIterator& end, const RandomAccessIterator& end,
VectorMap normal_map) VectorMap normal_map)
{ {
this->weight = 1.; this->weight() = 1.;
typename Kernel::Vector_3 vertical (0., 0., 1.); typename Kernel::Vector_3 vertical (0., 0., 1.);
for (std::size_t i = 0; i < (std::size_t)(end - begin); i++) for (std::size_t i = 0; i < (std::size_t)(end - begin); i++)
@ -114,6 +116,8 @@ public:
/// \endcond /// \endcond
}; };
} // namespace Attribute
} // namespace Classification } // namespace Classification
} // namespace CGAL } // namespace CGAL

View File

@ -17,8 +17,8 @@
// //
// Author(s) : Simon Giraudot // Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_ATTRIBUTE_H #ifndef CGAL_CLASSIFICATION_ATTRIBUTE_BASE_H
#define CGAL_CLASSIFICATION_ATTRIBUTE_H #define CGAL_CLASSIFICATION_ATTRIBUTE_BASE_H
#include <vector> #include <vector>
@ -29,49 +29,44 @@ namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassification
\brief Abstract class describing a classification attribute. \brief Abstract class describing a classification attribute that
associates a scalar value to each item of the classification input.
A classification attribute associates a scalar value to each item
of the classification input.
*/ */
class Attribute class Attribute_base
{ {
double m_weight;
public: public:
double weight; ///< Weight of the attribute between 0 and +&infin;.
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
double mean; double mean;
double max; double max;
virtual ~Attribute() { } virtual ~Attribute_base() { }
/// \endcond /// \endcond
/*! /*!
\brief Returns the ID of the attribute. \brief Returns the weight of the attribute between 0 and +&infin;.
This method returns _abstract\_attribute_ and should be overloaded
by a child class with a specific ID.
*/ */
virtual std::string id() { return "abstract_attribute"; } double& weight() { return m_weight; }
/*! /*!
\brief Returns the value taken by the attribute on the given item. \brief Returns `abstract_attribute` and should be overloaded
by a inherited class with a specific name.
*/
virtual std::string name() { return "abstract_attribute"; }
This method must be implemented by inherited classes. /*!
\brief Returns the value taken by the attribute at the given
\param index Index of the input item. index. This method must be implemented by inherited classes.
\return the value of the attribute on the item of index `index`
*/ */
virtual double value (std::size_t index) = 0; virtual double value (std::size_t index) = 0;
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
virtual double normalized (std::size_t index) virtual double normalized (std::size_t index)
{ {
return (std::max) (0., (std::min) (1., value(index) / weight)); return (std::max) (0., (std::min) (1., value(index) / m_weight));
} }
virtual double favored (std::size_t index) { return (1. - normalized (index)); } virtual double favored (std::size_t index) { return (1. - normalized (index)); }
virtual double penalized (std::size_t index) { return normalized (index); } virtual double penalized (std::size_t index) { return normalized (index); }
@ -92,7 +87,7 @@ public:
if (vect[i] < min) if (vect[i] < min)
min = vect[i]; min = vect[i];
} }
// std::cerr << id() << " Min/max = " << min << " / " << max << std::endl; // std::cerr << name() << " Min/max = " << min << " / " << max << std::endl;
mean /= vect.size(); mean /= vect.size();
} }
@ -104,17 +99,18 @@ public:
/*! /*!
\ingroup PkgClassification \ingroup PkgClassification
\brief Handle to a classification `Attribute`. \brief Handle to a classification `Attribute_base`.
\cgalModels Handle \cgalModels Handle
*/ */
class Attribute_handle { }; class Attribute_handle { };
#else #else
typedef boost::shared_ptr<Attribute> Attribute_handle; typedef boost::shared_ptr<Attribute_base> Attribute_handle;
#endif #endif
} // namespace Classification } // namespace Classification
} // namespace CGAL } // namespace CGAL
#endif // CGAL_CLASSIFICATION_ATTRIBUTE_H #endif // CGAL_CLASSIFICATION_ATTRIBUTE_BASE_H

View File

@ -51,29 +51,27 @@ namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationDataStructures
\brief Class designed to help the user using the classification \brief Class designed to help the user using the classification
algorithm. algorithm. The classification algorithm is designed to be as flexible
as possible, letting the user free to use its own data structures,
The classification algorithm is designed to be as flexible as attributes and classification types. Nevertheless, \cgal provides a
possible, letting the user free to use its own data structures, predefined framework that should work correctly on common urban point
attributes and classification types. sets. Using this class, classification can be performed without having
to instantiate all attributes and data structures separately. This
Nevertheless, \cgal provides a predefined framework that should work class also provides functions to save and load a specific
correctly on common urban point sets. Using this class, classification
can be performed without having to instanciate all attributes and data
structures separately.
This class also provides functions to save and load a specific
configuration (attribute effects and weights), as well as a function configuration (attribute effects and weights), as well as a function
to write a classified point set in a PLY format with colors and to write a classified point set in a PLY format with colors and
labels. labels.
\tparam Kernel The geometric kernel used \tparam Kernel is a model of \cgal Kernel
\tparam RandomAccessIterator Iterator over the input \tparam RandomAccessIterator Iterator over the input
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`. \tparam PointMap is a model of `ReadablePropertyMap` whose key
\tparam DiagonalizeTraits Solver used for matrix diagonalization. type is the value type of `RandomAccessIterator` and value type is
`Point_3<Kernel>`.
\tparam DiagonalizeTraits is a model of `DiagonalizeTraits` used
for matrix diagonalization.
*/ */
template <typename Kernel, template <typename Kernel,
typename RandomAccessIterator, typename RandomAccessIterator,
@ -102,29 +100,29 @@ public:
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
typedef typename Kernel::Point_3 Point; typedef typename Kernel::Point_3 Point;
typedef Attribute_anisotropy typedef Attribute::Anisotropy
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Anisotropy; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Anisotropy;
typedef Attribute_distance_to_plane typedef Attribute::Distance_to_plane
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Distance_to_plane; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Distance_to_plane;
typedef Attribute_eigentropy typedef Attribute::Eigentropy
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Eigentropy; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Eigentropy;
typedef Attribute_elevation typedef Attribute::Elevation
<Kernel, RandomAccessIterator, PointMap> Elevation; <Kernel, RandomAccessIterator, PointMap> Elevation;
typedef Attribute_linearity typedef Attribute::Linearity
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Linearity; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Linearity;
typedef Attribute_omnivariance typedef Attribute::Omnivariance
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Omnivariance; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Omnivariance;
typedef Attribute_planarity typedef Attribute::Planarity
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Planarity; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Planarity;
typedef Attribute_sphericity typedef Attribute::Sphericity
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Sphericity; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Sphericity;
typedef Attribute_sum_eigenvalues typedef Attribute::Sum_eigenvalues
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Sum_eigen; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Sum_eigen;
typedef Attribute_surface_variation typedef Attribute::Surface_variation
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Surface_variation; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Surface_variation;
typedef Attribute_vertical_dispersion typedef Attribute::Vertical_dispersion
<Kernel, RandomAccessIterator, PointMap> Dispersion; <Kernel, RandomAccessIterator, PointMap> Dispersion;
typedef Attribute_verticality typedef Attribute::Verticality
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Verticality; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Verticality;
/// \endcond /// \endcond
@ -197,9 +195,9 @@ public:
/*! /*!
\brief Constructs an helper object. \brief Constructs a helper object.
This triggers the instanciation of all necessary data structures This triggers the instantiation of all necessary data structures
(neighborhood, eigen analysis, etc.) on the specified number of (neighborhood, eigen analysis, etc.) on the specified number of
scales. scales.
@ -207,7 +205,7 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param point_map Property map to access the input points \param point_map Property map to access the input points
\param nb_scales Number of scales. Default only uses the first \param nb_scales Number of scales. %Default only uses the first
scale (unaltered point set). Increasing this value generates scale (unaltered point set). Increasing this value generates
recursively simplified point set and computes the associated recursively simplified point set and computes the associated
attributes. Using `nb_scales=5` usually provides satisfying attributes. Using `nb_scales=5` usually provides satisfying
@ -238,16 +236,16 @@ public:
/*! /*!
\brief Constructs an helper object by loading a configuration file. \brief Constructs an helper object by loading the stream `input`.
All data structures, attributes and types specified in the input All data structures, attributes and types specified in the input
file `filename` are instanciated if possible (in particular, stream `input` are instantiated if possible (in particular,
property maps needed should be provided). property maps needed should be provided).
\tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3<Kernel>`. \tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3<Kernel>`.
\tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. \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_`. \tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_t`.
\param filename Name of the output file \param input Input stream
\param psc Classification object where to store attributes and types \param psc Classification object where to store attributes and types
\param begin Iterator to the first input object \param begin Iterator to the first input object
\param end Past-the-end iterator \param end Past-the-end iterator
@ -259,14 +257,14 @@ public:
template<typename VectorMap = CGAL::Empty_property_map<RandomAccessIterator, typename Kernel::Vector_3>, template<typename VectorMap = CGAL::Empty_property_map<RandomAccessIterator, typename Kernel::Vector_3>,
typename ColorMap = CGAL::Empty_property_map<RandomAccessIterator, RGB_Color>, typename ColorMap = CGAL::Empty_property_map<RandomAccessIterator, RGB_Color>,
typename EchoMap = CGAL::Empty_property_map<RandomAccessIterator, std::size_t> > typename EchoMap = CGAL::Empty_property_map<RandomAccessIterator, std::size_t> >
Helper (const char* filename, Classifier& psc, Helper (std::istream& input, Classifier& psc,
RandomAccessIterator begin, RandomAccessIterator end, RandomAccessIterator begin, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
VectorMap normal_map = VectorMap(), VectorMap normal_map = VectorMap(),
ColorMap color_map = ColorMap(), ColorMap color_map = ColorMap(),
EchoMap echo_map = EchoMap()) EchoMap echo_map = EchoMap())
{ {
load (filename, psc, begin, end, point_map, normal_map, color_map, echo_map); load (input, psc, begin, end, point_map, normal_map, color_map, echo_map);
} }
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
@ -313,16 +311,16 @@ public:
{ {
std::size_t nb_useful = 0; std::size_t nb_useful = 0;
for (std::size_t j = 0; j < m_scales[i]->attributes.size(); ++ j) for (std::size_t j = 0; j < m_scales[i]->attributes.size(); ++ j)
if (m_scales[i]->attributes[j]->weight != 0.) if (m_scales[i]->attributes[j]->weight() != 0.)
nb_useful ++; nb_useful ++;
std::cerr << " * scale " << i << " with size " << m_scales[i]->voxel_size std::cerr << " * scale " << i << " with size " << m_scales[i]->voxel_size
<< ", " << nb_useful << " useful attribute(s)"; << ", " << nb_useful << " useful attribute(s)";
if (nb_useful != 0) std::cerr << ":" << std::endl; if (nb_useful != 0) std::cerr << ":" << std::endl;
else std::cerr << std::endl; else std::cerr << std::endl;
for (std::size_t j = 0; j < m_scales[i]->attributes.size(); ++ j) for (std::size_t j = 0; j < m_scales[i]->attributes.size(); ++ j)
if (m_scales[i]->attributes[j]->weight != 0.) if (m_scales[i]->attributes[j]->weight() != 0.)
std::cerr << " - " << m_scales[i]->attributes[j]->id() std::cerr << " - " << m_scales[i]->attributes[j]->id()
<< " (weight = " << m_scales[i]->attributes[j]->weight << ")" << std::endl; << " (weight = " << m_scales[i]->attributes[j]->weight() << ")" << std::endl;
} }
} }
/// \endcond /// \endcond
@ -383,17 +381,17 @@ public:
Generate, for all precomputed scales, the following attributes: Generate, for all precomputed scales, the following attributes:
- `CGAL::Classification::Attribute_anisotropy` - `CGAL::Classification::Attribute::Anisotropy`
- `CGAL::Classification::Attribute_distance_to_plane` - `CGAL::Classification::Attribute::Distance_to_plane`
- `CGAL::Classification::Attribute_eigentropy` - `CGAL::Classification::Attribute::Eigentropy`
- `CGAL::Classification::Attribute_elevation` - `CGAL::Classification::Attribute::Elevation`
- `CGAL::Classification::Attribute_linearity` - `CGAL::Classification::Attribute::Linearity`
- `CGAL::Classification::Attribute_omnivariance` - `CGAL::Classification::Attribute::Omnivariance`
- `CGAL::Classification::Attribute_planarity` - `CGAL::Classification::Attribute::Planarity`
- `CGAL::Classification::Attribute_sphericity` - `CGAL::Classification::Attribute::Sphericity`
- `CGAL::Classification::Attribute_sum_eigenvalues` - `CGAL::Classification::Attribute::Sum_eigenvalues`
- `CGAL::Classification::Attribute_surface_variation` - `CGAL::Classification::Attribute::Surface_variation`
- `CGAL::Classification::Attribute_vertical_dispersion` - `CGAL::Classification::Attribute::Vertical_dispersion`
\param psc The classification object where to store the attributes \param psc The classification object where to store the attributes
\param begin Iterator to the first input object \param begin Iterator to the first input object
@ -430,7 +428,7 @@ public:
Generate, for all precomputed scales, the following attribute: Generate, for all precomputed scales, the following attribute:
- `CGAL::Classification::Attribute_verticality` - `CGAL::Classification::Attribute::Verticality`
If the normal map is left to its default type If the normal map is left to its default type
`CGAL::Empty_property_map`, then the verticality attributes are `CGAL::Empty_property_map`, then the verticality attributes are
@ -480,15 +478,15 @@ public:
Generate the following attributes: Generate the following attributes:
- 9 attributes `CGAL::Classification::Attribute_hsv` on - 9 attributes `CGAL::Classification::Attribute::Hsv` on
channel 0 (hue) with mean ranging from 0° to 360° and standard channel 0 (hue) with mean ranging from 0° to 360° and standard
deviation of 22.5. deviation of 22.5.
- 5 attributes `CGAL::Classification::Attribute_hsv` on - 5 attributes `CGAL::Classification::Attribute::Hsv` on
channel 1 (saturation) with mean ranging from 0 to 100 and standard channel 1 (saturation) with mean ranging from 0 to 100 and standard
deviation of 12.5 deviation of 12.5
- 5 attributes `CGAL::Classification::Attribute_hsv` on - 5 attributes `CGAL::Classification::Attribute::Hsv` on
channel 2 (value) with mean ranging from 0 to 100 and standard channel 2 (value) with mean ranging from 0 to 100 and standard
deviation of 12.5 deviation of 12.5
@ -507,7 +505,7 @@ public:
ColorMap color_map) ColorMap color_map)
{ {
typedef Attribute_hsv<Kernel, RandomAccessIterator, ColorMap> Hsv; typedef Attribute::Hsv<Kernel, RandomAccessIterator, ColorMap> Hsv;
CGAL::Timer t; t.start(); CGAL::Timer t; t.start();
for (std::size_t i = 0; i <= 8; ++ i) for (std::size_t i = 0; i <= 8; ++ i)
{ {
@ -541,7 +539,7 @@ public:
Generate, for all precomputed scales, the following attribute: Generate, for all precomputed scales, the following attribute:
- `CGAL::Classification::Attribute_echo_scatter` - `CGAL::Classification::Attribute::Echo_scatter`
\tparam EchoMap Property map to access the echo values of the input points (if any). \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 psc The classification object where to store the attributes
@ -554,7 +552,7 @@ public:
RandomAccessIterator begin, RandomAccessIterator end, RandomAccessIterator begin, RandomAccessIterator end,
EchoMap echo_map) EchoMap echo_map)
{ {
typedef Attribute_echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap> Echo_scatter; typedef Attribute::Echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap> Echo_scatter;
CGAL::Timer t; t.start(); CGAL::Timer t; t.start();
for (std::size_t i = 0; i < m_scales.size(); ++ i) for (std::size_t i = 0; i < m_scales.size(); ++ i)
{ {
@ -601,7 +599,7 @@ public:
/*! /*!
\brief Saves the current configuration in the file `filename`. \brief Saves the current configuration in the stream `output`.
This allows to easily save and recover a specific classification This allows to easily save and recover a specific classification
configuration, that is to say: configuration, that is to say:
@ -614,10 +612,10 @@ public:
the `load()` method and the constructor that takes a file name the `load()` method and the constructor that takes a file name
as parameter. as parameter.
\param filename Name of the output file \param output Output stream
\param psc Classification object whose attributes and types must be saved \param psc Classification object whose attributes and types must be saved
*/ */
void save (const char* filename, Classifier& psc) void save (std::ostream& output, Classifier& psc)
{ {
boost::property_tree::ptree tree; boost::property_tree::ptree tree;
@ -631,12 +629,12 @@ public:
for (std::size_t i = 0; i < psc.number_of_attributes(); ++ i) for (std::size_t i = 0; i < psc.number_of_attributes(); ++ i)
{ {
Attribute_handle att = psc.get_attribute(i); Attribute_handle att = psc.get_attribute(i);
if (att->weight == 0) if (att->weight() == 0)
continue; continue;
boost::property_tree::ptree ptr; boost::property_tree::ptree ptr;
ptr.put("id", name_att (att, map_scale)); ptr.put("id", name_att (att, map_scale));
ptr.put("weight", att->weight); ptr.put("weight", att->weight());
tree.add_child("classification.attributes.attribute", ptr); tree.add_child("classification.attributes.attribute", ptr);
} }
@ -649,16 +647,16 @@ public:
for (std::size_t j = 0; j < psc.number_of_attributes(); ++ j) for (std::size_t j = 0; j < psc.number_of_attributes(); ++ j)
{ {
Attribute_handle att = psc.get_attribute(j); Attribute_handle att = psc.get_attribute(j);
if (att->weight == 0) if (att->weight() == 0)
continue; continue;
boost::property_tree::ptree ptr2; boost::property_tree::ptree ptr2;
ptr2.put("id", name_att (att, map_scale)); ptr2.put("id", name_att (att, map_scale));
Type::Attribute_effect effect = type->attribute_effect(att); Attribute::Effect effect = type->attribute_effect(att);
if (effect == Type::Attribute_effect::PENALIZED_ATT) if (effect == Attribute::PENALIZING)
ptr2.put("effect", "penalized"); ptr2.put("effect", "penalized");
else if (effect == Type::Attribute_effect::NEUTRAL_ATT) else if (effect == Attribute::NEUTRAL)
ptr2.put("effect", "neutral"); ptr2.put("effect", "neutral");
else if (effect == Type::Attribute_effect::FAVORED_ATT) else if (effect == Attribute::FAVORING)
ptr2.put("effect", "favored"); ptr2.put("effect", "favored");
ptr.add_child("attribute", ptr2); ptr.add_child("attribute", ptr2);
} }
@ -667,15 +665,15 @@ public:
// Write property tree to XML file // Write property tree to XML file
boost::property_tree::xml_writer_settings<std::string> settings(' ', 3); boost::property_tree::xml_writer_settings<std::string> settings(' ', 3);
boost::property_tree::write_xml(filename, tree, std::locale(), settings); boost::property_tree::write_xml(output, tree, settings);
} }
/*! /*!
\brief Load a configuration from the file `filename`. \brief Load a configuration from the stream `input`.
All data structures, attributes and types specified in the input All data structures, attributes and types specified in the input
file `filename` are instanciated if possible (in particular, stream `input` are instantiated if possible (in particular,
property maps needed should be provided). property maps needed should be provided).
The input file is written in an XML format written by the `save()` The input file is written in an XML format written by the `save()`
@ -684,7 +682,7 @@ public:
\tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3<Kernel>`. \tparam VectorMap is a model of `ReadablePropertyMap` with value type `Vector_3<Kernel>`.
\tparam ColorMap is a model of `ReadablePropertyMap` with value type `CGAL::Classification::RGB_Color`. \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_`. \tparam EchoMap is a model of `ReadablePropertyMap` with value type `std::size_`.
\param filename Name of the output file \param input Input stream
\param psc Classification object where to store attributes and types \param psc Classification object where to store attributes and types
\param begin Iterator to the first input object \param begin Iterator to the first input object
\param end Past-the-end iterator \param end Past-the-end iterator
@ -696,7 +694,7 @@ public:
template<typename VectorMap = CGAL::Empty_property_map<RandomAccessIterator, typename Kernel::Vector_3>, template<typename VectorMap = CGAL::Empty_property_map<RandomAccessIterator, typename Kernel::Vector_3>,
typename ColorMap = CGAL::Empty_property_map<RandomAccessIterator, RGB_Color>, typename ColorMap = CGAL::Empty_property_map<RandomAccessIterator, RGB_Color>,
typename EchoMap = CGAL::Empty_property_map<RandomAccessIterator, std::size_t> > typename EchoMap = CGAL::Empty_property_map<RandomAccessIterator, std::size_t> >
bool load (const char* filename, Classifier& psc, bool load (std::istream& input, Classifier& psc,
RandomAccessIterator begin, RandomAccessIterator end, RandomAccessIterator begin, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
VectorMap normal_map = VectorMap(), VectorMap normal_map = VectorMap(),
@ -704,8 +702,8 @@ public:
EchoMap echo_map = EchoMap()) EchoMap echo_map = EchoMap())
{ {
typedef Attribute_echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap> Echo_scatter; typedef Attribute::Echo_scatter<Kernel, RandomAccessIterator, PointMap, EchoMap> Echo_scatter;
typedef Attribute_hsv<Kernel, RandomAccessIterator, ColorMap> Hsv; typedef Attribute::Hsv<Kernel, RandomAccessIterator, ColorMap> Hsv;
clear(); clear();
@ -714,7 +712,7 @@ public:
boost::make_transform_iterator (end, CGAL::Property_map_to_unary_function<PointMap>(point_map))); boost::make_transform_iterator (end, CGAL::Property_map_to_unary_function<PointMap>(point_map)));
boost::property_tree::ptree tree; boost::property_tree::ptree tree;
boost::property_tree::read_xml(filename, tree); boost::property_tree::read_xml(input, tree);
double voxel_size = tree.get<double>("classification.parameters.voxel_size"); double voxel_size = tree.get<double>("classification.parameters.voxel_size");
@ -829,7 +827,7 @@ public:
Attribute_handle att = psc.get_attribute (psc.number_of_attributes() - 1); Attribute_handle att = psc.get_attribute (psc.number_of_attributes() - 1);
m_scales[scale]->attributes.push_back (att); m_scales[scale]->attributes.push_back (att);
att->weight = weight; att->weight() = weight;
att_map[full_id] = att; att_map[full_id] = att;
} }
std::cerr << "Elevation took " << t.time() << " second(s)" << std::endl; std::cerr << "Elevation took " << t.time() << " second(s)" << std::endl;
@ -851,11 +849,11 @@ public:
Attribute_handle att = it->second; Attribute_handle att = it->second;
std::string effect = v2.second.get<std::string>("effect"); std::string effect = v2.second.get<std::string>("effect");
if (effect == "penalized") if (effect == "penalized")
new_type->set_attribute_effect (att, Type::PENALIZED_ATT); new_type->set_attribute_effect (att, Attribute::PENALIZING);
else if (effect == "neutral") else if (effect == "neutral")
new_type->set_attribute_effect (att, Type::NEUTRAL_ATT); new_type->set_attribute_effect (att, Attribute::NEUTRAL);
else else
new_type->set_attribute_effect (att, Type::FAVORED_ATT); new_type->set_attribute_effect (att, Attribute::FAVORING);
} }
} }

View File

@ -14,16 +14,19 @@ namespace CGAL {
namespace Classification { namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationDataStructures
\brief Class that precomputes and stored the eigenvectors and \brief Class that precomputes and stored the eigenvectors and
eigenvalues of the covariance matrices of all points of a point eigenvalues of the covariance matrices of all points of a point
set, using a local neighborhood. set using a local neighborhood.
\tparam Kernel The geometric kernel used. \tparam Kernel is a model of \cgal Kernel.
\tparam RandomAccessIterator Iterator over the input. \tparam RandomAccessIterator Iterator over the input.
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`. \tparam PointMap is a model of `ReadablePropertyMap` whose key
\tparam DiagonalizeTraits Solver used for matrix diagonalization. type is the value type of `RandomAccessIterator` and value type is
`Point_3<Kernel>`.
\tparam DiagonalizeTraits is a model of `DiagonalizeTraits` used
for matrix diagonalization.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap, template <typename Kernel, typename RandomAccessIterator, typename PointMap,
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> > typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<double,3> >
@ -44,7 +47,7 @@ private:
std::vector<Vector> m_smallest_eigenvectors; std::vector<Vector> m_smallest_eigenvectors;
std::vector<Vector> m_middle_eigenvectors; std::vector<Vector> m_middle_eigenvectors;
std::vector<Vector> m_largest_eigenvectors; std::vector<Vector> m_largest_eigenvectors;
double m_mean_range;
public: public:
@ -62,18 +65,13 @@ public:
\param begin Iterator to the first input object \param begin Iterator to the first input object
\param end Past-the-end iterator \param end Past-the-end iterator
\param point_map Property map to access the input points \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
\param mean_range The mean value of the range corresponding to the
`knn` number of neighbors is returned by the constructor through
this reference.
*/ */
template <typename NeighborQuery> template <typename NeighborQuery>
Local_eigen_analysis (RandomAccessIterator begin, Local_eigen_analysis (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
const NeighborQuery& neighbor_query, const NeighborQuery& neighbor_query)
double& mean_range)
{ {
std::size_t size = end - begin; std::size_t size = end - begin;
m_eigenvalues.reserve (size); m_eigenvalues.reserve (size);
@ -82,7 +80,7 @@ public:
m_middle_eigenvectors.reserve (size); m_middle_eigenvectors.reserve (size);
m_largest_eigenvectors.reserve (size); m_largest_eigenvectors.reserve (size);
mean_range = 0.; m_mean_range = 0.;
for (std::size_t i = 0; i < size; i++) for (std::size_t i = 0; i < size; i++)
{ {
@ -93,17 +91,17 @@ public:
for (std::size_t j = 0; j < neighbors.size(); ++ j) for (std::size_t j = 0; j < neighbors.size(); ++ j)
neighbor_points.push_back (get(point_map, begin[neighbors[j]])); neighbor_points.push_back (get(point_map, begin[neighbors[j]]));
mean_range += CGAL::sqrt (CGAL::squared_distance (get(point_map, begin[i]), m_mean_range += CGAL::sqrt (CGAL::squared_distance (get(point_map, begin[i]),
get(point_map, begin[neighbors.back()]))); get(point_map, begin[neighbors.back()])));
compute (get(point_map, begin[i]), neighbor_points); compute (get(point_map, begin[i]), neighbor_points);
} }
mean_range /= size; m_mean_range /= size;
} }
/*! /*!
\brief Returns the estimated normal vector of the indexed point. \brief Returns the estimated unoriented normal vector of the indexed point.
*/ */
const Vector& normal_vector (std::size_t index) const { return m_smallest_eigenvectors[index]; } const Vector& normal_vector (std::size_t index) const { return m_smallest_eigenvectors[index]; }
@ -120,7 +118,11 @@ public:
/*! /*!
\brief Returns the sum of eigenvalues of the index point. \brief Returns the sum of eigenvalues of the index point.
*/ */
const double& sum_eigenvalues (std::size_t index) const { return m_sum_eigenvalues[index]; } const double& sum_of_eigenvalues (std::size_t index) const { return m_sum_eigenvalues[index]; }
/// \cond SKIP_IN_MANUAL
double mean_range() const { return m_mean_range; }
/// \endcond
private: private:

View File

@ -10,14 +10,20 @@ namespace CGAL {
namespace Classification { namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationDataStructures
\brief Class that precomputes a 2D planimetric grid used for \brief Class that precomputes a 2D planimetric grid.
digital terrain modeling.
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.
\tparam Kernel The geometric kernel used. \tparam Kernel The geometric kernel used.
\tparam RandomAccessIterator Iterator over the input. \tparam RandomAccessIterator Iterator over the input.
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`. \tparam PointMap is a model of `ReadablePropertyMap` whose key
type is the value type of `RandomAccessIterator` and value type is
`Point_3<Kernel>`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap>
@ -72,15 +78,22 @@ public:
} }
/*!
\brief Returns the number of cells along the X-axis.
*/
std::size_t width() const { return m_grid.width(); } std::size_t width() const { return m_grid.width(); }
/*!
\brief Returns the number of cells along the Y-axis.
*/
std::size_t height() const { return m_grid.height(); } 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 points lying in the given indexed cell.
*/ */
const std::vector<std::size_t>& indices(std::size_t x, std::size_t y) const { return m_grid(x,y); } const std::vector<std::size_t>& indices(std::size_t x, std::size_t y) const { return m_grid(x,y); }
/*! /*!
\brief Returns `true` if the indexed cell is to be used for classification. \brief Returns `false` if the cell indexed by `(x,y)` is empty, `true` otherwise.
*/ */
bool mask(std::size_t x, std::size_t y) const { return (!(m_grid(x,y).empty())); } bool mask(std::size_t x, std::size_t y) const { return (!(m_grid(x,y).empty())); }

View File

@ -19,14 +19,24 @@ namespace CGAL {
namespace Classification { namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassificationDataStructures
\brief Class that precomputes spatial searching structures and \brief Class that precomputes spatial searching structures for an
gives easy access to local neighborhoods of points. input point set and gives easy access to local neighborhoods of
points.
\tparam Kernel The geometric kernel used. It allows the user to generate models of `NeighborQuery` based on
a fixed range neighborhood or on a fixed K number of neighbors. In
addition, the spatial searching structures can be computed on a
simplified version of the point set to allow for neighbor queries
at a higher scale.
\tparam Kernel is a model of \cgal Kernel.
\tparam RandomAccessIterator Iterator over the input. \tparam RandomAccessIterator Iterator over the input.
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`.
\tparam PointMap is a model of `ReadablePropertyMap` whose key
type is the value type of `RandomAccessIterator` and value type is
`Point_3<Kernel>`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap>
class Point_set_neighborhood class Point_set_neighborhood
@ -69,7 +79,8 @@ class Point_set_neighborhood
public: public:
/*! /*!
Functor that returns a neighborhood with a fixed number of points. Functor that computes the neighborhood of an input point with a
fixed number of neighbors.
\cgalModels NeighborQuery \cgalModels NeighborQuery
*/ */
@ -99,7 +110,9 @@ public:
}; };
/*! /*!
Functor that returns a neighborhood with a fixed radius. Functor that computes the neighborhood of an input point defined
as the points lying in a sphere of fixed radius centered at the
input point.
\cgalModels NeighborQuery \cgalModels NeighborQuery
*/ */

View File

@ -8,37 +8,27 @@ namespace Classification {
/*! /*!
\ingroup PkgClassification \ingroup PkgClassification
\brief Classification type. \brief %Classification type (for example: vegetation, ground, etc.)
defined as a set of relationship with classification attributes.
A type is what is sought after when performing classification on an
input set (for example: vegetation, ground, etc.). It is defined
as a set of relationship with classification attributes.
*/ */
class Type class Type
{ {
public: public:
enum Attribute_effect /// Defines how an attribute affects this type.
{
FAVORED_ATT = 0, ///< High values of the attribute favor this type
NEUTRAL_ATT = 1, ///< The attribute has no effect on this type
PENALIZED_ATT = 2 ///< Low values of the attribute favor this type
};
private: private:
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
std::string m_id; std::string m_name;
std::map<Attribute_handle, Attribute_effect> m_attribute_effects; std::map<Attribute_handle, Attribute_effect> m_attribute_effects;
/// \endcond /// \endcond
public: public:
/*! /*!
\param id The name of the classification type \param name The name of the classification type
(e.g. vegetation). (e.g. vegetation).
*/ */
Type (std::string id) : m_id (id) { } Type (std::string name) : m_name (name) { }
/*! /*!
\brief Sets how an attribute affects the classification type. \brief Sets how an attribute affects the classification type.
@ -60,27 +50,24 @@ public:
{ {
std::map<Attribute_handle, Attribute_effect>::iterator std::map<Attribute_handle, Attribute_effect>::iterator
search = m_attribute_effects.find (att); search = m_attribute_effects.find (att);
return (search == m_attribute_effects.end () ? NEUTRAL_ATT : search->second); return (search == m_attribute_effects.end () ? NEUTRAL : search->second);
} }
/*! const std::string& name() const { return m_name; }
\brief Returns the ID of the classification type.
*/
const std::string& id() const { return m_id; }
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
void info() void info()
{ {
std::cerr << "Attribute " << m_id << ": "; std::cerr << "Attribute " << m_name << ": ";
for (std::map<Attribute_handle, Attribute_effect>::iterator it = m_attribute_effects.begin(); for (std::map<Attribute_handle, Attribute_effect>::iterator it = m_attribute_effects.begin();
it != m_attribute_effects.end(); ++ it) it != m_attribute_effects.end(); ++ it)
{ {
if (it->second == NEUTRAL_ATT) if (it->second == NEUTRAL)
continue; continue;
std::cerr << it->first; std::cerr << it->first;
if (it->second == FAVORED_ATT) std::cerr << " (favored), "; if (it->second == FAVORING) std::cerr << " (favored), ";
else if (it->second == PENALIZED_ATT) std::cerr << " (penalized), "; else if (it->second == PENALIZING) std::cerr << " (penalized), ";
} }
std::cerr << std::endl; std::cerr << std::endl;
} }

View File

@ -60,31 +60,31 @@ namespace CGAL {
\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 attribute and a set of classification types.
This class implement the core of the algorithm. It uses a data set as This class implements the core of the classification algorithm
input and assign each input iterator to a classification type among a \cgalCite{cgal:lm-clscm-12}. It uses a data set as input and assignes
set of user defined classification types. each input iterator to a classification type among a set of user
defined classification types.
To achieve this classification algorithm, a set of local geometric To achieve this classification algorithm, a set of local geometric
attributes are used, such as: attributes are used, such as planarity, elevation or vertical
dispersion.
- planarity The user must define a set of classification types such as building,
- elevation ground or vegetation.
- vertical dispersion
The user must define a set of classification types such as: 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.
- building \tparam RandomAccessIterator %Iterator over the input items, model of
- ground `RandomAccessIterator`
- vegetation
Each pair of attribute/type must be assigned an effect (for example, \tparam ItemMap is a model of `ReadablePropertyMap` that accesses the
vegetation has a low planarity and a high vertical dispersion) and item type from the value_type of `RandomAccessIterator`
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.
\tparam RandomAccessIterator Iterator over the input items
\tparam ItemMap is a model of `ReadablePropertyMap`
*/ */
template <typename RandomAccessIterator, template <typename RandomAccessIterator,
@ -143,7 +143,7 @@ private:
std::vector<Type_handle> m_types; std::vector<Type_handle> m_types;
std::vector<Attribute_handle> m_attributes; std::vector<Attribute_handle> m_attributes;
typedef Classification::Type::Attribute_effect Attribute_effect; typedef Classification::Attribute::Effect Attribute_effect;
std::vector<std::vector<Attribute_effect> > m_effect_table; std::vector<std::vector<Attribute_effect> > m_effect_table;
/// \endcond /// \endcond
@ -155,10 +155,7 @@ public:
/// @{ /// @{
/*! /*!
\brief Constructs a classification object based on the input iterators. \brief Initializes a classification object based on the input iterators.
This method just initializes the structure and does not compute
anything.
\param begin Iterator to the first input object \param begin Iterator to the first input object
@ -288,10 +285,10 @@ public:
/*! /*!
\brief Runs the classification algorithm with a global \brief Runs the classification algorithm with a global
regularizarion based on a graphcut. regularization based on a graphcut.
The computed classification energy is globally regularized through The computed classification energy is globally regularized through
and alpha-expansion algorithm. This method is slow but provides an alpha-expansion algorithm. This method is slow but provides
the user with good quality results. the user with good quality results.
\tparam NeighborQuery is a model of `NeighborQuery` \tparam NeighborQuery is a model of `NeighborQuery`
@ -357,7 +354,7 @@ public:
/// @{ /// @{
/*! /*!
\brief Instanciates and adds a classification type. \brief Instantiates and adds a classification type.
\param name ID of the classification type. \param name ID of the classification type.
@ -450,7 +447,7 @@ public:
/*! /*!
\brief Adds an attribute. \brief Adds an attribute.
\param attribute Handle of the attribute to add. \param attribute %Handle of the attribute to add.
*/ */
void add_attribute (Attribute_handle attribute) void add_attribute (Attribute_handle attribute)
{ {
@ -487,11 +484,11 @@ public:
\note If classification was not performed (using `run()`, \note If classification was not performed (using `run()`,
`run_with_local_smoothing()` or `run_with_graphcut()`), this `run_with_local_smoothing()` or `run_with_graphcut()`), this
function always returns the default empty `Type_handle`. function always returns the default `Type_handle`.
\param index Index of the input item \param index %Index of the input item
\return Pointer to the classification type \return %Handle to the classification type
*/ */
Type_handle classification_type_of (std::size_t index) const Type_handle classification_type_of (std::size_t index) const
{ {
@ -527,7 +524,7 @@ public:
`run_with_local_smoothing()` or `run_with_graphcut()`), this `run_with_local_smoothing()` or `run_with_graphcut()`), this
function always returns 0. function always returns 0.
\param index Index of the input item \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 double confidence_of (std::size_t index) const
@ -546,9 +543,9 @@ public:
/*! /*!
\brief Runs the training algorithm. \brief Runs the training algorithm.
The object must have been filled with the `Classification::Type` All the `Classification::Type` and `Classification::Attribute`
and `Classification::Attribute` objects before running this necessary for the classification should have been registered in
function. the object before running this function.
Each classification type must be given a small set of user-defined Each classification type must be given a small set of user-defined
inliers to provide the training algorithm with a ground truth. inliers to provide the training algorithm with a ground truth.
@ -563,7 +560,7 @@ public:
configuration found. configuration found.
*/ */
double training (std::size_t nb_tests = 300) double train (std::size_t nb_tests = 300)
{ {
if (m_training_type.empty()) if (m_training_type.empty())
return 0.; return 0.;
@ -594,13 +591,13 @@ public:
for (std::size_t j = 0; j < m_attributes.size(); ++ j) for (std::size_t j = 0; j < m_attributes.size(); ++ j)
{ {
Attribute_handle att = m_attributes[j]; Attribute_handle att = m_attributes[j];
best_weights[j] = att->weight; best_weights[j] = att->weight();
std::size_t nb_useful = 0; std::size_t nb_useful = 0;
double min = (std::numeric_limits<double>::max)(); double min = (std::numeric_limits<double>::max)();
double max = -(std::numeric_limits<double>::max)(); double max = -(std::numeric_limits<double>::max)();
att->weight = wmin; att->weight() = wmin;
for (std::size_t i = 0; i < 100; ++ i) for (std::size_t i = 0; i < 100; ++ i)
{ {
estimate_attribute_effect(training_sets, att); estimate_attribute_effect(training_sets, att);
@ -608,12 +605,12 @@ public:
{ {
CGAL_CLASSTRAINING_CERR << "#"; CGAL_CLASSTRAINING_CERR << "#";
nb_useful ++; nb_useful ++;
min = (std::min) (min, att->weight); min = (std::min) (min, att->weight());
max = (std::max) (max, att->weight); max = (std::max) (max, att->weight());
} }
else else
CGAL_CLASSTRAINING_CERR << "-"; CGAL_CLASSTRAINING_CERR << "-";
att->weight *= factor; att->weight() *= factor;
} }
CGAL_CLASSTRAINING_CERR << std::endl; CGAL_CLASSTRAINING_CERR << std::endl;
CGAL_CLASSTRAINING_CERR << att->id() << " useful in " CGAL_CLASSTRAINING_CERR << att->id() << " useful in "
@ -626,18 +623,18 @@ public:
if (nb_useful < 2) if (nb_useful < 2)
{ {
att_train.back().skipped = true; att_train.back().skipped = true;
att->weight = 0.; att->weight() = 0.;
best_weights[j] = att->weight; best_weights[j] = att->weight();
} }
else if (best_weights[j] == 1.) else if (best_weights[j] == 1.)
{ {
att->weight = 0.5 * (att_train.back().wmin + att_train.back().wmax); att->weight() = 0.5 * (att_train.back().wmin + att_train.back().wmax);
best_weights[j] = att->weight; best_weights[j] = att->weight();
++ att_used; ++ att_used;
} }
else else
{ {
att->weight = best_weights[j]; att->weight() = best_weights[j];
++ att_used; ++ att_used;
} }
estimate_attribute_effect(training_sets, att); estimate_attribute_effect(training_sets, att);
@ -677,7 +674,7 @@ public:
if (j == current_att_changed) if (j == current_att_changed)
continue; continue;
m_attributes[j]->weight = best_weights[j]; m_attributes[j]->weight() = best_weights[j];
estimate_attribute_effect(training_sets, m_attributes[j]); estimate_attribute_effect(training_sets, m_attributes[j]);
if (attribute_useful(m_attributes[j])) if (attribute_useful(m_attributes[j]))
nb_used ++; nb_used ++;
@ -685,7 +682,7 @@ public:
Attribute_handle current_att = m_attributes[current_att_changed]; Attribute_handle current_att = m_attributes[current_att_changed];
const Attribute_training& tr = att_train[current_att_changed]; const Attribute_training& tr = att_train[current_att_changed];
current_att->weight = tr.wmin; current_att->weight() = tr.wmin;
for (std::size_t j = 0; j < nb_trials_per_attribute; ++ j) for (std::size_t j = 0; j < nb_trials_per_attribute; ++ j)
{ {
estimate_attribute_effect(training_sets, current_att); estimate_attribute_effect(training_sets, current_att);
@ -709,11 +706,11 @@ public:
for (std::size_t k = 0; k < m_attributes.size(); ++ k) for (std::size_t k = 0; k < m_attributes.size(); ++ k)
{ {
Attribute_handle att = m_attributes[k]; Attribute_handle att = m_attributes[k];
best_weights[k] = att->weight; best_weights[k] = att->weight();
} }
} }
current_att->weight *= tr.factor; current_att->weight() *= tr.factor;
} }
++ current_att_changed; ++ current_att_changed;
@ -722,7 +719,7 @@ public:
for (std::size_t i = 0; i < best_weights.size(); ++ i) for (std::size_t i = 0; i < best_weights.size(); ++ i)
{ {
Attribute_handle att = m_attributes[i]; Attribute_handle att = m_attributes[i];
att->weight = best_weights[i]; att->weight() = best_weights[i];
} }
estimate_attributes_effects(training_sets); estimate_attributes_effects(training_sets);
@ -735,16 +732,16 @@ public:
{ {
Attribute_handle att = m_attributes[i]; Attribute_handle att = m_attributes[i];
CGAL_CLASSTRAINING_CERR << "ATTRIBUTE " << att->id() << ": " << best_weights[i] << std::endl; CGAL_CLASSTRAINING_CERR << "ATTRIBUTE " << att->id() << ": " << best_weights[i] << std::endl;
att->weight = best_weights[i]; att->weight() = best_weights[i];
Classification::Type::Attribute_effect side = m_types[0]->attribute_effect(att); Classification::Type::Attribute_effect side = m_types[0]->attribute_effect(att);
bool to_remove = true; bool to_remove = true;
for (std::size_t j = 0; j < m_types.size(); ++ j) for (std::size_t j = 0; j < m_types.size(); ++ j)
{ {
Type_handle ctype = m_types[j]; Type_handle ctype = m_types[j];
if (ctype->attribute_effect(att) == Classification::Type::FAVORED_ATT) if (ctype->attribute_effect(att) == Classification::Type::FAVORING)
CGAL_CLASSTRAINING_CERR << " * Favored for "; CGAL_CLASSTRAINING_CERR << " * Favored for ";
else if (ctype->attribute_effect(att) == Classification::Type::PENALIZED_ATT) else if (ctype->attribute_effect(att) == Classification::Type::PENALIZING)
CGAL_CLASSTRAINING_CERR << " * Penalized for "; CGAL_CLASSTRAINING_CERR << " * Penalized for ";
else else
CGAL_CLASSTRAINING_CERR << " * Neutral for "; CGAL_CLASSTRAINING_CERR << " * Neutral for ";
@ -777,9 +774,9 @@ public:
\brief Adds the input item specified by index `idx` as an inlier \brief Adds the input item specified by index `idx` as an inlier
of `class_type` for the training algorithm. of `class_type` for the training algorithm.
\param class_type Handle to the classification type. \param class_type %Handle to the classification type.
\param idx Index of the input item. \param idx %Index of the input item.
*/ */
bool add_training_index (Type_handle class_type, bool add_training_index (Type_handle class_type,
std::size_t idx) std::size_t idx)
@ -805,7 +802,7 @@ public:
\brief Adds input items specified by a range of indices as \brief Adds input items specified by a range of indices as
inliers of `class_type` for the training algorithm. inliers of `class_type` for the training algorithm.
\param class_type Handle to the classification type. \param class_type %Handle to the classification type.
\param first Iterator to the first index to add \param first Iterator to the first index to add
\param beyond Past-the-end iterator \param beyond Past-the-end iterator
@ -856,7 +853,7 @@ public:
m_effect_table = std::vector<std::vector<Attribute_effect> > m_effect_table = std::vector<std::vector<Attribute_effect> >
(m_types.size(), std::vector<Attribute_effect> (m_attributes.size(), (m_types.size(), std::vector<Attribute_effect> (m_attributes.size(),
Classification::Type::NEUTRAL_ATT)); Classification::Type::NEUTRAL));
for (std::size_t i = 0; i < m_effect_table.size (); ++ i) for (std::size_t i = 0; i < m_effect_table.size (); ++ i)
for (std::size_t j = 0; j < m_effect_table[i].size (); ++ j) for (std::size_t j = 0; j < m_effect_table[i].size (); ++ j)
@ -875,13 +872,13 @@ private:
double out = 0.; double out = 0.;
for (std::size_t i = 0; i < m_effect_table[class_type].size(); ++ i) for (std::size_t i = 0; i < m_effect_table[class_type].size(); ++ i)
{ {
if (m_attributes[i]->weight == 0.) if (m_attributes[i]->weight() == 0.)
continue; continue;
if (m_effect_table[class_type][i] == Classification::Type::FAVORED_ATT) if (m_effect_table[class_type][i] == Classification::Type::FAVORING)
out += m_attributes[i]->favored (pt_index); out += m_attributes[i]->favored (pt_index);
else if (m_effect_table[class_type][i] == Classification::Type::PENALIZED_ATT) else if (m_effect_table[class_type][i] == Classification::Type::PENALIZING)
out += m_attributes[i]->penalized (pt_index); out += m_attributes[i]->penalized (pt_index);
else if (m_effect_table[class_type][i] == Classification::Type::NEUTRAL_ATT) else if (m_effect_table[class_type][i] == Classification::Type::NEUTRAL)
out += m_attributes[i]->ignored (pt_index); out += m_attributes[i]->ignored (pt_index);
} }
return out; return out;
@ -924,11 +921,11 @@ private:
} }
sd[j] = std::sqrt (sd[j] / training_sets[j].size()); sd[j] = std::sqrt (sd[j] / training_sets[j].size());
if (mean[j] - sd[j] > 0.5) if (mean[j] - sd[j] > 0.5)
ctype->set_attribute_effect (att, Classification::Type::FAVORED_ATT); ctype->set_attribute_effect (att, Classification::Type::FAVORING);
else if (mean[j] + sd[j] < 0.5) else if (mean[j] + sd[j] < 0.5)
ctype->set_attribute_effect (att, Classification::Type::PENALIZED_ATT); ctype->set_attribute_effect (att, Classification::Type::PENALIZING);
else else
ctype->set_attribute_effect (att, Classification::Type::NEUTRAL_ATT); ctype->set_attribute_effect (att, Classification::Type::NEUTRAL);
} }
} }

View File

@ -20,7 +20,6 @@
% %
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
@article{ cgal:afh-pdecm-02, @article{ cgal:afh-pdecm-02,
author = "P. K. Agarwal and E. Flato and D. Halperin", author = "P. K. Agarwal and E. Flato and D. Halperin",
title = "Polygon Decomposition for Efficient Construction of {Minkowski} Sums", title = "Polygon Decomposition for Efficient Construction of {Minkowski} Sums",
@ -977,6 +976,15 @@ note = {\url{ttp://hal.inria.fr/inria-00090522}}
, pages = "209--225" , pages = "209--225"
} }
@article{cgal:hws-fsso3-16,
title={Fast semantic segmentation of 3D point clouds with strongly varying density},
author={Hackel, Timo and Wegner, Jan D and Schindler, Konrad},
journal={ISPRS Annals of the Photogrammetry, Remote Sensing and Spatial Information Sciences, Prague, Czech Republic},
volume={3},
pages={177--184},
year={2016}
}
@book{ cgal:hw-vrml2h-96 @book{ cgal:hw-vrml2h-96
,author = {Jed Hartman and Josie Wernecke} ,author = {Jed Hartman and Josie Wernecke}
,title = {The {VRML} 2.0 Handbook: Building Moving Worlds on the ,title = {The {VRML} 2.0 Handbook: Building Moving Worlds on the
@ -1038,6 +1046,15 @@ note = {\url{ttp://hal.inria.fr/inria-00090522}}
,pages = "307--320" ,pages = "307--320"
} }
@book{ cgal:l-mrfmi-09,
author = {Li, Stan Z.},
title = {Markov Random Field Modeling in Image Analysis},
year = {2009},
isbn = {9781848002784},
edition = {3rd},
publisher = {Springer Publishing Company, Incorporated}
}
@inproceedings { cgal:l-nmdgp-05, @inproceedings { cgal:l-nmdgp-05,
AUTHOR = {Bruno Levy}, AUTHOR = {Bruno Levy},
TITLE = {Numerical Methods for Digital Geometry Processing}, TITLE = {Numerical Methods for Digital Geometry Processing},

View File

@ -1395,7 +1395,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output. # generate Latex output.
GENERATE_LATEX = NO GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be # If a relative path is entered the value of OUTPUT_DIRECTORY will be

View File

@ -793,15 +793,15 @@ public Q_SLOTS:
// std::cerr << att->weight // std::cerr << att->weight
// << " " << (int)(1001. * 2. * std::atan(att->weight) / CGAL_PI) << std::endl; // << " " << (int)(1001. * 2. * std::atan(att->weight) / CGAL_PI) << std::endl;
ui_widget.attribute_weight->setValue ((int)(1001. * 2. * std::atan(att->weight) / CGAL_PI)); ui_widget.attribute_weight->setValue ((int)(1001. * 2. * std::atan(att->weight()) / CGAL_PI));
for (std::size_t i = 0; i < classification_item->types().size(); ++ i) for (std::size_t i = 0; i < classification_item->types().size(); ++ i)
{ {
CGAL::Classification::Type::Attribute_effect CGAL::Classification::Type::Attribute_effect
eff = classification_item->types()[i].first->attribute_effect(att); eff = classification_item->types()[i].first->attribute_effect(att);
if (eff == CGAL::Classification::Type::PENALIZED_ATT) if (eff == CGAL::Classification::Type::PENALIZING)
class_rows[i].effect->setCurrentIndex(0); class_rows[i].effect->setCurrentIndex(0);
else if (eff == CGAL::Classification::Type::NEUTRAL_ATT) else if (eff == CGAL::Classification::Type::NEUTRAL)
class_rows[i].effect->setCurrentIndex(1); class_rows[i].effect->setCurrentIndex(1);
else else
class_rows[i].effect->setCurrentIndex(2); class_rows[i].effect->setCurrentIndex(2);
@ -824,11 +824,11 @@ public Q_SLOTS:
if (att == Scene_point_set_classification_item::Attribute_handle()) if (att == Scene_point_set_classification_item::Attribute_handle())
return; return;
att->weight = std::tan ((CGAL_PI/2.) * v / 1001.); att->weight() = std::tan ((CGAL_PI/2.) * v / 1001.);
// std::cerr << att->weight << std::endl; // std::cerr << att->weight << std::endl;
for (std::size_t i = 0; i < class_rows.size(); ++ i) for (std::size_t i = 0; i < class_rows.size(); ++ i)
class_rows[i].effect->setEnabled(att->weight != 0.); class_rows[i].effect->setEnabled(att->weight() != 0.);
} }
void on_effect_changed (int v) void on_effect_changed (int v)
@ -854,19 +854,19 @@ public Q_SLOTS:
if (v == 0) if (v == 0)
{ {
classification_item->types()[i].first->set_attribute_effect classification_item->types()[i].first->set_attribute_effect
(att, CGAL::Classification::Type::PENALIZED_ATT); (att, CGAL::Classification::Type::PENALIZING);
// std::cerr << " penalized for "; // std::cerr << " penalized for ";
} }
else if (v == 1) else if (v == 1)
{ {
classification_item->types()[i].first->set_attribute_effect classification_item->types()[i].first->set_attribute_effect
(att, CGAL::Classification::Type::NEUTRAL_ATT); (att, CGAL::Classification::Type::NEUTRAL);
// std::cerr << " neutral for "; // std::cerr << " neutral for ";
} }
else else
{ {
classification_item->types()[i].first->set_attribute_effect classification_item->types()[i].first->set_attribute_effect
(att, CGAL::Classification::Type::FAVORED_ATT); (att, CGAL::Classification::Type::FAVORING);
// std::cerr << " favored for "; // std::cerr << " favored for ";
} }
// std::cerr << classification_item->types()[i].first->id() << std::endl; // std::cerr << classification_item->types()[i].first->id() << std::endl;

View File

@ -210,9 +210,9 @@ void Scene_point_set_classification_item::compute_normals_and_vertices() const
for (Point_set::const_iterator it = m_points->point_set()->begin(); for (Point_set::const_iterator it = m_points->point_set()->begin();
it != m_points->point_set()->first_selected(); ++ it) it != m_points->point_set()->first_selected(); ++ it)
{ {
colors_points.push_back ((double)(m_points->point_set()->red(*it)) / 255.); colors_points.push_back (m_points->point_set()->red(*it));
colors_points.push_back ((double)(m_points->point_set()->green(*it)) / 255.); colors_points.push_back (m_points->point_set()->green(*it));
colors_points.push_back ((double)(m_points->point_set()->blue(*it)) / 255.); colors_points.push_back (m_points->point_set()->blue(*it));
} }
} }
else if (index_color == 1) // classif else if (index_color == 1) // classif
@ -262,8 +262,8 @@ void Scene_point_set_classification_item::compute_normals_and_vertices() const
else else
{ {
Attribute_handle att = m_psc->get_attribute(index_color - 3); Attribute_handle att = m_psc->get_attribute(index_color - 3);
double weight = att->weight; double weight = att->weight();
att->weight = att->max; att->weight() = att->max;
for (Point_set::const_iterator it = m_points->point_set()->begin(); for (Point_set::const_iterator it = m_points->point_set()->begin();
it != m_points->point_set()->first_selected(); ++ it) it != m_points->point_set()->first_selected(); ++ it)
{ {
@ -271,7 +271,7 @@ void Scene_point_set_classification_item::compute_normals_and_vertices() const
colors_points.push_back (ramp.g(att->normalized(*it))); colors_points.push_back (ramp.g(att->normalized(*it)));
colors_points.push_back (ramp.b(att->normalized(*it))); colors_points.push_back (ramp.b(att->normalized(*it)));
} }
att->weight = weight; att->weight() = weight;
} }
for (Point_set::const_iterator it = m_points->point_set()->first_selected(); for (Point_set::const_iterator it = m_points->point_set()->first_selected();
@ -519,7 +519,7 @@ void Scene_point_set_classification_item::train()
return; return;
} }
m_psc->training(m_nb_trials); m_psc->train(m_nb_trials);
m_psc->run(); m_psc->run();
m_helper->info(); m_helper->info();

View File

@ -49,9 +49,9 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
friend value_type get (const Point_set_color_map& pm, const key_type& i) friend value_type get (const Point_set_color_map& pm, const key_type& i)
{ {
Color out = {{ pm.ps->red(i), Color out = {{ (unsigned char)(255 * pm.ps->red(i)),
pm.ps->green(i), (unsigned char)(255 * pm.ps->green(i)),
pm.ps->blue(i) }}; (unsigned char)(255 * pm.ps->blue(i)) }};
return out; return out;
} }
@ -257,7 +257,8 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
return; return;
} }
m_helper->save (filename, *m_psc); std::ofstream f (filename);
m_helper->save (f, *m_psc);
} }
void load_config(const char* filename) void load_config(const char* filename)
@ -275,13 +276,14 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
bool echo; bool echo;
boost::tie (echo_map, echo) = m_points->point_set()->template property_map<boost::uint8_t>("echo"); boost::tie (echo_map, echo) = m_points->point_set()->template property_map<boost::uint8_t>("echo");
std::ifstream f (filename);
if (!normals && !colors && !echo) if (!normals && !colors && !echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map()); m_points->point_set()->point_map());
else if (!normals && !colors && echo) else if (!normals && !colors && echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
@ -289,14 +291,14 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
CGAL::Empty_property_map<Iterator, Color>(), CGAL::Empty_property_map<Iterator, Color>(),
echo_map); echo_map);
else if (!normals && colors && !echo) else if (!normals && colors && !echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
CGAL::Empty_property_map<Iterator, Vector_3>(), CGAL::Empty_property_map<Iterator, Vector_3>(),
Color_map(m_points->point_set())); Color_map(m_points->point_set()));
else if (!normals && colors && echo) else if (!normals && colors && echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
@ -304,13 +306,13 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
Color_map(m_points->point_set()), Color_map(m_points->point_set()),
echo_map); echo_map);
else if (normals && !colors && !echo) else if (normals && !colors && !echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
m_points->point_set()->normal_map()); m_points->point_set()->normal_map());
else if (normals && !colors && echo) else if (normals && !colors && echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
@ -318,14 +320,14 @@ class SCENE_POINT_SET_CLASSIFICATION_ITEM_EXPORT Scene_point_set_classification_
CGAL::Empty_property_map<Iterator, Color>(), CGAL::Empty_property_map<Iterator, Color>(),
echo_map); echo_map);
else if (normals && colors && !echo) else if (normals && colors && !echo)
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),
m_points->point_set()->normal_map(), m_points->point_set()->normal_map(),
CGAL::Empty_property_map<Iterator, Color>()); CGAL::Empty_property_map<Iterator, Color>());
else else
m_helper = new Helper (filename, *m_psc, m_helper = new Helper (f, *m_psc,
m_points->point_set()->begin(), m_points->point_set()->begin(),
m_points->point_set()->end(), m_points->point_set()->end(),
m_points->point_set()->point_map(), m_points->point_set()->point_map(),

View File

@ -348,21 +348,26 @@ make_property_map(const std::vector<T>& v)
return make_property_map(&v[0]); return make_property_map(&v[0]);
} }
/// Empty property map that only returns the default value type /// \ingroup PkgProperty_map
/// /// Property map that only returns the default value type
/// \cgalModels `ReadablePropertyMap` /// \cgalModels `ReadablePropertyMap`
///
/// \endcond
template<class InputIterator, class ValueType> template<class InputIterator, class ValueType>
struct Empty_property_map{ struct Default_property_map{
const ValueType default_value;
typedef typename InputIterator::value_type key_type; typedef typename InputIterator::value_type key_type;
typedef boost::readable_property_map_tag category; typedef boost::readable_property_map_tag category;
Default_property_map(const Value_Type& default_value) : default_value (default_value) { }
/// Free function to use a get the value from an iterator using Input_iterator_property_map. /// Free function to use a get the value from an iterator using Input_iterator_property_map.
inline friend ValueType inline friend ValueType
get (const Empty_property_map&, const key_type&){ return ValueType(); } get (const Empty_property_map&, const key_type&){ return ValueType(); }
}; };
/// \endcond
} // namespace CGAL } // namespace CGAL