Skip to content

Commit

Permalink
Merge pull request #1039 from rolanddenis/pr_linearizer
Browse files Browse the repository at this point in the history
Linearizer
  • Loading branch information
dcoeurjo committed Sep 11, 2015
2 parents f504b24 + 77f6b05 commit 50b7fab
Show file tree
Hide file tree
Showing 7 changed files with 771 additions and 113 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@
- *Kernel Package*
- HyperRectDomain can now be empty (lowerBound == upperBound + diagonal(1)). Warning about the use
of lexicographical order in comparison operators of PointVector. (Roland Denis, [#996](https://github.com/DGtal-team/DGtal/pull/996))
- Adds generic linearization (point to index) and reverse process (index to point), specialized for HyperRectDomain.
(Roland Denis, [#1039](https://github.com/DGtal-team/DGtal/pull/1039))

- *Shapes Package*
- Adds a vertex Iterator in the Mesh class in addition to the
Expand Down
111 changes: 2 additions & 109 deletions src/DGtal/images/ImageContainerBySTLVector.ih
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

//////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <DGtal/kernel/domains/Linearizer.h>
//////////////////////////////////////////////////////////////////////////////

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -179,112 +180,6 @@ DGtal::ImageContainerBySTLVector<D, V>::className() const
return "ImageContainerBySTLVector";
}

///////////////////////////////////////////////////////////////////////////////
// Helper classes defined in the compilation unit (anonymous namespace)

namespace
{

/**
* Class template for linearization of the coordinates of a Point.
* This class template is to be specialized for efficiency for dimensions 1,
* 2 and 3 to prevent the use of a loop in these cases.
*
* @tparam Domain an instance of HyperRectDomain
* @tparam dimension domain dimension
*/
template < typename Domain, int dimension>
struct linearizer
{

typedef typename Domain::Point Point;
typedef typename Domain::Size Size;

/**
* Compute the linearized offset of a point in a vector container.
*
* @param aPoint a point
* @param lowerBound lower bound of the image domain.
* @param extent extension of the image domain.
*
* @return the index
*/
static Size apply( const Point & aPoint, const Point & lowerBound,
const Point & extent )
{
Size pos = aPoint[ 0 ] - lowerBound[ 0 ] ;
Size multiplier = 1;
for (typename Domain::Dimension k = 1 ; k < dimension ; ++k)
{
multiplier *= extent[ k-1 ];
pos += multiplier * ( aPoint[ k ] - lowerBound[ k ] );
}
return pos;
}
};

/**
* Specialization of the linearizer class for dimension 1.
*
*/
template < typename Domain >
struct linearizer< Domain, 1 >
{
typedef typename Domain::Point Point;
typedef typename Domain::Size Size;

static Size apply( const Point & aPoint,
const Point & lowerBound,
const Point & /*extent*/ )
{
return aPoint[ 0 ] - lowerBound[ 0 ];
}
};

/**
* Specialization of the linearizer class for dimension 2.
*
*/
template < typename Domain >
struct linearizer< Domain, 2 >
{
typedef typename Domain::Point Point;
typedef typename Domain::Size Size;

static Size apply( const Point & aPoint,
const Point & lowerBound,
const Point & extent )
{
return ( aPoint[ 0 ] - lowerBound[ 0 ] ) + extent[ 0 ] *
(aPoint[ 1 ] - lowerBound[ 1 ] );
}
};

/**
* Specialization of the linearizer class for dimension 3.
*
*/
template < typename Domain >
struct linearizer< Domain, 3 >
{
typedef typename Domain::Point Point;
typedef typename Domain::Size Size;

static Size apply( const Point & aPoint,
const Point & lowerBound,
const Point & extent )
{
Size res = aPoint[ 0 ] - lowerBound[ 0 ];
Size multiplier = extent[ 0 ];
res += multiplier * ( aPoint[ 1 ] - lowerBound[ 1 ] );
multiplier *= extent[ 1 ];
res += multiplier * ( aPoint[ 2 ] - lowerBound[ 2 ] );
return res;
}
};
}



///////////////////////////////////////////////////////////////////////////////
// Internals - private :
Expand All @@ -293,9 +188,7 @@ inline
typename DGtal::ImageContainerBySTLVector<Domain, T>::Size
DGtal::ImageContainerBySTLVector<Domain, T>::linearized(const Point &aPoint) const
{
return linearizer<Domain, Domain::dimension >::apply( aPoint,
myDomain.lowerBound(),
myExtent );
return DGtal::Linearizer<Domain, ColMajorStorage>::getIndex( aPoint, myDomain.lowerBound(), myExtent );
}


Expand Down
8 changes: 4 additions & 4 deletions src/DGtal/kernel/domains/HyperRectDomain_Iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ namespace DGtal
if ( current_pos < TPoint::dimension )
++myPoint[current_pos];
}
while (( current_pos < TPoint::dimension - 1 ) &&
while (( current_pos + 1 < TPoint::dimension ) &&
( myPoint[ current_pos ] > myupper[ current_pos ] ) );
}
}
Expand Down Expand Up @@ -279,7 +279,7 @@ namespace DGtal
if ( current_pos < TPoint::dimension )
--myPoint[ current_pos ];
}
while (( current_pos < TPoint::dimension - 1 ) &&
while (( current_pos + 1 < TPoint::dimension ) &&
( myPoint[ current_pos ] < mylower[ current_pos ] ) );
}
}
Expand Down Expand Up @@ -464,7 +464,7 @@ namespace DGtal
if ( current_pos < mySubDomain.size() )
++myPoint[ mySubDomain[current_pos] ];
}
while (( current_pos < mySubDomain.size() - 1 ) &&
while (( current_pos + 1 < mySubDomain.size() ) &&
( myPoint[ mySubDomain[current_pos] ] >
myupper[ mySubDomain[current_pos] ] ) );
}
Expand Down Expand Up @@ -512,7 +512,7 @@ namespace DGtal
if ( current_pos < mySubDomain.size() )
--myPoint[ mySubDomain[current_pos] ];
}
while (( current_pos < mySubDomain.size() - 1 ) &&
while (( current_pos + 1 < mySubDomain.size() ) &&
( myPoint[ mySubDomain[current_pos] ] <
mylower[ mySubDomain[current_pos] ] ) );
}
Expand Down
191 changes: 191 additions & 0 deletions src/DGtal/kernel/domains/Linearizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
**/

