9 #ifndef LARCOREALG_GEOMETRY_PARTITIONS_H 10 #define LARCOREALG_GEOMETRY_PARTITIONS_H 24 #include <type_traits> 51 template <
typename Stream>
54 std::forward<Stream>(out) <<
area();
65 template <AreaOwner::AreaRangeMember_t Range>
90 template <
typename Data>
93 template <
typename Stream>
97 std::string firstIndent =
"");
118 template <
typename Stream,
typename Data>
122 std::string firstIndent =
"");
144 std::string describeArea(std::string
indent, std::string firstIndent)
const;
172 template <
typename Data>
201 virtual Data_t* atPoint(
double w,
double d)
const = 0;
206 return doDescribe(indent, firstIndent);
227 template <
typename Pred>
234 std::size_t
nParts()
const {
return parts().size(); }
249 template <
typename Pred>
250 static void walk(
Partition_t const* start, Pred&& pred);
258 template <
typename Data>
276 return Base_t::contains(w, d) ? myData :
nullptr;
283 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
289 template <
typename Data>
295 using Base_t::Base_t;
300 template <
typename Data>
312 virtual Data_t* atPoint(
double w,
double d)
const override;
318 std::size_t
size()
const {
return parts().size(); }
338 Data_t* defData =
nullptr)
339 :
Base_t(area, defData), myParts(
std::move(subpartitions))
343 virtual Partition_t const* findPart(
double w,
double d)
const = 0;
346 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
349 virtual std::string describeIntro()
const;
368 template <
typename Data,
typename Sorter>
398 Data_t* defData =
nullptr,
400 :
Base_t(area, std::move(subpartitions), defData), sorter(sorter)
409 Partition_t const* findPartWithKey(
double key)
const;
418 template <
typename Data, PartitionBase::AreaRangeMember_t Range>
420 :
public SortedPartition<Data, details::PartitionSorterByAreaRangeLower<Range>> {
423 using Base_t::Base_t;
428 template <
typename Data>
433 using Base_t::Base_t;
438 return Base_t::findPartWithKey(d);
442 virtual std::string describeIntro()
const override;
448 template <
typename Data>
454 using Base_t::Base_t;
459 return Base_t::findPartWithKey(w);
463 virtual std::string describeIntro()
const override;
469 template <
typename Data>
496 unsigned int nDepthPartitions,
497 unsigned int nWidthPartitions,
498 Data_t* defData =
nullptr);
503 unsigned int nDepthPartitions,
504 Data_t* defData =
nullptr);
515 auto part(std::size_t iDepth, std::size_t iWidth) -> decltype(
auto)
517 return Base_t::parts()[iDepth * nWidthParts() + iWidth];
519 auto part(std::size_t iDepth, std::size_t iWidth)
const -> decltype(
auto)
521 return Base_t::parts()[iDepth * nWidthParts() + iWidth];
525 virtual Partition_t const* findPart(
double w,
double d)
const override;
528 std::vector<double> computeWidthSeps(
unsigned int nD,
unsigned int nW)
const;
530 std::vector<double> computeDepthSeps(
unsigned int nD,
unsigned int nW)
const;
533 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
535 template <PartitionBase::AreaRangeMember_t Range,
typename BeginIter,
typename EndIter>
536 static std::vector<double> detectSeparators(BeginIter b,
538 std::size_t
const nGroups,
539 std::size_t
const startDelta,
540 std::size_t
const stride);
552 std::string firstIndent)
const 554 std::ostringstream sstr;
555 sstr << firstIndent <<
"partition covers ";
570 template <
typename T,
typename =
void>
573 template <
typename Part>
576 std::enable_if_t<std::is_base_of<PartitionBase, std::decay_t<Part>>::value>>
577 :
public std::true_type {};
580 template <
typename T>
585 template <
typename,
typename =
void>
588 template <
typename PartPtr>
590 std::enable_if_t<is_partition_type_v<decltype(*std::declval<PartPtr>())>>>
591 :
public std::true_type {};
594 template <
typename T>
599 template <
typename,
typename =
void>
602 template <
typename Iter>
605 std::enable_if_t<is_partition_ptr_v<std::decay_t<typename Iter::value_type>>>>
606 :
public std::true_type {};
612 template <AreaOwner::AreaRangeMember_t Range>
614 static constexpr
auto range = Range;
626 template <PartitionBase::AreaRangeMember_t Range>
633 using Base_t::operator();
636 template <
typename PartPtr,
640 return operator()(*part);
645 template <PartitionBase::AreaRangeMember_t Range>
651 static constexpr
auto range = Range;
653 template <
typename T>
654 static auto key(T
const& obj)
660 using Key_t = decltype(Sorter_t::key(std::declval<PartitionBase>()));
665 template <
typename A,
typename B>
668 return sortKey(key(a), key(b));
680 template <
typename Data>
681 template <
typename Stream>
685 std::string firstIndent
689 std::string typeName = lar::debug::demangle<Data>();
690 if (data) { out << typeName <<
"[" << ((
void*)data) <<
"]"; }
692 out <<
"no '" << typeName <<
"' data";
696 template <
typename Stream,
typename Data>
700 std::string firstIndent
709 template <
typename Data>
713 template <
typename Data>
714 template <
typename Pred>
721 for (
auto const& subPart : start->
parts())
722 subPart->walk(std::forward<Pred>(pred));
728 template <
typename Data>
730 std::string firstIndent)
const 732 std::string msg = Base_t::doDescribe(indent, firstIndent);
734 std::ostringstream sstr;
749 template <
typename Data>
752 if (!Base_t::contains(
w,
d))
return nullptr;
754 auto part = findPart(
w,
d);
755 return part ?
part->atPoint(
w,
d) : Base_t::data();
759 template <
typename Data>
761 std::string firstIndent)
const 763 std::string msg = firstIndent + describeIntro();
764 if (Base_t::data()) {
765 std::ostringstream sstr;
771 for (
auto const&
part : parts()) {
772 msg +=
"\n" + indent +
" * ";
773 msg +=
part->describe(indent +
" ",
"");
780 template <
typename Data>
789 template <
typename Data,
typename Sorter>
793 auto pbegin = Base_t::parts().cbegin();
794 auto iPart = std::upper_bound(pbegin, Base_t::parts().
cend(), key, sorter);
795 return (iPart == pbegin) ?
nullptr : (--iPart)->
get();
799 template <
typename Data,
typename Sorter>
806 std::sort(Base_t::myParts.
begin(), Base_t::myParts.
end(), sorter);
812 template <
typename Data>
815 std::ostringstream sstr;
816 sstr <<
Base_t::size() <<
" partitions along depth covering " << Base_t::area();
823 template <
typename Data>
826 std::ostringstream sstr;
827 sstr <<
Base_t::size() <<
" partitions along width covering " << Base_t::area();
834 template <
typename Data>
837 unsigned int nDepthPartitions,
838 unsigned int nWidthPartitions,
841 :
Base_t(area, std::move(subpartitions), defData)
842 , widthSeps(computeWidthSeps(nDepthPartitions, nWidthPartitions))
843 , depthSeps(computeDepthSeps(nDepthPartitions, nWidthPartitions))
845 assert(nWidthPartitions * nDepthPartitions ==
Base_t::size());
848 template <
typename Data>
851 unsigned int nDepthPartitions,
855 std::move(subpartitions),
857 (nDepthPartitions ? subpartitions.
size() / nDepthPartitions : 0),
862 template <
typename Data>
864 std::string firstIndent)
const 866 std::ostringstream sstr;
873 for (std::size_t iDepth = 0; iDepth <
nDepthParts(); ++iDepth) {
874 for (std::size_t iWidth = 0; iWidth <
nWidthParts(); ++iWidth) {
876 << indent <<
" [" << iDepth <<
"][" << iWidth <<
"] " 877 <<
part(iDepth, iWidth)->describe(indent +
" ",
"");
884 template <
typename Data>
888 if (iWidth ==
widthSeps.cbegin())
return nullptr;
890 if (iDepth ==
depthSeps.cbegin())
return nullptr;
892 std::distance(
widthSeps.cbegin(), iWidth) - 1U)
897 template <
typename Data>
899 unsigned int nW)
const 901 return detectSeparators<&Area_t::width>(
905 template <
typename Data>
907 unsigned int nW)
const 909 return detectSeparators<&Area_t::depth>(
913 template <
typename Data>
914 template <geo::part::AreaOwner::AreaRangeMember_t Range,
typename BeginIter,
typename EndIter>
917 std::size_t
const nGroups,
918 std::size_t
const startDelta,
919 std::size_t
const stride)
950 "Begin iterator does not point to a pointer to partition type");
954 std::size_t
const nParts = std::distance(b, e);
955 std::size_t
const nPartsInGroup = nParts / nGroups;
957 auto const part = [b](std::size_t index) {
return std::next(b, index)->get(); };
959 std::vector<double> seps(nGroups);
960 for (
size_t g = 0; g < nGroups; ++g) {
962 double& sep = seps[g];
965 std::size_t index = g * startDelta;
966 sep = lowerBound(
part(index));
968 std::size_t
const iend = index + nPartsInGroup * stride;
969 while ((index += stride) < iend) {
970 double const l = lowerBound(
part(index));
971 if (sep > l) sep = l;
980 #endif // LARCOREALG_GEOMETRY_PARTITIONS_H
Partition_t const * findPartWithKey(double key) const
Returns the only partition which could contain the specified key.
AreaOwner(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
Trait type evaluating true if T is iterator to some PartitionBase.
PartitionBase(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
PartitionContainer(Area_t const &area, Subpartitions_t &&subpartitions, Data_t *defData=nullptr)
Constructor: sets the partition.
A basic interface for objects owning an area.
void describePartitionData(Stream &&out, Data const *data, std::string indent="", std::string firstIndent="")
Describes a data object for Partition::describe() method.
Partition-related utilities.
auto part(std::size_t iDepth, std::size_t iWidth) -> decltype(auto)
std::vector< double > computeDepthSeps(unsigned int nD, unsigned int nW) const
Computes and returns width separation levels proper for depthSeps.
constexpr bool is_partition_type_v
Constant true if T is derived from PartitionBase.
static Key_t key(Key_t k)
static auto key(T const &obj)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Partition of area along the width dimension.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Describes this and each of the subpartitions.
void initParts()
Performs initialization on the specified subpartition list.
virtual Base_t::Partition_t const * findPart(double, double d) const override
Returns the only partition which could contain the specified depth.
virtual Data_t * atPoint(double w, double d) const override
Returns stored datum only if point is covered, nullptr otherwise.
bool contains(Data_t w, Data_t d) const
Returns whether the specified point is in the area.
Class providing custom dump for data contained in the partition.
std::vector< double > depthSeps
Separators for depth dimension.
virtual Data_t * data() const
Returns the datum directly stored (nullptr if none).
Ordering class to sort partition by specified range (lower boundary).
bool operator()(A const &a, B const &b) const
std::vector< double > widthSeps
Separators for width dimension.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const
Returns a description of the partition.
bool contains(double w, double d) const
Returns whether the specified point is covered by this object.
std::vector< double > computeWidthSeps(unsigned int nD, unsigned int nW) const
Computes and returns width separation levels proper for widthSeps.
std::string describe(std::string indent="") const
Returns a description of the partition.
Partition(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Trait type evaluating true if T is derived from PartitionBase.
Non-template definitions and data for Partition class hierarchy.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
std::vector< std::unique_ptr< Partition_t const >> Subpartitions_t
Type of list of subpartitions. It needs to preserve polymorphism.
Base element of a partitioned structure.
virtual Subpartitions_t const & parts() const
Returns a list of all subpartitions.
Partition of area along the depth dimension.
Area_t myArea
Covered area.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Returns a description of the partition.
Partition of area along a area range dimension (width or depth).
lar::util::simple_geo::Rectangle< double > Area_t
Type of area covered by the partition.
std::string indent(std::size_t const i)
Area_t const & area() const
Returns the covered area.
PartitionWithData(Area_t const &area, Data_t *myData)
Constructor: sets the covered area and the contained datum.
std::size_t size() const
Returns the number of contained subpartitions.
void walk(Pred &&pred) const
Applies pred to all partitions.
virtual Subpartitions_t const & parts() const override
Returns a list of the subpartitions owned.
virtual Partition_t const * findPart(double w, double d) const override
Returns the only partition which could contain the specified depth.
Range< Data_t > Range_t
Type for dimension boundaries.
static Subpartitions_t const NoSubparts
Subpartitions (if any).
Subpartitions_t myParts
List of subpartitions.
Data_t * myData
The contained datum.
void dumpArea(Stream &&out) const
Output the owned area into an output stream.
std::string describe(std::string indent, std::string firstIndent) const
Returns a description of the partition.
std::size_t nWidthParts() const
Number of partitions on width direction.
virtual Data_t * data() const override
Returns the datum directly stored (nullptr if none).
static bool sortKey(Key_t a, Key_t b)
virtual Data_t * atPoint(double w, double d) const override
Returns stored datum only if point is covered, nullptr otherwise.
Unpartitioned element ("leaf") of a partitioned area.
Partition divided in subpartitions (abstract).
auto part(std::size_t iDepth, std::size_t iWidth) const -> decltype(auto)
decltype(Sorter_t::key(std::declval< PartitionBase >())) Key_t
Type of sorting key. In short: double.
Data Data_t
Type of data stored in the partition.
SortedPartition(Area_t const &area, Subpartitions_t &&subpartitions, Data_t *defData=nullptr, Sorter_t sorter={})
Constructor: sets the partition.
Functions to help debugging by instrumenting code.
constexpr bool is_partition_ptr_v
Constant true if T is pointer to some PartitionBase.
Sorter_t sorter
Object used for sorting and binary search.
static std::vector< double > detectSeparators(BeginIter b, EndIter e, std::size_t const nGroups, std::size_t const startDelta, std::size_t const stride)
Some simple functions to represent geometry entitiesThis library is simple and header-only.
Partition of area sorted across a dimension.
virtual std::string describeIntro() const
Introduction to the description of the subpartitions.
std::size_t nDepthParts() const
A container of partitions organised in a width/depth rectangular grid.
Trait type evaluating true if T is pointer to some PartitionBase.
virtual Base_t::Partition_t const * findPart(double w, double) const override
Returns the only partition which could contain the specified depth.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Prints the information about the partition grid.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
std::size_t nParts() const
Returns the number of subparts in the partition (0 if simple element).
virtual std::string describeIntro() const override
Introduction to the description of the subpartitions.
std::string describeArea(std::string indent, std::string firstIndent) const
Returns a description of the partition area.
Data_t lower
Starting coordinate.
GridPartition(Area_t const &area, Subpartitions_t &&subpartitions, unsigned int nDepthPartitions, unsigned int nWidthPartitions, Data_t *defData=nullptr)
Creates a partition with a grid of subpartitions.
Partition also containing data directly.
PartitionDataDescriber(Stream &&out, Data const *data, std::string indent="", std::string firstIndent="")
Constructor; see describePartitionData() for argument description.
typename Partition_t::Data_t Data_t
Type of contained data.
virtual std::string describeIntro() const override
Introduction to the description of the subpartitions.
Area_t::Range_t(Area_t::*) AreaRangeMember_t
Type of pointer to Area_t data member of type Range_t.