11 #ifndef LARCOREALG_GEOMETRY_PARTITIONS_H 12 #define LARCOREALG_GEOMETRY_PARTITIONS_H 26 #include <type_traits> 56 template <
typename Stream>
59 std::forward<Stream>(out) <<
area();
70 template <AreaOwner::AreaRangeMember_t Range>
95 template <
typename Data>
98 template <
typename Stream>
102 std::string firstIndent =
"");
123 template <
typename Stream,
typename Data>
127 std::string firstIndent =
"");
152 std::string describeArea(std::string
indent, std::string firstIndent)
const;
182 template <
typename Data>
212 virtual Data_t* atPoint(
double w,
double d)
const = 0;
217 return doDescribe(indent, firstIndent);
240 template <
typename Pred>
247 std::size_t
nParts()
const {
return parts().size(); }
263 template <
typename Pred>
264 static void walk(
Partition_t const* start, Pred&& pred);
272 template <
typename Data>
290 return Base_t::contains(w, d) ? myData :
nullptr;
297 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
303 template <
typename Data>
310 using Base_t::Base_t;
316 template <
typename Data>
329 virtual Data_t* atPoint(
double w,
double d)
const override;
335 std::size_t
size()
const {
return parts().size(); }
355 Data_t* defData =
nullptr)
356 :
Base_t(area, defData), myParts(
std::move(subpartitions))
360 virtual Partition_t const* findPart(
double w,
double d)
const = 0;
363 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
366 virtual std::string describeIntro()
const;
386 template <
typename Data,
typename Sorter>
417 Data_t* defData =
nullptr,
419 :
Base_t(area, std::move(subpartitions), defData), sorter(sorter)
428 Partition_t const* findPartWithKey(
double key)
const;
437 template <
typename Data, PartitionBase::AreaRangeMember_t Range>
439 :
public SortedPartition<Data, details::PartitionSorterByAreaRangeLower<Range>> {
443 using Base_t::Base_t;
449 template <
typename Data>
455 using Base_t::Base_t;
460 return Base_t::findPartWithKey(d);
464 virtual std::string describeIntro()
const override;
470 template <
typename Data>
476 using Base_t::Base_t;
481 return Base_t::findPartWithKey(w);
485 virtual std::string describeIntro()
const override;
491 template <
typename Data>
518 unsigned int nDepthPartitions,
519 unsigned int nWidthPartitions,
520 Data_t* defData =
nullptr);
526 unsigned int nDepthPartitions,
527 Data_t* defData =
nullptr);
538 auto part(std::size_t iDepth, std::size_t iWidth) -> decltype(
auto)
540 return Base_t::parts()[iDepth * nWidthParts() + iWidth];
542 auto part(std::size_t iDepth, std::size_t iWidth)
const -> decltype(
auto)
544 return Base_t::parts()[iDepth * nWidthParts() + iWidth];
548 virtual Partition_t const* findPart(
double w,
double d)
const override;
551 std::vector<double> computeWidthSeps(
unsigned int nD,
unsigned int nW)
const;
553 std::vector<double> computeDepthSeps(
unsigned int nD,
unsigned int nW)
const;
556 virtual std::string doDescribe(std::string
indent, std::string firstIndent)
const override;
558 template <PartitionBase::AreaRangeMember_t Range,
typename BeginIter,
typename EndIter>
559 static std::vector<double> detectSeparators(BeginIter b,
561 std::size_t
const nGroups,
562 std::size_t
const startDelta,
563 std::size_t
const stride);
576 std::string firstIndent)
const 578 std::ostringstream sstr;
579 sstr << firstIndent <<
"partition covers ";
596 template <
typename T,
typename =
void>
599 template <
typename Part>
602 std::enable_if_t<std::is_base_of<PartitionBase, std::decay_t<Part>>::value>>
603 :
public std::true_type {};
606 template <
typename T>
611 template <
typename,
typename =
void>
614 template <
typename PartPtr>
617 std::enable_if_t<is_partition_type_v<decltype(*std::declval<PartPtr>())>>>
618 :
public std::true_type {};
621 template <
typename T>
626 template <
typename,
typename =
void>
629 template <
typename Iter>
632 std::enable_if_t<is_partition_ptr_v<std::decay_t<typename Iter::value_type>>>>
633 :
public std::true_type {};
639 template <AreaOwner::AreaRangeMember_t Range>
641 static constexpr
auto range = Range;
655 template <PartitionBase::AreaRangeMember_t Range>
662 using Base_t::operator();
665 template <
typename PartPtr,
669 return operator()(*part);
675 template <PartitionBase::AreaRangeMember_t Range>
681 static constexpr
auto range = Range;
683 template <
typename T>
684 static auto key(T
const& obj)
690 using Key_t = decltype(Sorter_t::key(std::declval<PartitionBase>()));
695 template <
typename A,
typename B>
698 return sortKey(key(a), key(b));
713 template <
typename Data>
714 template <
typename Stream>
718 std::string firstIndent
722 std::string typeName = lar::debug::demangle<Data>();
723 if (data) { out << typeName <<
"[" << ((
void*)data) <<
"]"; }
725 out <<
"no '" << typeName <<
"' data";
729 template <
typename Stream,
typename Data>
733 std::string firstIndent
742 template <
typename Data>
746 template <
typename Data>
747 template <
typename Pred>
754 for (
auto const& subPart : start->
parts())
755 subPart->walk(std::forward<Pred>(pred));
762 template <
typename Data>
764 std::string firstIndent)
const 766 std::string msg = Base_t::doDescribe(indent, firstIndent);
768 std::ostringstream sstr;
783 template <
typename Data>
786 if (!Base_t::contains(
w,
d))
return nullptr;
788 auto part = findPart(
w,
d);
789 return part ?
part->atPoint(
w,
d) : Base_t::data();
793 template <
typename Data>
795 std::string firstIndent)
const 797 std::string msg = firstIndent + describeIntro();
798 if (Base_t::data()) {
799 std::ostringstream sstr;
805 for (
auto const&
part : parts()) {
806 msg +=
"\n" + indent +
" * ";
807 msg +=
part->describe(indent +
" ",
"");
814 template <
typename Data>
823 template <
typename Data,
typename Sorter>
827 auto pbegin = Base_t::parts().cbegin();
828 auto iPart = std::upper_bound(pbegin, Base_t::parts().
cend(), key, sorter);
829 return (iPart == pbegin) ?
nullptr : (--iPart)->
get();
833 template <
typename Data,
typename Sorter>
841 std::sort(Base_t::myParts.
begin(), Base_t::myParts.
end(), sorter);
848 template <
typename Data>
851 std::ostringstream sstr;
852 sstr <<
Base_t::size() <<
" partitions along depth covering " << Base_t::area();
859 template <
typename Data>
862 std::ostringstream sstr;
863 sstr <<
Base_t::size() <<
" partitions along width covering " << Base_t::area();
870 template <
typename Data>
873 unsigned int nDepthPartitions,
874 unsigned int nWidthPartitions,
877 :
Base_t(area,
std::move(subpartitions), defData)
878 , widthSeps(computeWidthSeps(nDepthPartitions, nWidthPartitions))
879 , depthSeps(computeDepthSeps(nDepthPartitions, nWidthPartitions))
881 assert(nWidthPartitions * nDepthPartitions ==
Base_t::size());
884 template <
typename Data>
887 unsigned int nDepthPartitions,
891 std::move(subpartitions),
893 (nDepthPartitions ? subpartitions.
size() / nDepthPartitions : 0),
898 template <
typename Data>
900 std::string firstIndent)
const 902 std::ostringstream sstr;
909 for (std::size_t iDepth = 0; iDepth <
nDepthParts(); ++iDepth) {
910 for (std::size_t iWidth = 0; iWidth <
nWidthParts(); ++iWidth) {
912 << indent <<
" [" << iDepth <<
"][" << iWidth <<
"] " 913 <<
part(iDepth, iWidth)->describe(indent +
" ",
"");
921 template <
typename Data>
925 if (iWidth ==
widthSeps.cbegin())
return nullptr;
927 if (iDepth ==
depthSeps.cbegin())
return nullptr;
929 std::distance(
widthSeps.cbegin(), iWidth) - 1U)
934 template <
typename Data>
936 unsigned int nW)
const 938 return detectSeparators<&Area_t::width>(
942 template <
typename Data>
944 unsigned int nW)
const 946 return detectSeparators<&Area_t::depth>(
950 template <
typename Data>
951 template <geo::part::AreaOwner::AreaRangeMember_t Range,
typename BeginIter,
typename EndIter>
954 std::size_t
const nGroups,
955 std::size_t
const startDelta,
956 std::size_t
const stride)
987 "Begin iterator does not point to a pointer to partition type");
991 std::size_t
const nParts = std::distance(b, e);
992 std::size_t
const nPartsInGroup = nParts / nGroups;
994 auto const part = [b](std::size_t index) {
return std::next(b, index)->get(); };
996 std::vector<double> seps(nGroups);
997 for (
size_t g = 0; g < nGroups; ++g) {
999 double& sep = seps[g];
1002 std::size_t index = g * startDelta;
1003 sep = lowerBound(
part(index));
1005 std::size_t
const iend = index + nPartsInGroup * stride;
1006 while ((index += stride) < iend) {
1007 double const l = lowerBound(
part(index));
1008 if (sep > l) sep = l;
1017 #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.
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.
auto part(std::size_t iDepth, std::size_t iWidth) -> decltype(auto)
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)
auto part(std::size_t iDepth, std::size_t iWidth) const -> decltype(auto)
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).
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 entities.
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.
Namespace collecting geometry-related classes utilities.
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.