29 std::unique_ptr<Acts::SurfaceArray>
 
   32     std::vector<std::shared_ptr<const Surface>> surfaces, 
size_t binsPhi,
 
   33     size_t binsZ, std::optional<ProtoLayer> protoLayerOpt,
 
   38       protoLayerOpt ? *protoLayerOpt : 
ProtoLayer(gctx, surfacesRaw);
 
   41   ACTS_VERBOSE(
" -- with " << surfaces.size() << 
" surfaces.")
 
   42   ACTS_VERBOSE(
" -- with phi x z  = " << binsPhi << 
" x " << binsZ << 
" = " 
   43                                       << binsPhi * binsZ << 
" bins.");
 
   47                                              protoLayer, ftransform, binsPhi);
 
   55   auto globalToLocal = [ftransform](
const Vector3D& 
pos) {
 
   59   auto localToGlobal = [itransform, 
R](
const Vector2D& loc) {
 
   64   std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
 
   66                               detail::AxisBoundaryType::Bound>(
 
   67           globalToLocal, localToGlobal, pAxisPhi, pAxisZ);
 
   69   sl->fill(gctx, surfacesRaw);
 
   72   return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
 
   76 std::unique_ptr<Acts::SurfaceArray>
 
   80     BinningType bTypeZ, std::optional<ProtoLayer> protoLayerOpt,
 
   85       protoLayerOpt ? *protoLayerOpt : 
ProtoLayer(gctx, surfacesRaw);
 
   95     pAxisPhi = createEquidistantAxis(gctx, surfacesRaw, 
binPhi, protoLayer,
 
   99         createVariableAxis(gctx, surfacesRaw, 
binPhi, protoLayer, ftransform);
 
  104         createEquidistantAxis(gctx, surfacesRaw, 
binZ, protoLayer, ftransform);
 
  107         createVariableAxis(gctx, surfacesRaw, 
binZ, protoLayer, ftransform);
 
  111   auto globalToLocal = [ftransform](
const Vector3D& 
pos) {
 
  115   auto localToGlobal = [itransform, 
R](
const Vector2D& loc) {
 
  120   std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
 
  121       makeSurfaceGridLookup2D<detail::AxisBoundaryType::Closed,
 
  122                               detail::AxisBoundaryType::Bound>(
 
  123           globalToLocal, localToGlobal, pAxisPhi, pAxisZ);
 
  125   sl->
fill(gctx, surfacesRaw);
 
  126   completeBinning(gctx, *sl, surfacesRaw);
 
  130   size_t bins0 = axes.at(0)->getNBins();
 
  131   size_t bins1 = axes.at(1)->getNBins();
 
  134   ACTS_VERBOSE(
" -- with " << surfaces.size() << 
" surfaces.")
 
  135   ACTS_VERBOSE(
" -- with phi x z  = " << bins0 << 
" x " << bins1 << 
" = " 
  136                                       << bins0 * bins1 << 
" bins.");
 
  138   return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
 
  142 std::unique_ptr<Acts::SurfaceArray>
 
  145     std::vector<std::shared_ptr<const Surface>> surfaces, 
size_t binsR,
 
  146     size_t binsPhi, std::optional<ProtoLayer> protoLayerOpt,
 
  151       protoLayerOpt ? *protoLayerOpt : 
ProtoLayer(gctx, surfacesRaw);
 
  156   ProtoAxis pAxisR = createEquidistantAxis(gctx, surfacesRaw, 
binR, protoLayer,
 
  159                                              protoLayer, ftransform, binsPhi);
 
  162   ACTS_VERBOSE(
"- z-position of disk estimated as " << Z);
 
  166   auto globalToLocal = [ftransform](
const Vector3D& 
pos) {
 
  170   auto localToGlobal = [itransform, Z](
const Vector2D& loc) {
 
  175   std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
 
  176       makeSurfaceGridLookup2D<detail::AxisBoundaryType::Bound,
 
  177                               detail::AxisBoundaryType::Closed>(
 
  178           globalToLocal, localToGlobal, pAxisR, pAxisPhi);
 
  182   size_t bins0 = axes.at(0)->getNBins();
 
  183   size_t bins1 = axes.at(1)->getNBins();
 
  185   ACTS_VERBOSE(
" -- with " << surfaces.size() << 
" surfaces.")
 
  186   ACTS_VERBOSE(
" -- with r x phi  = " << bins0 << 
" x " << bins1 << 
" = " 
  187                                       << bins0 * bins1 << 
" bins.");
 
  188   sl->
fill(gctx, surfacesRaw);
 
  189   completeBinning(gctx, *sl, surfacesRaw);
 
  191   return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
 
  195 std::unique_ptr<Acts::SurfaceArray>
 
  199     BinningType bTypePhi, std::optional<ProtoLayer> protoLayerOpt,
 
  204       protoLayerOpt ? *protoLayerOpt : 
ProtoLayer(gctx, surfacesRaw);
 
  215         createEquidistantAxis(gctx, surfacesRaw, 
binR, protoLayer, ftransform);
 
  218         createVariableAxis(gctx, surfacesRaw, 
binR, protoLayer, ftransform);
 
  223   if (pAxisR.
nBins > 1) {
 
  226     std::vector<std::vector<const Surface*>> phiModules(pAxisR.
nBins);
 
  227     for (
const auto& srf : surfacesRaw) {
 
  230       phiModules.at(bin).push_back(srf);
 
  233     std::vector<size_t> nPhiModules;
 
  234     auto matcher = m_cfg.surfaceMatcher;
 
  236       return matcher(gctx, 
binPhi, a, b);
 
  240         phiModules.begin(), phiModules.end(), std::back_inserter(nPhiModules),
 
  241         [&equal, 
this](std::vector<const Surface*> surfaces_) -> 
size_t {
 
  242           return this->findKeySurfaces(surfaces_, equal).size();
 
  252         (*std::min_element(nPhiModules.begin(), nPhiModules.end()));
 
  253     pAxisPhi = createEquidistantAxis(gctx, surfacesRaw, 
binPhi, protoLayer,
 
  254                                      ftransform, nBinsPhi);
 
  259       pAxisPhi = createEquidistantAxis(gctx, surfacesRaw, 
binPhi, protoLayer,
 
  263           createVariableAxis(gctx, surfacesRaw, 
binPhi, protoLayer, ftransform);
 
  268   ACTS_VERBOSE(
"- z-position of disk estimated as " << Z);
 
  272   auto globalToLocal = [ftransform](
const Vector3D& 
pos) {
 
  276   auto localToGlobal = [itransform, Z](
const Vector2D& loc) {
 
  281   std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
 
  282       makeSurfaceGridLookup2D<detail::AxisBoundaryType::Bound,
 
  283                               detail::AxisBoundaryType::Closed>(
 
  284           globalToLocal, localToGlobal, pAxisR, pAxisPhi);
 
  288   size_t bins0 = axes.at(0)->getNBins();
 
  289   size_t bins1 = axes.at(1)->getNBins();
 
  291   ACTS_VERBOSE(
" -- with " << surfaces.size() << 
" surfaces.")
 
  292   ACTS_VERBOSE(
" -- with r x phi  = " << bins0 << 
" x " << bins1 << 
" = " 
  293                                       << bins0 * bins1 << 
" bins.");
 
  295   sl->
fill(gctx, surfacesRaw);
 
  296   completeBinning(gctx, *sl, surfacesRaw);
 
  298   return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
 
  303 std::unique_ptr<Acts::SurfaceArray>
 
  306     std::vector<std::shared_ptr<const Surface>> surfaces, 
size_t bins1,
 
  307     size_t bins2, 
BinningValue bValue, std::optional<ProtoLayer> protoLayerOpt,
 
  312       protoLayerOpt ? *protoLayerOpt : 
ProtoLayer(gctx, surfacesRaw);
 
  315   ACTS_VERBOSE(
" -- with " << surfaces.size() << 
" surfaces.")
 
  316   ACTS_VERBOSE(
" -- with " << bins1 << 
" x " << bins2 << 
" = " << bins1 * bins2
 
  321   auto globalToLocal = [ftransform](
const Vector3D& 
pos) {
 
  325   auto localToGlobal = [itransform](
const Vector2D& loc) {
 
  326     return itransform * 
Vector3D(loc.x(), loc.y(), 0.);
 
  329   std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl;
 
  334       ProtoAxis pAxis1 = createEquidistantAxis(gctx, surfacesRaw, 
binY,
 
  335                                                protoLayer, ftransform, bins1);
 
  336       ProtoAxis pAxis2 = createEquidistantAxis(gctx, surfacesRaw, 
binZ,
 
  337                                                protoLayer, ftransform, bins2);
 
  338       sl = makeSurfaceGridLookup2D<detail::AxisBoundaryType::Bound,
 
  339                                    detail::AxisBoundaryType::Bound>(
 
  340           globalToLocal, localToGlobal, pAxis1, pAxis2);
 
  344       ProtoAxis pAxis1 = createEquidistantAxis(gctx, surfacesRaw, 
binX,
 
  345                                                protoLayer, ftransform, bins1);
 
  346       ProtoAxis pAxis2 = createEquidistantAxis(gctx, surfacesRaw, 
binZ,
 
  347                                                protoLayer, ftransform, bins2);
 
  348       sl = makeSurfaceGridLookup2D<detail::AxisBoundaryType::Bound,
 
  349                                    detail::AxisBoundaryType::Bound>(
 
  350           globalToLocal, localToGlobal, pAxis1, pAxis2);
 
  354       ProtoAxis pAxis1 = createEquidistantAxis(gctx, surfacesRaw, 
binX,
 
  355                                                protoLayer, ftransform, bins1);
 
  356       ProtoAxis pAxis2 = createEquidistantAxis(gctx, surfacesRaw, 
binY,
 
  357                                                protoLayer, ftransform, bins2);
 
  358       sl = makeSurfaceGridLookup2D<detail::AxisBoundaryType::Bound,
 
  359                                    detail::AxisBoundaryType::Bound>(
 
  360           globalToLocal, localToGlobal, pAxis1, pAxis2);
 
  364       throw std::invalid_argument(
 
  365           "Acts::SurfaceArrayCreator::" 
  366           "surfaceArrayOnPlane: Invalid binning " 
  371   sl->
fill(gctx, surfacesRaw);
 
  372   completeBinning(gctx, *sl, surfacesRaw);
 
  374   return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
 
  380     const std::vector<const Surface*>& surfaces,
 
  381     const std::function<
bool(
const Surface*, 
const Surface*)>& equal)
 const {
 
  382   std::vector<const Surface*> keys;
 
  383   for (
const auto& srfA : surfaces) {
 
  385     for (
const auto& srfB : keys) {
 
  386       if (equal(srfA, srfB)) {
 
  392       keys.push_back(srfA);
 
  402   auto matcher = m_cfg.surfaceMatcher;
 
  404     return matcher(gctx, bValue, a, b);
 
  406   std::vector<const Surface*> keys = findKeySurfaces(surfaces, equal);
 
  415   if (surfaces.empty()) {
 
  416     throw std::logic_error(
 
  417         "No surfaces handed over for creating arbitrary bin utility!");
 
  423   auto matcher = m_cfg.surfaceMatcher;
 
  426     return matcher(gctx, bValue, a, b);
 
  428   std::vector<const Acts::Surface*> keys = findKeySurfaces(surfaces, equal);
 
  430   std::vector<double> bValues;
 
  432     std::stable_sort(keys.begin(), keys.end(),
 
  438     double maxPhi = 0.5 * (
phi(keys.at(0)->binningPosition(gctx, 
binPhi)) +
 
  439                            phi(keys.at(1)->binningPosition(gctx, 
binPhi)));
 
  448     double previous = 
phi(keys.at(0)->binningPosition(gctx, 
binPhi));
 
  450     for (
size_t i = 1; i < keys.size(); i++) {
 
  458       bValues.push_back(edge);
 
  463     unsigned int segments = 72;
 
  469     if (backBounds == 
nullptr)
 
  471           "Given SurfaceBounds are not planar - not implemented for " 
  472           "other bounds yet! ");
 
  474     std::vector<Acts::Vector3D> backVertices =
 
  475         makeGlobalVertices(gctx, *backSurface, backBounds->
vertices(segments));
 
  476     double maxBValue = 
phi(
 
  477         *std::max_element(backVertices.begin(), backVertices.end(),
 
  482     bValues.push_back(maxBValue);
 
  484     bValues.push_back(
M_PI);
 
  487     std::stable_sort(keys.begin(), keys.end(),
 
  490                                b->binningPosition(gctx, 
binZ).z());
 
  493     bValues.push_back(protoLayer.
min(
binZ));
 
  494     bValues.push_back(protoLayer.
max(
binZ));
 
  497     double previous = keys.front()->binningPosition(gctx, 
binZ).z();
 
  504           0.5 * (previous + (*surface)->binningPosition(gctx, 
binZ).z()));
 
  505       previous = (*surface)->binningPosition(gctx, 
binZ).z();
 
  508     std::stable_sort(keys.begin(), keys.end(),
 
  511                                perp(b->binningPosition(gctx, 
binR)));
 
  514     bValues.push_back(protoLayer.
min(
binR));
 
  515     bValues.push_back(protoLayer.
max(
binR));
 
  518     double previous = 
perp(keys.front()->binningPosition(gctx, 
binR));
 
  526           0.5 * (previous + 
perp((*surface)->binningPosition(gctx, 
binR))));
 
  527       previous = 
perp((*surface)->binningPosition(gctx, 
binR));
 
  530   std::sort(bValues.begin(), bValues.end());
 
  531   ACTS_VERBOSE(
"Create variable binning Axis for binned SurfaceArray");
 
  534       " (binX = 0, binY = 1, binZ = 2, binR = 3, binPhi = 4, " 
  535       "binRPhi = 5, binH = 6, binEta = 7)");
 
  536   ACTS_VERBOSE(
"  Number of bins: " << (bValues.size() - 1));
 
  538                                        << bValues.back() << 
")");
 
  542   pAxis.bValue = bValue;
 
  543   pAxis.binEdges = bValues;
 
  544   pAxis.nBins = bValues.size() - 1;
 
  553     size_t nBins)
 const {
 
  554   if (surfaces.empty()) {
 
  555     throw std::logic_error(
 
  556         "No surfaces handed over for creating equidistant axis!");
 
  568   std::vector<const Acts::Surface*> keys;
 
  573     binNumber = determineBinCount(gctx, surfaces, bValue);
 
  580   auto matcher = m_cfg.surfaceMatcher;
 
  584     if (m_cfg.doPhiBinningOptimization) {
 
  589           surfaces.begin(), surfaces.end(),
 
  592                    phi(b->binningPosition(gctx, 
binR));
 
  596       auto equal = [&
gctx, &bValue, &matcher](
const Surface* a,
 
  598         return matcher(gctx, bValue, a, b);
 
  600       keys = findKeySurfaces(surfaces, equal);
 
  603       if (keys.size() > 1) {
 
  615         double angle = 
M_PI - (max + 0.5 * 
step);
 
  630     maximum = protoLayer.
max(bValue, 
false);
 
  631     minimum = protoLayer.
min(bValue, 
false);
 
  635   ACTS_VERBOSE(
"Create equidistant binning Axis for binned SurfaceArray");
 
  638       " (binX = 0, binY = 1, binZ = 2, binR = 3, binPhi = 4, " 
  639       "binRPhi = 5, binH = 6, binEta = 7)");
 
  641   ACTS_VERBOSE(
"  (Min/Max) = (" << minimum << 
"/" << maximum << 
")");
 
  648   pAxis.
nBins = binNumber;
 
  655     const std::vector<Acts::Vector2D>& locVertices)
 const {
 
  656   std::vector<Acts::Vector3D> globVertices;
 
  657   for (
auto& vertex : locVertices) {
 
  660     globVertices.push_back(globVertex);