Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3b3501e
WIP ParallelIIEstimator
BDoignies Mar 2, 2026
0b9242b
Forgot .h file
BDoignies Mar 2, 2026
04e562a
Ordered evaluation for ParallelIIEstimator
BDoignies Mar 11, 2026
beebcf8
Few more comments
BDoignies Mar 11, 2026
3e9680d
Merge branch 'main' into parallelII
dcoeurjo Mar 12, 2026
1121654
Merge branch 'main' into parallelII
dcoeurjo Mar 12, 2026
933395b
Merge branch 'main' into parallelII
dcoeurjo Mar 13, 2026
f5e2d01
Pre commit fixes
BDoignies Apr 1, 2026
7021794
cmake edit to make sure that DGTAL_WITH_OPENMP has been set
dcoeurjo Apr 3, 2026
07c6535
WIP testing the splitter
dcoeurjo Apr 3, 2026
efee3cb
Adding Axis splitter and concept check
dcoeurjo Apr 9, 2026
57b6f43
Merge branch 'main' into parallelII
dcoeurjo Apr 9, 2026
4fee775
Removing traces.
dcoeurjo Apr 9, 2026
b1650b1
t push
dcoeurjo Apr 9, 2026
2c5da9b
Moved DomainSplitter to kernel package
BDoignies Apr 29, 2026
f84ad03
Updated test for parallel integral invariant and added a bit of doc.
BDoignies Apr 29, 2026
9914bb9
Add include to StdDefs
BDoignies May 18, 2026
ef5af3e
Removing unused parameter
dcoeurjo Jun 7, 2026
55ae444
Removing unsused variable
dcoeurjo Jun 7, 2026
96bf95a
Merge branch 'main' into parallelII
dcoeurjo Jun 7, 2026
648bc3a
Adding header
dcoeurjo Jun 7, 2026
7251dea
Adding header
dcoeurjo Jun 7, 2026
7df9956
Adding header
dcoeurjo Jun 7, 2026
5864887
Fixing doxygen issues
dcoeurjo Jun 7, 2026
3aff584
Merge branch 'main' into parallelII
dcoeurjo Jun 7, 2026
1f34d5b
Documentation edits
dcoeurjo Jun 7, 2026
9db68c4
edits
dcoeurjo Jun 8, 2026
325d0e1
Adding parallel II example and updating the documentation
dcoeurjo Jun 8, 2026
010262f
Adding parallel II example and updating the documentation
dcoeurjo Jun 8, 2026
6b4fa0c
Changelog
dcoeurjo Jun 8, 2026
b367f15
Changelog
dcoeurjo Jun 8, 2026
a2ce45e
Adding multithreading for NormalVectors
dcoeurjo Jun 8, 2026
9db67f3
Enabling axis selection in ParallelII/AxisSplitter
dcoeurjo Jun 12, 2026
4bd6965
Adding illustration
dcoeurjo Jun 12, 2026
0e2c3c3
Enabling openmp parameter in python
dcoeurjo Jun 13, 2026
d0213bb
JPG image
dcoeurjo Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
- *Build*
- Fixing old `DEBUG_VERBOSE` to `DGTAL_DEBUG_VERBOSE` (David Coeurjolly, [#1834](https://github.com/DGtal-team/DGtal/pull/1834))

- *Geometry*
- In DigitalSurfaceConvolver (eg. when using the Integral Invariant estimators), an bug existed when the shapoe domain does not contain the point (0,0,0). This PR fixes it using KCoords to represent the Kernel origin instead of a Spel which requires a valid KSpace (David Coeurjolly, [#1840](https://github.com/DGtal-team/DGtal/pull/1840))

# DGtal 2.1.0

## New features
Expand Down
2 changes: 2 additions & 0 deletions cmake/CheckDGtalOptionalDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ endif()
set(OPENMP_FOUND_DGTAL 0)
if(DGTAL_WITH_OPENMP)
include(openmp)
target_link_libraries(DGtal PUBLIC OpenMP::OpenMP_CXX)

set(DGtalLibDependencies ${DGtalLibDependencies} OpenMP::OpenMP_CXX)
set(OPENMP_FOUND_DGTAL 1)
set(DGTAL_WITH_OPENMP 1)
Expand Down
6 changes: 3 additions & 3 deletions src/DGtal/geometry/surfaces/DigitalSurfaceConvolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ class DigitalSurfaceConvolver
const DigitalKernel * myKernel; ///< Two choice to iterate over the full kernel. See init() for more information.
const PairIterators * myKernelMask; ///< Two choice to iterate over the full kernel. See init() for more information.

Spel myKernelSpelOrigin; ///< Copy of the origin cell of the kernel.
KSpace::Point myKernelKCoordsOrigin; ///< Copy of the origin cell of the kernel.

// ------------------------- Hidden services ------------------------------

Expand Down Expand Up @@ -775,7 +775,7 @@ class DigitalSurfaceConvolver< TFunctor, TKernelFunctor, TKSpace, TDigitalKernel
const DigitalKernel * myKernel; ///< Two choice to iterate over the full kernel. See init() for more information.
const PairIterators * myKernelMask; ///< Two choice to iterate over the full kernel. See init() for more information.

Spel myKernelSpelOrigin; ///< Copy of the origin cell of the kernel.
KSpace::Point myKernelKCoordsOrigin; ///< Copy of the origin cell of the kernel.

// ------------------------- Hidden services ------------------------------

Expand Down Expand Up @@ -1145,7 +1145,7 @@ class DigitalSurfaceConvolver< TFunctor, TKernelFunctor, TKSpace, TDigitalKernel
const DigitalKernel * myKernel; ///< Two choice to iterate over the full kernel. See init() for more information.
const PairIterators * myKernelMask; ///< Two choice to iterate over the full kernel. See init() for more information.

Spel myKernelSpelOrigin; ///< Copy of the origin cell of the kernel.
KSpace::Point myKernelKCoordsOrigin; ///< Copy of the origin cell of the kernel.

// ------------------------- Hidden services ------------------------------

Expand Down
41 changes: 23 additions & 18 deletions src/DGtal/geometry/surfaces/DigitalSurfaceConvolver.ih
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, d
myMasks( other.myMasks ),
myKernel( other.myKernel ),
myKernelMask( other.myKernelMask ),
myKernelSpelOrigin( other.myKernelSpelOrigin )
myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
{
}

Expand All @@ -89,7 +89,8 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, d
ConstAlias< PairIterators > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernelMask = &fullKernel;
myMasks = &masks;

Expand All @@ -107,7 +108,8 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, d
ConstAlias< DigitalKernel > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernel = &fullKernel;
myMasks = &masks;

Expand Down Expand Up @@ -589,7 +591,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
myMasks( other.myMasks ),
myKernel( other.myKernel ),
myKernelMask( other.myKernelMask ),
myKernelSpelOrigin( other.myKernelSpelOrigin )
myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
{
}

Expand All @@ -601,7 +603,8 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
ConstAlias< PairIterators > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<2,typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernelMask = &fullKernel;
myMasks = &masks;

Expand All @@ -619,7 +622,8 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
ConstAlias< DigitalKernel > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<2,typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernel = &fullKernel;
myMasks = &masks;

Expand Down Expand Up @@ -1048,7 +1052,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;

/// Check if we can use previous results
if( useLastResults )
Expand Down Expand Up @@ -1213,7 +1217,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;

ASSERT( currentInnerSpel != currentOuterSpel );

Expand Down Expand Up @@ -1338,7 +1342,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;

/// Check if we can use previous results
if( useLastResults )
Expand Down Expand Up @@ -1502,7 +1506,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;

ASSERT( currentInnerSpel != currentOuterSpel );

Expand Down Expand Up @@ -1620,7 +1624,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
myMasks( other.myMasks ),
myKernel( other.myKernel ),
myKernelMask( other.myKernelMask ),
myKernelSpelOrigin( other.myKernelSpelOrigin )
myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
{
}

Expand All @@ -1632,7 +1636,8 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
ConstAlias< PairIterators > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<3,typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernelMask = &fullKernel;
myMasks = &masks;

Expand All @@ -1650,10 +1655,10 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
ConstAlias< DigitalKernel > fullKernel,
ConstAlias< std::vector< PairIterators > > masks )
{
myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
KhalimskySpaceND<3,typename KSpace::Integer> preK;
myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
myKernel = &fullKernel;
myMasks = &masks;

ASSERT ( myMasks->size () == 27 );

isInitFullMasks = false;
Expand Down Expand Up @@ -2099,7 +2104,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;

/// Check if we can use previous results
if( useLastResults )
Expand Down Expand Up @@ -2269,7 +2274,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;

ASSERT( currentInnerSpel != currentOuterSpel );

Expand Down Expand Up @@ -2399,7 +2404,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;

/// Check if we can use previous results
if( useLastResults )
Expand Down Expand Up @@ -2569,7 +2574,7 @@ DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3
{
DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;

ASSERT( currentInnerSpel != currentOuterSpel );

Expand Down
74 changes: 74 additions & 0 deletions src/DGtal/geometry/surfaces/estimation/DomainSplitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include <vector>

namespace DGtal
{
/**
* @brief Data structure returned by Domain splitters
*
* This class offers the ability for the splitter to give information
* about the surfaces or object within the splits.
* For example, the hintVoxelCount field may allow to pre-allocate buffers.
*/
template<typename Domain>
struct SplitInfo
{

Domain domain; //< The actual split domain
uint32_t hintVoxelCount = 0; //< An expected guess for the number of voxel
};

// TODO: CDomainSplitter concept ?
/**
* @brief Splits a domain evenly along all dimensions
*
* @tparam The model of domain to split
*/
template<typename Domain>
struct EvenDomainSplitter
{
/**
* @brief Splits a domain
*
* This functions may split the domain in fewer part than wanted to ensure
* even subdomains.
*
* @param d The domain to split
* @param splitHint The wanted number of splits
*/
std::vector<SplitInfo<Domain>> operator()(const Domain& d, uint32_t splitHint) const {
// Find best match possible for even splitting
const uint32_t splitCount = std::floor(std::log(splitHint) / std::log(Domain::dimension));
const uint32_t totalSplits = std::pow(splitCount, Domain::dimension);

if (splitCount == 0)
return { SplitInfo{d, 0} };

auto splitSize = (d.upperBound() - d.lowerBound()) / (int32_t)splitCount;
std::vector<SplitInfo<Domain>> result;
result.reserve(totalSplits);

for (uint32_t i = 0; i < totalSplits; ++i)
{
auto start = d.lowerBound();
auto idx = i;
for (uint32_t j = 0; j < Domain::dimension; ++j)
{
auto k = idx % splitCount;
start[j] += k * splitSize[j] + k; // +k ensure no overlap between domains
idx /= splitCount;
}

// Make correction to ensure it remains within the domain
auto end = start + splitSize;
for (uint32_t j = 0; j < Domain::dimension; ++j)
end[j] = std::clamp(end[j], d.lowerBound()[j], d.upperBound()[j]);

result.emplace_back(Domain(start, end), 0);
}

return result;
};
};
}
Loading
Loading