Skip to content

Commit

Permalink
ENH: Remove Object from VoxelComplex
Browse files Browse the repository at this point in the history
This drops the runtime by ~4x (orientative)
And the memory usage (not quantified).

Also reduce time of testing. Fix #1347
  • Loading branch information
phcerdan committed Nov 29, 2018
1 parent d124719 commit c0bb843
Show file tree
Hide file tree
Showing 7 changed files with 468 additions and 570 deletions.
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- *Helpers*
- Classes Shortcuts and ShortcutsGeometry to simplify coding with DGtal. Integrate a lot of volume, digital surfaces, mesh, surface, geometry, estimators functions, with many conversion and input/output tools. (Jacques-Olivier Lachaud, [#1357](https://github.com/DGtal-team/DGtal/pull/1357))

- *Topology Package*
- Remove the internal object from VoxelComplex, improving performance
(Pablo Hernandez, [#1369](https://github.com/DGtal-team/DGtal/pull/1369))

## Bug Fixes
- *Configuration/General*
Expand Down
168 changes: 85 additions & 83 deletions src/DGtal/topology/VoxelComplex.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@
namespace DGtal {

// Forward definitions.
template <typename TKSpace, typename TObject, typename TCellContainer>
template <typename TKSpace, typename TCellContainer>
class VoxelComplex;
namespace functions {
template <typename TKSpace, typename TObject, typename TCellContainer>
VoxelComplex<TKSpace, TObject, TCellContainer> &
operator-=(VoxelComplex<TKSpace, TObject, TCellContainer> &,
const VoxelComplex<TKSpace, TObject, TCellContainer> &);
template <typename TKSpace, typename TObject, typename TCellContainer>
VoxelComplex<TKSpace, TObject, TCellContainer>
operator-(const VoxelComplex<TKSpace, TObject, TCellContainer> &,
const VoxelComplex<TKSpace, TObject, TCellContainer> &);
template <typename TKSpace, typename TCellContainer>
VoxelComplex<TKSpace, TCellContainer> &
operator-=(VoxelComplex<TKSpace, TCellContainer> &,
const VoxelComplex<TKSpace, TCellContainer> &);
template <typename TKSpace, typename TCellContainer>
VoxelComplex<TKSpace, TCellContainer>
operator-(const VoxelComplex<TKSpace, TCellContainer> &,
const VoxelComplex<TKSpace, TCellContainer> &);

} // namespace functions
/////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -87,16 +87,12 @@ operator-(const VoxelComplex<TKSpace, TObject, TCellContainer> &,
*
*/

template <typename TKSpace, typename TObject,
template <typename TKSpace,
typename TCellContainer = typename TKSpace::template CellMap< CubicalCellData >::Type >
class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
public:
// The TObject::DigitalSet::Container must be associative.
BOOST_CONCEPT_ASSERT((concepts::CSTLAssociativeContainer<
typename TObject::DigitalSet::Container>));

/** Type of this instance of VoxelComplex. */
using Self = VoxelComplex<TKSpace, TObject, TCellContainer>;
using Self = VoxelComplex<TKSpace, TCellContainer>;

friend Self &DGtal::functions::operator-=<>(Self &, const Self &);
friend Self DGtal::functions::operator-<>(const Self &, const Self &);
Expand All @@ -109,10 +105,6 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
using CellContainer = TCellContainer;
/** Type of data associated to each cell. */
using Data = typename CellContainer::mapped_type;
/** Type for input Object storing the digital set of spels with a topology*/
using Object = TObject;
/** Type of the associated DigitalTopology of Object. */
using DigitalTopology = typename TObject::DigitalTopology;

/// The dimension of the embedding space.
static const Dimension dimension = KSpace::dimension;
Expand Down Expand Up @@ -172,12 +164,13 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
Self &operator=(const Self &other);

/**
* Construct the VoxelComplex with target \a obj
* Construct the VoxelComplex with target \a input_set
*
* @param obj input object to copy to the complex.
* @param input_set input set to construct the complex.
*
*/
void construct(const TObject &obj);
template < typename TDigitalSet >
void construct(const TDigitalSet &input_set);

/**
* Construct from digital set and precomputed look up table for simplicity.
Expand All @@ -193,7 +186,8 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*
* @see LookUpTableFunctions.h
*/
void construct(const typename Object::DigitalSet &input_set,
template < typename TDigitalSet >
void construct(const TDigitalSet &input_set,
const Alias<ConfigMap> input_table);

/**
Expand All @@ -205,6 +199,14 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*/
void setSimplicityTable(const Alias<ConfigMap> input_table);

/**
* Copy table variables from other Complex.
*
* @param complex to copy table from
*
*/
void copySimplicityTable(const Self & other);

/**
* Get const reference to table[conf]->bool for simplicity.
*
Expand Down Expand Up @@ -240,7 +242,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
* Insert cell (voxel) in the khalimsky space AND in the object set.
*
* @param kcell input voxel
* @param close_it if true, apply @ref voxelClose.
* @param close_it if true, apply @voxelClose.
* @param data associated data with the input cell. @see insertCell
*/
void insertVoxelCell(const Cell &kcell, const bool &close_it = true,
Expand All @@ -250,24 +252,36 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
* Insert cell(voxel) in K-space and in the object set.
*
* @param data_pair pair<Cell, Data>
* @param close_it if true, apply @ref voxelClose
* @param close_it if true, apply @voxelClose
*/
void insertVoxelCell(const std::pair<Cell, Data> &data_pair,
const bool &close_it = true) {
insertVoxelCell(data_pair.first, close_it, data_pair.second);
}

/**
* Create a uSpel from the input Point and insert it using insertVoxelCell.
* Create a @uSpel from the input Point and insert it using insertVoxelCell.
* @see insertVoxelCell
*
* @param dig_point input point of the KSpace
* @param close_it flag to apply @ref voxelClose
* @param close_it flag to apply @voxelClose
* @param data associated data with the input point.
*/
void insertVoxelPoint(const Point &dig_point, const bool &close_it = true,
const Data &data = Data());

/**
* Dump the voxels (kcell with dimension 3) into a input container.
*
* @tparam TDigitalSet the type of the container
* @param in_out_set input and output digital set, voxels gets inserted.
* Note that the input digital set is not cleared in this function before inserting.
*
* @return all the voxels in a container of the chosen type.
*/
template<typename TDigitalSet>
void dumpVoxels(TDigitalSet & in_out_set);

/**
* Clears the voxel complex, which becomes empty.
* This includes the khalmisky cells and also the object points.
Expand All @@ -282,7 +296,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*
* @return A point in myObject
*/
const typename Object::Point &objPointFromVoxel(const Cell &voxel) const;
/* const typename Object::Point &objPointFromVoxel(const Cell &voxel) const; */
//------ Spels ------//
/**
* Get pointels that are Faces of input_cell.
Expand All @@ -308,6 +322,27 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*/
void spelsFromCell(std::set<Cell> &spels_out, const Cell &input_cell) const;

/**
* Return the neighbor spels of input_cell
*
* @param input_cell center of the neighborhood
*
* @return neighborhood of input_cell
*/
std::set<Cell> neighborhoodVoxels(const Cell &input_cell) const;

/**
* Return a set of of voxels forming the properNeighborhood of the inputCell.
*
* @param input_cell center of the neighborhood
*
* @sa neighborhoodVoxels
* @sa Kneighborhood
*
* @return properNeighborhood
*/
std::set<Cell> properNeighborhoodVoxels(const Cell &input_cell) const;

/**
* Get a clique holding the K-neighborhood of the input cell.
* The K-neighborhood is calculated first, getting the pointels
Expand All @@ -321,13 +356,18 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
Clique Kneighborhood(const Cell &input_cell) const;

/**
* Populate this complex object from the spels belonging to
* the Khalimsky space.
* Use thinning to check if cell is simple.
* First create a CubicalComplex from the neighbor voxels on input_cell.
* This does not include input_cell itself, close the new clique and apply
* a collapse operation.
* A input_spel is simple in the complex, if after the collapse on the proper
* neighborhood clique, there is only one pointel.
*
* @return const reference to object().
* @param input_spel
*
* @return true if input_spell can be removed without altering the topology.
*/
const Object &populateObjectFromCells();

bool isSimpleByThinning(const Cell &input_spel) const;
/**
* Check if the input_spel from khalimsky space is simple using
* object properties.
Expand All @@ -343,41 +383,13 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*/
bool isSimple(const Cell &input_spel) const;

/**
* @return true if object is connected, false if disconnected.
*
* @note connectedness::unkwown is not possible.
*
* @see Object::computeConnectedness.
*/
bool isConnected() const;

/**
* @return Object representing the spels.
*/
Object &object();
/**
* @return Object representing the spels, read only.
*/
const Object &object() const;

/**
* @return digitalSet of Object representing the spels.
*/
typename Object::DigitalSet &objectSet();

/**
* @return digitalSet of Object representing the spels, read only.
*/
const typename Object::DigitalSet &objectSet() const;

//------ Cliques ------//
// Cliques, union of adjacent spels.
// The intersection of all spels of the clique define the type.
// 0-clique, 1-clique, 2-clique. 3-clique are isolated spels.
public:
/**
* Function to call @ref K_0, @ref K_1, @ref K_2, @ref K_3 according to dimension d
* Function to call @K_0, @K_1, @K_2, @K_3 according to dimension d
*
* @param d dimension.
* @param cellMapIterator cell iterator of cubical or voxel complex.
Expand All @@ -390,7 +402,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {

/**
* Return all critical cliques for \b cubical.
* It calls criticalCliquesForD()
* It calls @criticalCliquePairForD
*
* @param cubical target complex to get critical cliques.
* @param verbose print messages
Expand All @@ -415,7 +427,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
return criticals;
}
/**
* Helper. Call @ref criticalCliques() of this VoxelComplex.
* Helper. Call @criticalCliques of this VoxelComplex.
*
* @param verbose print messages
*
Expand All @@ -428,7 +440,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {

/**
* Main method to iterate over cells of selected dimension in a complex,
* returning critical cliques. Uses @ref criticalCliquePair().
* returning critical cliques. Uses @criticalCliquePair.
*
* @param d dimension of cell.
* @param cubical target complex to get critical cliques.
Expand Down Expand Up @@ -466,8 +478,8 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
*
* @return <is_critical, 2-clique>
*/
std::pair<bool, Clique> K_2(const typename Object::Point &A,
const typename Object::Point &B,
std::pair<bool, Clique> K_2(const typename KSpace::Point &A,
const typename KSpace::Point &B,
bool verbose = false) const;

/**
Expand Down Expand Up @@ -535,9 +547,7 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {

/*------------- Data --------------*/
protected:
/** Object with a topology representing spels. */
Object myObject;
/** Look Up Table to speed computations of @ref isSimple. */
/** Look Up Table to speed computations of @isSimple. */
CountedPtrOrPtr<ConfigMap> myTablePtr;
/** ConfigurationMask (LUT table). */
CountedPtrOrPtr<PointToMaskMap> myPointToMaskPtr;
Expand All @@ -546,22 +556,14 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
/*------------- Internal Methods --------------*/
/**
* pointToMask map, used internally in @ref VoxelComplex::isSimple for
* @ref functions::getSpelNeighborhoodConfigurationOccupancy
* @ref LookUpTableFunctions.h::getSpelNeighborhoodConfigurationOccupancy
*
* @return reference to @ref PointToMaskMap member.
* @return reference to pointToMaskMap member.
*
* @see pointToBitMaskMap()
* @see LookUpTableFunctions.h::pointToBitMaskMap()
*/
const PointToMaskMap &pointToMask() const;

/**
* Populate myObject member with an empty set with valid domain and
* topology. Used in @ref VoxelComplex::construct with digital sets.
*
* @param dig_set input digital set.
*/
void instantiateEmptyObject(const typename Object::DigitalSet &dig_set);

// ----------------------- Interface --------------------------------------
public:
/**
Expand Down Expand Up @@ -591,10 +593,10 @@ class VoxelComplex : public CubicalComplex<TKSpace, TCellContainer> {
* @param object the object of class 'VoxelComplex' to write.
* @return the output stream after the writing.
*/
template <typename TKSpace, typename TObject, typename TCellContainer>
template <typename TKSpace, typename TCellContainer>
std::ostream &
operator<<(std::ostream &out,
const VoxelComplex<TKSpace, TObject, TCellContainer> &object);
const VoxelComplex<TKSpace, TCellContainer> &object);

} // namespace DGtal

Expand Down
Loading

0 comments on commit c0bb843

Please sign in to comment.