27#if defined(LatticeSetByIntervals_RECURSES)
28#error Recursive header files inclusion detected in LatticeSetByIntervals.h
31#define LatticeSetByIntervals_RECURSES
33#if !defined LatticeSetByIntervals_h
35#define LatticeSetByIntervals_h
37#include <unordered_map>
38#include <boost/iterator/iterator_facade.hpp>
40#include "DGtal/base/Common.h"
41#include "DGtal/kernel/CUnsignedNumber.h"
42#include "DGtal/kernel/CBoundedNumber.h"
43#include "DGtal/kernel/CSpace.h"
44#include "DGtal/kernel/PointVector.h"
45#include "DGtal/kernel/IntegralIntervals.h"
60 template <
typename TSpace >
114 template <
typename Po
intIterator>
118 for ( ; it != itE; ++it ) {
135 for (
const auto& aRow : aSet )
136 myData[ aRow.first ].data().push_back( aRow.second );
172 for (
const auto& pV :
myData )
175 auto iVec = pV.second.integerVector();
176 for (
auto x : iVec )
205 for (
const auto& pV :
myData )
206 nb += pV.second.size();
240 auto it =
myData.find( p );
243 it->second.erase( x );
244 if ( it->second.empty() )
253 for (
auto it =
myData.begin(), itE =
myData.end(); it != itE; )
254 if ( it->second.empty() )
276 trace.
error() <<
"[LatticeSetByInterval::add] "
277 <<
"Both lattice sets should share the same axis: "
278 <<
axis() <<
" != " << other.
axis() << std::endl;
281 for (
const auto& pV : other.
myData )
283 const Point& p = pV.first;
284 auto it =
myData.find( p );
286 it->second.add( pV.second );
303 trace.
error() <<
"[LatticeSetByInterval::subtract] "
304 <<
"Both lattice sets should share the same axis: "
305 <<
axis() <<
" != " << other.
axis() << std::endl;
308 for (
const auto& pV : other.
myData )
310 const Point& p = pV.first;
311 auto it =
myData.find( p );
313 it->second.subtract( pV.second );
354 return A_plus_B.
subtract( A_delta_B );
365 Self A_minus_B = *
this;
367 Self B_minus_A = other;
369 return A_minus_B.
add( B_minus_A );
381 trace.
error() <<
"[LatticeSetByInterval::subtract] "
382 <<
"Both lattice sets should share the same axis: "
383 <<
axis() <<
" != " << other.
axis() << std::endl;
386 for (
const auto& pV : other.
myData )
388 const Point& p = pV.first;
389 const auto it =
myData.find( p );
390 if ( it ==
myData.cend() )
return false;
391 if ( ! it->second.includes( pV.second ) )
return false;
402 trace.
error() <<
"[LatticeSetByInterval::subtract] "
403 <<
"Both lattice sets should share the same axis: "
404 <<
axis() <<
" != " << other.
axis() << std::endl;
407 if (
myData.size() != other.
myData.size() )
return false;
408 auto it =
myData.cbegin();
409 for (
const auto& I : other.
myData )
411 if ( it->first != I.first )
return false;
412 if ( ! it->second.equals( I.second ) )
return false;
442 const Point q = 2 * pV.first;
443 C.
myData[ q ] = pV.second.starOfPoints();
448 if ( k ==
myAxis )
continue;
449 for (
const auto& value : C.
myData )
451 Point q = value.first;
452 if ( q[ k ] & 0x1 )
continue;
454 C.
myData[ q ].add( value.second );
456 C.
myData[ q ].add( value.second );
471 for (
auto& pV : C.
myData )
472 pV.second = pV.second.starOfCells();
476 if ( k ==
myAxis )
continue;
477 for (
const auto& value : C.
myData )
479 Point q = value.first;
480 if ( q[ k ] & 0x1 )
continue;
482 C.
myData[ q ].add( value.second );
484 C.
myData[ q ].add( value.second );
499 for (
const auto& pV :
myData )
501 const Point& p = pV.first;
502 const auto& V = pV.second;
505 if ( k ==
myAxis )
continue;
506 if ( ( p[ k ] & 0x1 ) != 0 )
continue;
508 Point q = p; q[ k ] -= 1;
509 Point r = p; r[ k ] += 1;
510 auto itq = S.
myData.find( q );
511 if ( itq != S.
myData.end() )
513 auto& W = itq->second;
516 auto itr = S.
myData.find( r );
517 if ( itr != S.
myData.end() )
519 auto& W = itr->second;
525 for (
auto& value : S.
myData )
527 auto & V = value.second;
529 for (
auto I : V.data() )
531 if ( ( I.first & 0x1 ) != 0 )
533 if ( I.first != I.second )
534 sub_to_V.
data().push_back(
Interval{ I.first, I.first } );
537 if ( ( I.second & 0x1 ) != 0 ) I.second -= 1;
538 for (
auto x = I.first; x <= I.second; x += 2 )
541 V.subtract( sub_to_V );
552 typedef std::vector< Integer > Coordinates;
553 std::map< Point, Coordinates > E;
555 for (
const auto& pV :
myData )
557 const Point& p = pV.first;
558 const auto& V = pV.second;
559 E[ p ] = V.extremaOfCells();
561 std::map< Point, Coordinates > next_E;
564 if ( k ==
myAxis )
continue;
565 for (
const auto& pC : E )
567 const auto& p = pC.first;
569 q[ k ] = q[ k ] >> 1;
570 bool odd = ( p[ k ] & 0x1 ) != 0;
572 auto it = next_E.find( q );
573 if ( it == next_E.end() ) next_E[ q ] = pC.second;
577 std::set_union( pC.second.cbegin(), pC.second.cend(),
578 it->second.cbegin(), it->second.cend(),
579 std::back_inserter( F ) );
586 auto it = next_E.find( q );
587 if ( it == next_E.end() ) next_E[ q ] = pC.second;
591 std::set_union( pC.second.cbegin(), pC.second.cend(),
592 it->second.cbegin(), it->second.cend(),
593 std::back_inserter( F ) );
603 for (
const auto& pC : E )
606 for (
auto&& x : pC.second )
612 std::sort(
R.begin(),
R.end() );
628 for (
const auto& pV : myData )
630 nb +=
sizeof(
Interval ) * pV.second.capacity() +
sizeof(
void* );
631 nb +=
sizeof( pV ) +
sizeof(
void* );
633 nb +=
sizeof(
Self );
656 auto it = myData.find( p );
657 if ( it != myData.end() ) myData.erase( it );
678#undef LatticeSetByIntervals_RECURSES
std::pair< Integer, Integer > Interval
void clear()
Clears the data structure.
size_type memory_usage() const noexcept
LatticeSetByIntervals(const LatticeSetByInterval &aSet, Dimension axis)
typename Space::Vector Vector
typename Space::Integer Integer
typename Container::iterator RowIterator
PointRange toPointRange() const
typename Intervals::Interval Interval
typename Container::const_iterator RowConstIterator
Self starOfPoints() const
Self & operator=(Self &&other)=default
std::map< Point, Intervals > Container
LatticeSetByIntervals(const Self &other)=default
Self set_difference(const Self &other) const
std::vector< Point > PointRange
Self & subtract(const Self &other)
BOOST_CONCEPT_ASSERT((concepts::CSpace< TSpace >))
Self set_union(const Self &other) const
Container myData
Associate to each point its sequences of intervals.
Self set_symmetric_difference(const Self &other) const
Self & operator=(const Self &other)=default
LatticeSetByIntervals(Self &&other)=default
Self & add(const Self &other)
Self skeletonOfCells() const
std::map< Point, Interval > LatticeSetByInterval
bool includes(const Self &other) const
void setAxis(Dimension axis)
PointRange extremaOfCells() const
Self set_intersection(const Self &other) const
typename Space::Point Point
LatticeSetByIntervals(PointIterator it, PointIterator itE, Dimension axis=0)
bool equals(const Self &other) const
static const Dimension dimension
Dimension myAxis
The axis along which data is stacked in intervals.
LatticeSetByIntervals(Dimension axis=0)
void purge()
Eliminates rows that contains no element.
TInteger Integer
Arithmetic ring induced by (+,-,*) and Integer numbers.
PointVector< dim, Integer > Point
Points in DGtal::SpaceND.
static const Dimension dimension
static constants to store the dimension.
PointVector< dim, Integer > Vector
Vectors in DGtal::SpaceND.
std::vector< Point > PointRange
DGtal is the top-level namespace which contains all DGtal functions and types.
DGtal::uint32_t Dimension
Aim: Defines the concept describing a digital space, ie a cartesian product of integer lines.