#pragma once

/**
* @file Linearizer.h
* @author Roland Denis (\c [email protected] )
* LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France
*
* @date 2015/06/18
*
* This file is part of the DGtal library.
*/

#if defined(Linearizer_RECURSES)
#error Recursive header files inclusion detected in Linearizer.h
#else // defined(Linearizer_RECURSES)
/** Prevents recursive inclusion of headers. */
#define Linearizer_RECURSES

#if !defined Linearizer_h
/** Prevents repeated inclusion of headers. */
#define Linearizer_h

//////////////////////////////////////////////////////////////////////////////
// Inclusions
#include <DGtal/kernel/domains/HyperRectDomain.h> // Only for specialization purpose.
//////////////////////////////////////////////////////////////////////////////

namespace DGtal
{

/////////////////////////////////////////////////////////////////////////////

/**
* @brief Tag (empty structure) specifying a row-major storage order.
*
* @see Linearizer
*/
struct RowMajorStorage {};

/**
* @brief Tag (empty structure) specifying a col-major storage order.
*
* @see Linearizer
*/
struct ColMajorStorage {};

/////////////////////////////////////////////////////////////////////////////
/**
* @brief Aim: Linearization and de-linearization interface for domains.
*
* Description of class 'Linearizer' <p>
* This class is empty but there is a specialization for HyperRectDomain.
*
* @tparam TDomain Type of the domain.
* @tparam TStorageOrder Storage Order (RowMajorStorage of ColMajorStorage).
*
*/
template <
typename TDomain,
typename TStorageOrder = ColMajorStorage
>
struct Linearizer;

/**
* @brief Aim: Linearization and de-linearization interface for HyperRectDomain.
*
* This is a static class that provides point linearization (point to index) and de-linearization (index to point) for storages working on HyperRectDomain.
*
* The storage order can be specified by template (default is colum-major ordered).
*
* Example:
* @code
* typedef SpaceND<2> Space;
* tydedef HyperRectDomain<Space> Domain;
* typedef typename Space::Point Point;
*
* const Domain domain( Point(0, 1), Point(4, 3) );
*
* typename Linearizer<Domain>::Size id = Linearizer<Domain>::getIndex( Point(2, 2), domain ); // returns 7.
*
* Point pt = Linearizer<Domain>::getPoint( 7, domain); // returns Point(2,2).
* @endcode
*
* @tparam TSpace Type of the space of the HyperRectDomain (auto-deduced from TDomain template, see Linearizer).
* @tparam TStorageOrder Storage Order (RowMajorStorage of ColMajorStorage).
*/
template <
typename TSpace,
typename TStorageOrder
>
struct Linearizer< HyperRectDomain<TSpace>, TStorageOrder >
{
// Usefull typedefs
typedef HyperRectDomain<TSpace> Domain; ///< The domain type.
typedef typename TSpace::Point Point; ///< The point type.
typedef Point Extent; ///< The domain's extent type.
typedef typename TSpace::Size Size; ///< The space's size type.

/** Linearized index of a point, given the domain lower-bound and extent.
*
* @param[in] aPoint The point to be linearized.
* @param[in] aLowerBound The lower-bound of the domain.
* @param[in] anExtent The extent of the domain.
* @return the linearized index of the point.
*/
static inline
Size getIndex( Point aPoint, Point const& aLowerBound, Extent const& anExtent );

/** Linearized index of a point, given the domain extent.
*
* The lower-bound of the domain is defined to the origin.
*
* @param[in] aPoint The Point to be linearized.
* @param[in] anExtent The extent of the domain.
* @return the linearized index of the point.
*/
static inline
Size getIndex( Point aPoint, Extent const& anExtent );

/** Linearized index of a point, given a domain.
*
* @param[in] aPoint The Point to be linearized.
* @param[in] aDomain The domain.
* @return the linearized index of the point.
*/
static inline
Size getIndex( Point aPoint, Domain const& aDomain );

/** De-linearization of an index, given the domain lower-bound and extent.
*
* @param[in] anIndex The linearized index.
* @param[in] aLowerBound The lower-bound of the domain.
* @param[in] anExtent The domain extent.
* @return the point whose linearized index is anIndex.
*/
static inline
Point getPoint( Size anIndex, Point const& aLowerBound, Extent const& anExtent );

/** De-linearization of an index, given the domain extent.
*
* The lower-bound of the domain is set to the origin.
*
* @param[in] anIndex The linearized index.
* @param[in] anExtent The domain extent.
* @return the point whose linearized index is anIndex.
*/
static inline
Point getPoint( Size anIndex, Extent const& anExtent );

/** De-linearization of an index, given a domain.
*
* @param[in] anIndex The linearized index.
* @param[in] aDomain The domain.
* @return the point whose linearized index is anIndex.
*/
static inline
Point getPoint( Size anIndex, Domain const& aDomain );

}; // end of class Linearizer

} // namespace DGtal


///////////////////////////////////////////////////////////////////////////////
// Includes inline functions.
#include "DGtal/kernel/domains/Linearizer.ih"

// //
///////////////////////////////////////////////////////////////////////////////

#endif // !defined Linearizer_h

#undef Linearizer_RECURSES
#endif // else defined(Linearizer_RECURSES)

Loading

0 comments on commit 50b7fab

Please sign in to comment.