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 Dec 30, 2018
1 parent 60e0e2b commit b2c35c1
Show file tree
Hide file tree
Showing 9 changed files with 502 additions and 613 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
- *Configuration/General*
- Simplifying Travis CI scripts (David Coeurjolly, [#1371](https://github.com/DGtal-team/DGtal/pull/1371))

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

## Bug Fixes
- *Configuration/General*
- Continuous integration AppVeyor fix
Expand Down
11 changes: 4 additions & 7 deletions examples/topology/generateVoxelComplexTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,17 @@ int main( int argc, char** argv )
typedef std::bitset<67108864> ConfigMap; // 2^26

using namespace Z3i;
using DigitalSet = DigitalSetByAssociativeContainer<
Domain, std::unordered_set< typename Domain::Point> >;
using Object = Object<DT26_6, DigitalSet>;
using VoxelComplex = VoxelComplex<KSpace, Object>;
using VoxelComplex = VoxelComplex<KSpace>;

std::function< bool(
const VoxelComplex & ,
const typename VoxelComplex::Cell & )
> skelFunction;
string error_message(
"Provide one of the following arguments for select function:\n"
"- skelIsthmus \n "
"- oneIsthmus \n "
"- twoIsthmus \n ");
"- skelIsthmus \n"
"- oneIsthmus \n"
"- twoIsthmus \n");
if (argc != 2 ){
cout << error_message << std::endl;
return 1;
Expand Down
173 changes: 82 additions & 91 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 other 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,39 +252,40 @@ 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 in the set.
* Note that the input digital set is not cleared in this function before inserting.
*/
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.
*/
void clear();

/**
* Get reference to a point in the DigitalSet of myObject
* corresponding to input voxel
*
* @param voxel input voxel
*
* @return A point in myObject
*/
const typename Object::Point &objPointFromVoxel(const Cell &voxel) const;
//------ Spels ------//
/**
* Get pointels that are Faces of input_cell.
Expand All @@ -308,6 +311,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 +345,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.
*
* @param input_spel input spel for checking its simplicity.
*
* @return const reference to object().
* @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 +372,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 +391,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 +416,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 +429,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 +467,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 +536,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 +545,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 +582,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 b2c35c1

Please sign in to comment.