diff --git a/Core/include/Acts/Geometry/Extent.hpp b/Core/include/Acts/Geometry/Extent.hpp index 471f12c010a..4ec8ecc4cd9 100644 --- a/Core/include/Acts/Geometry/Extent.hpp +++ b/Core/include/Acts/Geometry/Extent.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2016-2018 CERN for the benefit of the Acts project +// Copyright (C) 2022 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -8,124 +8,220 @@ #pragma once +/// @note This file is foreseen for the `Geometry` module to replace `Extent` + #include "Acts/Definitions/Algebra.hpp" #include "Acts/Utilities/BinningType.hpp" -#include "Acts/Utilities/Helpers.hpp" +#include "Acts/Utilities/Enumerate.hpp" +#include "Acts/Utilities/Range1D.hpp" +#include "Acts/Utilities/RangeXD.hpp" -#include -#include -#include -#include -#include +#include +#include +#include #include namespace Acts { -using Range = std::pair; +using Envelope = std::array; +using ExtentEnvelope = std::array, binValues>; + +constexpr Envelope zeroEnvelope = {0., 0}; +constexpr ExtentEnvelope zeroEnvelopes = { + zeroEnvelope, zeroEnvelope, zeroEnvelope, zeroEnvelope, + zeroEnvelope, zeroEnvelope, zeroEnvelope, zeroEnvelope}; -// @brief Extent in space +/// A class representing the geometric extent of an object in its possbile +/// dimensions, these can be all dimensions that are described as BinningValues +/// +/// The extent object can have an optional envelope in all of those values +/// @note that the consistency of the different envelopes is not checked /// -/// This is a nested struct to the GeometryObject representation -/// which can be retrieved and used for surface parsing and will -/// give you the maximal extent in 3D space/ -struct Extent { - /// Possible maximal value - static constexpr double maxval = std::numeric_limits::max(); - - /// Start value - static constexpr Range maxrange = {maxval, -maxval}; - - // The different ranges - std::vector ranges{(int)binValues, maxrange}; - - // Constructor - Extent() = default; - - /// Check if it intersects - /// @param other The source Extent - /// @param bVal The binning value for the check (binValues for all) - /// @param tolerance An additional tolerance for the intersection check - bool intersects(const Extent& other, BinningValue bVal = binValues, - double tolerance = s_epsilon) { - // Helper to check - auto checkRange = [&](BinningValue bvc) -> bool { - auto& a = ranges[bvc]; - auto& b = other.ranges[bvc]; - return (a.second + tolerance > b.first and - a.first - tolerance < b.second); - }; - - // Check all - if (bVal == binValues) { - for (int ibv = 0; ibv < (int)binValues; ++ibv) { - if (checkRange((BinningValue)ibv)) { - return true; - } - } - return false; +class Extent { + public: + /// Constructor with (optional) @param envelope + Extent(const ExtentEnvelope& envelope = zeroEnvelopes); + + /// Extend with a position vertex + /// + /// @param vtx the vertex to be used for extending + /// @param bValues the binning values + /// @param applyEnv boolean to steer if envelope should be applied + /// @param fillHistograms is a boolean flag to steer whether the values + /// to fill this extent should be stored + void extend(const Vector3& vtx, + const std::vector& bValues = s_binningValues, + bool applyEnv = true, bool fillHistograms = false); + + /// Extend with a set of vectors by iterators + /// + /// @param start the start iterator of the loop + /// @param end the end iterator of the loop + /// @param bValues the binning values + /// @param applyEnv boolean to steer if envelope should be applied + /// @param fillHistograms is a boolean flag to steer whether the values + /// to fill this extent should be stored + template + void extend(const vector_iterator_t& start, const vector_iterator_t& end, + const std::vector& bValues = s_binningValues, + bool applyEnv = true, bool fillHistograms = false) { + for (vector_iterator_t vIt = start; vIt < end; ++vIt) { + extend(*vIt, bValues, applyEnv, fillHistograms); } - // Check specific - return checkRange(bVal); } - /// Extend with another extent - /// @param other is the source Extent - void extend(const Extent& other) { - for (std::size_t ir = 0; ir < other.ranges.size(); ++ir) { - ranges[ir].first = std::min(ranges[ir].first, other.ranges[ir].first); - ranges[ir].second = std::max(ranges[ir].second, other.ranges[ir].second); + /// Extend with another geometric extent, usually pushes the + /// current range to the boundaries of the rhs extent, + /// unless the current extent is already bigger. + /// + /// @note the extent can also simply set an envelope + /// which then is applied to the current one + /// + /// @param rhs is the other source Extent + /// @param bValues the binning values + /// @param applyEnv boolean to steer if envelope should be applied + /// on the constraint values, if only an envelope is given + /// but the value not constraint, then it is always applied + /// + /// @note that the histogram values can not be filled in this call + void extend(const Extent& rhs, + const std::vector& bValues = s_binningValues, + bool applyEnv = true); + + /// Set a range for a dedicated binning value + /// + /// @param bValue the binning identification + /// @param min the minimum parameter + /// @param max the maximum parameter + void set(BinningValue bValue, ActsScalar min, ActsScalar max); + + /// (re-)Set the envelope + /// + /// @param envelope new envelope to be set + void setEnvelope(const ExtentEnvelope& envelope = zeroEnvelopes); + + /// Return the individual 1-dimensional range + /// + /// @param bValue is the binning value to be returned + /// + /// @return a one dimensional arrange + Range1D& range(BinningValue bValue); + + /// Return the individual 1-dimensional range + /// + /// @param bValue is the binning value to be returned + /// + /// @return a one dimensional arrange + const Range1D& range(BinningValue bValue) const; + + /// Return the N-dimension range + const RangeXD range() const; + + /// Return an D-dimensional sub range according to the + /// the given @param binValues + template + RangeXD range( + const std::array& binValues) const { + RangeXD rRange; + for (auto [i, v] : enumerate(binValues)) { + rRange[i] = range(v); } + return rRange; + } + + /// Return the envelope - non-const access + ExtentEnvelope& envelope(); + + /// Return the envelope - const access + const ExtentEnvelope& envelope() const; + + /// Return the histogram store + /// + /// The histogram stroe can be used for automated binning detection + const std::array, binValues>& valueHistograms() const; + + /// Access the minimum parameter + /// + /// @param bValue the binning identification + ActsScalar min(BinningValue bValue) const { return m_range[bValue].min(); } + + /// Access the maximum parameter + /// + /// @param bValue the binning identification + ActsScalar max(BinningValue bValue) const { return m_range[bValue].max(); } + + /// Access the maximum parameter + /// + /// @param bValue the binning identification + ActsScalar medium(BinningValue bValue) const { + return 0.5 * (m_range[bValue].min() + m_range[bValue].max()); } + /// Contains check + /// + /// @param rhs the extent that is check if it is contained + /// @param bValue is the binning value, if set to binValues + /// the check on all is done + /// + /// @return true if the rhs is contained + bool contains(const Extent& rhs, BinningValue bValue = binValues) const; + + /// Intersection checks + /// + /// @param rhs the extent that is check for intersection + /// @param bValue is the binning value, if set to binValues + /// the check on all is done + /// + /// @return true if the rhs intersects + bool intersects(const Extent& rhs, BinningValue bValue = binValues) const; + + /// Constraints check + /// + /// @param bValue is the binning value, if all the check on all is done + bool constrains(BinningValue bValue = binValues) const; + /// Convert to output stream for screen output /// @param sl [in,out] The output stream std::ostream& toStream(std::ostream& sl) const; - /// Access the minimum parameter - /// @param bval the binning identification - double& min(BinningValue bval) { return ranges[bval].first; } + private: + /// A bitset that remembers the constraint values + std::bitset m_constrains{0}; + /// The actual range store + RangeXD m_range; + /// A potential envenelope + ExtentEnvelope m_envelope = zeroEnvelopes; + /// (Optional) Value histograms for bin detection + std::array, binValues> m_valueHistograms; +}; - /// Access the minimum parameter - /// @param bval the binning identification - double min(BinningValue bval) const { return ranges[bval].first; } +inline Range1D& Acts::Extent::range(BinningValue bValue) { + return m_range[bValue]; +} - /// Access the max parameter - /// @param bval the binning identification - double& max(BinningValue bval) { return ranges[bval].second; } +inline const Range1D& Acts::Extent::range( + BinningValue bValue) const { + return m_range[bValue]; +} - /// Access the max parameter - /// @param bval the binning identification - double max(BinningValue bval) const { return ranges[bval].second; } +inline const RangeXD Extent::range() const { + return m_range; +} - /// Access the medium parameter - /// @param bval the binning identification - double medium(BinningValue bval) const { - return 0.5 * (ranges[bval].first + ranges[bval].second); - } +inline ExtentEnvelope& Extent::envelope() { + return m_envelope; +} - /// Access the range - always positive - /// @param bval the binning identification - double range(BinningValue bval) const { - return std::abs(ranges[bval].second - ranges[bval].first); - } +inline const ExtentEnvelope& Extent::envelope() const { + return m_envelope; +} - /// Check the vertex - /// @param vtx the Vertex to be checked - void check(const Vector3& vtx) { - // min/max value check - auto minMax = [&](BinningValue bval, double value) -> void { - ranges[bval].first = std::min(value, ranges[bval].first); - ranges[bval].second = std::max(value, ranges[bval].second); - }; - // Walk through the binning parameters - for (int bval = 0; bval < binValues; ++bval) { - BinningValue bValue = static_cast(bval); - minMax(bValue, VectorHelpers::cast(vtx, bValue)); - } - } -}; +inline const std::array, binValues>& +Extent::valueHistograms() const { + return m_valueHistograms; +} /// Overload of << operator for std::ostream for debug output -std::ostream& operator<<(std::ostream& sl, const Extent& ext); +std::ostream& operator<<(std::ostream& sl, const Extent& rhs); } // namespace Acts diff --git a/Core/include/Acts/Utilities/BinningType.hpp b/Core/include/Acts/Utilities/BinningType.hpp index 7599deb223c..e59a27796b8 100644 --- a/Core/include/Acts/Utilities/BinningType.hpp +++ b/Core/include/Acts/Utilities/BinningType.hpp @@ -45,6 +45,10 @@ enum BinningValue : int { binValues = 9 }; +/// @brief static list of all binning values +static std::vector s_binningValues = { + binX, binY, binZ, binR, binPhi, binRPhi, binH, binEta, binMag}; + /// @brief screen output option inline const std::vector& binningValueNames() { static const std::vector _binningValueNames = { diff --git a/Core/include/Acts/Utilities/Enumerate.hpp b/Core/include/Acts/Utilities/Enumerate.hpp new file mode 100644 index 00000000000..9802788efe5 --- /dev/null +++ b/Core/include/Acts/Utilities/Enumerate.hpp @@ -0,0 +1,48 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2022 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +namespace Acts { +/// Helper utility to allow indexed enumeration with structured binding +/// +/// Usage: +/// +/// for (auto [ i, value ] = enumerate(container) ) { ... }; +/// +/// with 'container' any stl-like container +/// +template ())), + typename = decltype(std::end(std::declval()))> +constexpr auto enumerate(container_type &&iterable) { + struct iterator { + size_t i; + container_type_iter iter; + + bool operator!=(const iterator &rhs) const { return iter != rhs.iter; } + + /** Increase index and iterator at once */ + void operator++() { + ++i; + ++iter; + } + + /** Tie them together for returning */ + auto operator*() const { return std::tie(i, *iter); } + }; + struct iterable_wrapper { + container_type iterable; + auto begin() { return iterator{0, std::begin(iterable)}; } + auto end() { return iterator{0, std::end(iterable)}; } + }; + return iterable_wrapper{std::forward(iterable)}; +} + +} // namespace Acts diff --git a/Core/src/Geometry/Extent.cpp b/Core/src/Geometry/Extent.cpp index 16a84bf612a..f450c383b1a 100644 --- a/Core/src/Geometry/Extent.cpp +++ b/Core/src/Geometry/Extent.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2020 CERN for the benefit of the Acts project +// Copyright (C) 2022 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -8,20 +8,148 @@ #include "Acts/Geometry/Extent.hpp" -#include -#include +#include "Acts/Utilities/Helpers.hpp" + +Acts::Extent::Extent( + const std::array, binValues>& envelope) + : m_constrains(0), m_envelope(envelope) { + m_range[binR] = + Range1D(0., std::numeric_limits::max()); + m_range[binPhi] = Range1D(-M_PI, M_PI); + m_range[binRPhi] = + Range1D(0., std::numeric_limits::max()); + m_range[binMag] = + Range1D(0., std::numeric_limits::max()); +} + +void Acts::Extent::extend(const Vector3& vtx, + const std::vector& bValues, + bool applyEnv, bool fillHistograms) { + for (auto bValue : bValues) { + // Get the casted value given the binnin value description + ActsScalar cValue = VectorHelpers::cast(vtx, bValue); + if (fillHistograms) { + m_valueHistograms[bValue].push_back(cValue); + } + // Apply envelope as suggested + ActsScalar lEnv = applyEnv ? m_envelope[bValue][0] : 0.; + ActsScalar hEnv = applyEnv ? m_envelope[bValue][1] : 0.; + ActsScalar mValue = cValue - lEnv; + // Special protection for radial value + if (bValue == binR and mValue < 0.) { + mValue = std::max(mValue, 0.); + } + if (constrains(bValue)) { + m_range[bValue].expand(mValue, cValue + hEnv); + } else { + m_range[bValue].shrink(mValue, cValue + hEnv); + } + m_constrains.set(bValue); + } +} + +void Acts::Extent::extend(const Extent& rhs, + const std::vector& bValues, + bool applyEnv) { + for (auto bValue : bValues) { + // The value is constraint, envelope can be optional + if (rhs.constrains(bValue)) { + ActsScalar lEnv = applyEnv ? m_envelope[bValue][0] : 0.; + ActsScalar hEnv = applyEnv ? m_envelope[bValue][1] : 0.; + if (constrains(bValue)) { + m_range[bValue].expand(rhs.range()[bValue].min() - lEnv, + rhs.range()[bValue].max() + hEnv); + } else { + m_range[bValue].shrink(rhs.range()[bValue].min() - lEnv, + rhs.range()[bValue].max() + hEnv); + } + m_constrains.set(bValue); + } else if (rhs.envelope()[bValue] != zeroEnvelope) { + // Only an envelope given, but value is not contraint -> apply envelope + m_range[bValue].expand(m_range[bValue].min() - rhs.envelope()[bValue][0], + m_range[bValue].max() + rhs.envelope()[bValue][1]); + m_constrains.set(bValue); + } + } +} + +void Acts::Extent::set(BinningValue bValue, ActsScalar min, ActsScalar max) { + ActsScalar minval = min; + if (bValue == binR and minval < 0.) { + minval = 0.; + } + m_range[bValue] = Range1D{minval, max}; + m_constrains.set(bValue); +} + +void Acts::Extent::setEnvelope(const ExtentEnvelope& envelope) { + m_envelope = envelope; +} + +bool Acts::Extent::contains(const Extent& rhs, BinningValue bValue) const { + // Helper to check including a constraint bit set check + auto checkContainment = [&](BinningValue bvc) -> bool { + if (not constrains(bvc)) { + return true; + } + return (rhs.range()[bvc] <= m_range[bvc]); + }; + + // Check all + if (bValue == binValues) { + for (int ibv = 0; ibv < (int)binValues; ++ibv) { + if (not checkContainment((BinningValue)ibv)) { + return false; + } + } + return true; + } + // Check specific + return checkContainment(bValue); +} + +bool Acts::Extent::intersects(const Extent& rhs, BinningValue bValue) const { + // Helper to check including a constraint bit set check + auto checkIntersect = [&](BinningValue bvc) -> bool { + if (not constrains(bvc) or not rhs.constrains(bvc)) { + return false; + } + return (m_range[bvc] && rhs.range()[bvc]); + }; + + // Check all + if (bValue == binValues) { + for (int ibv = 0; ibv < (int)binValues; ++ibv) { + if (checkIntersect((BinningValue)ibv)) { + return true; + } + } + return false; + } + // Check specific + return checkIntersect(bValue); +} + +bool Acts::Extent::constrains(BinningValue bValue) const { + if (bValue == binValues) { + return (m_constrains.count() > 0); + } + return m_constrains.test(size_t(bValue)); +} std::ostream& Acts::Extent::toStream(std::ostream& sl) const { sl << "Extent in space : " << std::endl; for (size_t ib = 0; ib < static_cast(binValues); ++ib) { - sl << " - value :" << std::setw(10) << binningValueNames()[ib] - << " | range = [" << ranges[ib].first << ", " << ranges[ib].second << "]" - << std::endl; + if (constrains((BinningValue)ib)) { + sl << " - value :" << std::setw(10) << binningValueNames()[ib] + << " | range = [" << m_range[ib].min() << ", " << m_range[ib].max() + << "]" << std::endl; + } } return sl; } // Overload of << operator for std::ostream for debug output -std::ostream& Acts::operator<<(std::ostream& sl, const Extent& ext) { - return ext.toStream(sl); -} \ No newline at end of file +std::ostream& Acts::operator<<(std::ostream& sl, const Extent& rhs) { + return rhs.toStream(sl); +} diff --git a/Core/src/Geometry/Polyhedron.cpp b/Core/src/Geometry/Polyhedron.cpp index 85718d93e8d..ba645876bde 100644 --- a/Core/src/Geometry/Polyhedron.cpp +++ b/Core/src/Geometry/Polyhedron.cpp @@ -44,7 +44,7 @@ Acts::Extent Acts::Polyhedron::extent(const Transform3& transform) const { auto vtxs = vertices; std::transform(vtxs.begin(), vtxs.end(), vtxs.begin(), [&](auto& v) { auto vt = (transform * v); - extent.check(vt); + extent.extend(vt); return (vt); }); @@ -59,9 +59,8 @@ Acts::Extent Acts::Polyhedron::extent(const Transform3& transform) const { tface.push_back(vtxs[f]); } if (detail::VerticesHelper::isInsidePolygon(origin, tface)) { - extent.ranges[binR].first = 0.; - extent.ranges[binPhi].first = -M_PI; - extent.ranges[binPhi].second = M_PI; + extent.range(binR).setMin(0.); + extent.range(binPhi).set(-M_PI, M_PI); break; } } @@ -90,7 +89,7 @@ Acts::Extent Acts::Polyhedron::extent(const Transform3& transform) const { for (size_t iv = 1; iv < vtxs.size() + 1; ++iv) { size_t fpoint = iv < vtxs.size() ? iv : 0; double testR = radialDistance(vtxs[fpoint], vtxs[iv - 1]); - extent.ranges[binR].first = std::min(extent.ranges[binR].first, testR); + extent.range(binR).expandMin(testR); } } } diff --git a/Core/src/Geometry/ProtoLayerHelper.cpp b/Core/src/Geometry/ProtoLayerHelper.cpp index ead85712eb6..427045aa416 100644 --- a/Core/src/Geometry/ProtoLayerHelper.cpp +++ b/Core/src/Geometry/ProtoLayerHelper.cpp @@ -29,7 +29,7 @@ std::vector Acts::ProtoLayerHelper::protoLayers( /// @return the referece of the SurfaceCluster for insertion auto findCluster = [&](const Extent& extent) -> SurfaceCluster& { for (auto& cluster : clusteredSurfaces) { - if (cluster.first.intersects(extent, sorting.first, sorting.second)) { + if (cluster.first.intersects(extent, sorting.first)) { return cluster; } } @@ -41,16 +41,16 @@ std::vector Acts::ProtoLayerHelper::protoLayers( // Loop over surfaces and sort into clusters for (auto& sf : surfaces) { auto sfExtent = sf->polyhedronRepresentation(gctx, 1).extent(); + sfExtent.envelope()[sorting.first] = {sorting.second, sorting.second}; auto& sfCluster = findCluster(sfExtent); sfCluster.first.extend(sfExtent); sfCluster.second.push_back(sf); } - // Loop over clusters and create ProtoLayer protoLayers.reserve(clusteredSurfaces.size()); for (auto& clusters : clusteredSurfaces) { - ACTS_VERBOSE("Creatingg ProtoLayer with " << clusters.second.size() - << " surfaces."); + ACTS_VERBOSE("Creating ProtoLayer with " << clusters.second.size() + << " surfaces."); protoLayers.push_back(ProtoLayer(gctx, clusters.second)); } return protoLayers; diff --git a/Examples/Algorithms/TrackFinding/src/SeedingAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/SeedingAlgorithm.cpp index c97acefa436..514533f3989 100644 --- a/Examples/Algorithms/TrackFinding/src/SeedingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/SeedingAlgorithm.cpp @@ -163,7 +163,7 @@ ActsExamples::ProcessCode ActsExamples::SeedingAlgorithm::execute( // stable and we do not need to create local copies. spacePointPtrs.push_back(&spacePoint); // store x,y,z values in extent - rRangeSPExtent.check({spacePoint.x(), spacePoint.y(), spacePoint.z()}); + rRangeSPExtent.extend({spacePoint.x(), spacePoint.y(), spacePoint.z()}); } } diff --git a/Plugins/DD4hep/src/DD4hepLayerBuilder.cpp b/Plugins/DD4hep/src/DD4hepLayerBuilder.cpp index 6415e81de45..354a46c3ff3 100644 --- a/Plugins/DD4hep/src/DD4hepLayerBuilder.cpp +++ b/Plugins/DD4hep/src/DD4hepLayerBuilder.cpp @@ -137,8 +137,8 @@ const Acts::LayerVector Acts::DD4hepLayerBuilder::endcapLayers( // manually create a proto layer double eiz = (z != 0.) ? z - m_cfg.defaultThickness : 0.; double eoz = (z != 0.) ? z + m_cfg.defaultThickness : 0.; - pl.extent.ranges[Acts::binZ] = {eiz, eoz}; - pl.extent.ranges[Acts::binR] = {rMin, rMax}; + pl.extent.range(Acts::binZ).set(eiz, eoz); + pl.extent.range(Acts::binR).set(rMin, rMax); pl.envelope[Acts::binR] = {0., 0.}; pl.envelope[Acts::binZ] = {0., 0.}; } else { @@ -150,7 +150,7 @@ const Acts::LayerVector Acts::DD4hepLayerBuilder::endcapLayers( std::abs(zMax - pl.max(Acts::binZ))}; pl.envelope[Acts::binR] = {std::abs(rMin - pl.min(Acts::binR)), std::abs(rMax - pl.max(Acts::binR))}; - pl.extent.ranges[Acts::binR] = {rMin, rMax}; + pl.extent.range(Acts::binR).set(rMin, rMax); } } else { throw std::logic_error( @@ -294,8 +294,8 @@ const Acts::LayerVector Acts::DD4hepLayerBuilder::centralLayers( // manually create a proto layer double eir = (r != 0.) ? r - m_cfg.defaultThickness : 0.; double eor = (r != 0.) ? r + m_cfg.defaultThickness : 0.; - pl.extent.ranges[Acts::binR] = {eir, eor}; - pl.extent.ranges[Acts::binZ] = {-dz, dz}; + pl.extent.range(Acts::binR).set(eir, eor); + pl.extent.range(Acts::binZ).set(-dz, dz); pl.envelope[Acts::binR] = {0., 0.}; pl.envelope[Acts::binZ] = {0., 0.}; } else { diff --git a/Tests/UnitTests/Core/Geometry/ExtentTests.cpp b/Tests/UnitTests/Core/Geometry/ExtentTests.cpp index f18a121ea3b..c129f5c9a0f 100644 --- a/Tests/UnitTests/Core/Geometry/ExtentTests.cpp +++ b/Tests/UnitTests/Core/Geometry/ExtentTests.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2017-2018 CERN for the benefit of the Acts project +// Copyright (C) 2022 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -23,7 +23,7 @@ using namespace UnitLiterals; namespace Test { -BOOST_AUTO_TEST_SUITE(Geometry) +BOOST_AUTO_TEST_SUITE(Core) /// Unit tests for Polyderon construction & operator += BOOST_AUTO_TEST_CASE(ExtentTest) { @@ -32,10 +32,10 @@ BOOST_AUTO_TEST_CASE(ExtentTest) { Vector3(15_mm, 3_mm, -10_mm), Vector3(15_mm, -3_mm, 10_mm), Vector3(18_mm, 0_mm, 10_mm), Vector3(15_mm, 3_mm, 10_mm)}; - // Create an Extent + // Create an Extent / without envelope Extent gExt; for (const auto& v : vertices) { - gExt.check(v); + gExt.extend(v); } double phiMin = std::atan2(-3_mm, 15_mm); @@ -53,48 +53,89 @@ BOOST_AUTO_TEST_CASE(ExtentTest) { CHECK_CLOSE_ABS(gExt.min(binPhi), phiMin, 1e-6); CHECK_CLOSE_ABS(gExt.max(binPhi), phiMax, 1e-6); + // Call with histogram filling + Extent gExtHist; + for (const auto& v : vertices) { + gExtHist.extend(v, {binX}, false, true); + } + const auto& vHist = gExtHist.valueHistograms(); + auto xVals = vHist[binX]; + + BOOST_CHECK(xVals.size() == 6u); + std::vector reference = {15_mm, 18_mm, 15_mm, + 15_mm, 18_mm, 15_mm}; + BOOST_CHECK(xVals == reference); + + // Call with ieterator range + Extent gExtItr; + gExtItr.extend(vertices.begin(), vertices.end()); + CHECK_CLOSE_ABS(gExtItr.min(binX), 15_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.max(binX), 18_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.min(binY), -3_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.max(binY), 3_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.min(binZ), -10_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.max(binZ), 10_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.min(binR), rMin, 1e-6); + CHECK_CLOSE_ABS(gExtItr.max(binR), 18_mm, 1e-6); + CHECK_CLOSE_ABS(gExtItr.min(binPhi), phiMin, 1e-6); + CHECK_CLOSE_ABS(gExtItr.max(binPhi), phiMax, 1e-6); + // Create a second Extent - Extent otherExt; - otherExt.extend(gExt); - - CHECK_CLOSE_ABS(otherExt.min(binX), 15_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.max(binX), 18_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.min(binY), -3_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.max(binY), 3_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.min(binZ), -10_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.max(binZ), 10_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.min(binR), rMin, 1e-6); - CHECK_CLOSE_ABS(otherExt.max(binR), 18_mm, 1e-6); - CHECK_CLOSE_ABS(otherExt.min(binPhi), phiMin, 1e-6); - CHECK_CLOSE_ABS(otherExt.max(binPhi), phiMax, 1e-6); -} + Extent gExtCopy; + gExtCopy.extend(gExt); + + CHECK_CLOSE_ABS(gExtCopy.min(binX), 15_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.max(binX), 18_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.min(binY), -3_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.max(binY), 3_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.min(binZ), -10_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.max(binZ), 10_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.min(binR), rMin, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.max(binR), 18_mm, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.min(binPhi), phiMin, 1e-6); + CHECK_CLOSE_ABS(gExtCopy.max(binPhi), phiMax, 1e-6); + + // Check containment + Extent unbound; + BOOST_CHECK(unbound.contains(gExt)); + BOOST_CHECK(unbound.contains(gExtCopy)); + + // Check application of an envelope on it + ExtentEnvelope xEnvelopes = zeroEnvelopes; + xEnvelopes[binX] = {1., 2.}; + + // Take the extent and extend by an envelope + Extent envelope(xEnvelopes); + gExt.extend(envelope); + // Changed ones + CHECK_CLOSE_ABS(gExt.min(binX), 14_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binX), 20_mm, 1e-6); + // Unchanged ones + CHECK_CLOSE_ABS(gExt.min(binY), -3_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binY), 3_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.min(binZ), -10_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binZ), 10_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.min(binR), rMin, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binR), 18_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.min(binPhi), phiMin, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binPhi), phiMax, 1e-6); -BOOST_AUTO_TEST_CASE(ExtentTestIntersects) { - Extent aExtent; - aExtent.ranges = {{1, 2}, {2, 3}, {4, 5}, {2., sqrt(5.)}, {-0.1, 1.4}, - {-4., 4.}, {0., 0.}, {1., 2.}, {0., sqrt(9.)}}; - - Extent bExtent; - bExtent.ranges = {{-2, -1}, {1, 2.5}, {6, 8}, - {0., sqrt(12.)}, {-0.1, 1.4}, {-2., 2.}, - {0., 0.}, {-2., 0.}, {0., sqrt(9.)}}; - - // They certainly intersect - BOOST_CHECK(aExtent.intersects(bExtent)); - // They do not intersect in x - BOOST_CHECK(!aExtent.intersects(bExtent, binX)); - // They do with a large tolerance though in x - BOOST_CHECK(aExtent.intersects(bExtent, binX, 3.)); - // They do intersect in y - BOOST_CHECK(aExtent.intersects(bExtent, binY)); - // They do not intersect in z - BOOST_CHECK(!aExtent.intersects(bExtent, binZ)); - // They do intersect in r - BOOST_CHECK(aExtent.intersects(bExtent, binR)); - // They do not intersect in eta - BOOST_CHECK(!aExtent.intersects(bExtent, binEta)); - // They do intersect with tolerance in eta - BOOST_CHECK(aExtent.intersects(bExtent, binEta, 3.)); + // Fill it with envelope + Extent gExtEnv(envelope); + gExtEnv.extend(vertices.begin(), vertices.end()); + // Changed ones + CHECK_CLOSE_ABS(gExtEnv.min(binX), 14_mm, 1e-6); + CHECK_CLOSE_ABS(gExtEnv.max(binX), 20_mm, 1e-6); + + // Check the set method + gExt.set(binX, 2_mm, 8_mm); + CHECK_CLOSE_ABS(gExt.min(binX), 2_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binX), 8_mm, 1e-6); + + // Radius can not go below 0 + gExt.set(binR, -2_mm, 18_mm); + CHECK_CLOSE_ABS(gExt.min(binR), 0_mm, 1e-6); + CHECK_CLOSE_ABS(gExt.max(binR), 18_mm, 1e-6); } BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/Geometry/LayerCreatorTests.cpp b/Tests/UnitTests/Core/Geometry/LayerCreatorTests.cpp index 8b80907c420..5d5410db7da 100644 --- a/Tests/UnitTests/Core/Geometry/LayerCreatorTests.cpp +++ b/Tests/UnitTests/Core/Geometry/LayerCreatorTests.cpp @@ -297,8 +297,8 @@ BOOST_FIXTURE_TEST_CASE(LayerCreator_createCylinderLayer, LayerCreatorFixture) { // CASE III ProtoLayer pl3; - pl3.extent.ranges[Acts::binR] = {1, 20}; - pl3.extent.ranges[Acts::binZ] = {-25, 25}; + pl3.extent.range(Acts::binR).set(1, 20); + pl3.extent.range(Acts::binZ).set(-25, 25); layer = std::dynamic_pointer_cast( p_LC->cylinderLayer(tgContext, srf, equidistant, equidistant, pl3)); CHECK_CLOSE_REL(layer->thickness(), 19, 1e-3); @@ -331,8 +331,8 @@ BOOST_FIXTURE_TEST_CASE(LayerCreator_createDiscLayer, LayerCreatorFixture) { draw_surfaces(surfaces, "LayerCreator_createDiscLayer_EC_1.obj"); ProtoLayer pl(tgContext, surfaces); - pl.extent.ranges[binZ] = {-10, 10}; - pl.extent.ranges[binR] = {5., 25.}; + pl.extent.range(binZ).set(-10, 10); + pl.extent.range(binR).set(5., 25.); std::shared_ptr layer = std::dynamic_pointer_cast( p_LC->discLayer(tgContext, surfaces, equidistant, equidistant, pl)); CHECK_CLOSE_REL(layer->thickness(), 20, 1e-3); diff --git a/Tests/UnitTests/Core/Geometry/ProtoLayerTests.cpp b/Tests/UnitTests/Core/Geometry/ProtoLayerTests.cpp index 1fa0784a178..4f380ae23e3 100644 --- a/Tests/UnitTests/Core/Geometry/ProtoLayerTests.cpp +++ b/Tests/UnitTests/Core/Geometry/ProtoLayerTests.cpp @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(ProtoLayerTests) { auto pLayerSf = createProtoLayer(Transform3::Identity()); auto pLayerSfShared = createProtoLayer(Transform3::Identity()); - BOOST_CHECK(pLayerSf.extent.ranges == pLayerSfShared.extent.ranges); + BOOST_CHECK(pLayerSf.extent.range() == pLayerSfShared.extent.range()); BOOST_CHECK(pLayerSf.envelope == pLayerSfShared.envelope); // CHECK That you have 4 surfaces @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(ProtoLayerTests) { BOOST_CHECK(pLayerSf.surfaces().size() == 5); // That should invalidate the ranges - BOOST_CHECK(pLayerSf.extent.ranges != pLayerSfShared.extent.ranges); + BOOST_CHECK(!(pLayerSf.extent.range() == pLayerSfShared.extent.range())); // Test 1 - identity transform auto protoLayer = createProtoLayer(Transform3::Identity()); diff --git a/Tests/UnitTests/Core/Surfaces/CylinderSurfaceTests.cpp b/Tests/UnitTests/Core/Surfaces/CylinderSurfaceTests.cpp index d9bfe512fc8..b043b598ced 100644 --- a/Tests/UnitTests/Core/Surfaces/CylinderSurfaceTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/CylinderSurfaceTests.cpp @@ -296,14 +296,14 @@ BOOST_AUTO_TEST_CASE(CylinderSurfaceBinningPosition) { exp = trf * exp; Vector3 bp = cylinder->binningPosition(testContext, binR); - BOOST_CHECK_EQUAL(bp, exp); - BOOST_CHECK_EQUAL(cylinder->binningPositionValue(testContext, binR), - VectorHelpers::perp(exp)); + CHECK_CLOSE_ABS(bp, exp, 1e-10); + CHECK_CLOSE_ABS(cylinder->binningPositionValue(testContext, binR), + VectorHelpers::perp(exp), 1e-10); bp = cylinder->binningPosition(testContext, binRPhi); - BOOST_CHECK_EQUAL(bp, exp); - BOOST_CHECK_EQUAL(cylinder->binningPositionValue(testContext, binRPhi), - VectorHelpers::phi(exp) * VectorHelpers::perp(exp)); + CHECK_CLOSE_ABS(bp, exp, 1e-10); + CHECK_CLOSE_ABS(cylinder->binningPositionValue(testContext, binRPhi), + VectorHelpers::phi(exp) * VectorHelpers::perp(exp), 1e-10); for (auto b : {binX, binY, binZ, binEta, binH, binMag}) { BOOST_TEST_CONTEXT("binValue: " << b) { diff --git a/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp b/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp index f8b37bcb7c3..01d2d9f085b 100644 --- a/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp @@ -91,14 +91,14 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { // Check the extent in space double r = hzpos * std::tan(alpha); auto extent = oneConePh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0_mm, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0_mm, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hzpos, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0_mm, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0_mm, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hzpos, 1e-6); /// The full cone on one side auto conePiece = std::make_shared(alpha, hzpmin, hzpos); @@ -109,14 +109,14 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { // Check the extent in space double rmin = hzpmin * std::tan(alpha); extent = oneConePiecePh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, rmin, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, hzpmin, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hzpos, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() rmin, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() hzpmin, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hzpos, 1e-6); // The full cone on both sides auto coneBoth = std::make_shared(alpha, hzneg, hzpos); @@ -126,14 +126,14 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { BOOST_CHECK_EQUAL(twoConesPh.faces.size(), expectedFaces); BOOST_CHECK_EQUAL(twoConesPh.vertices.size(), expectedFaces + 1); extent = twoConesPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0_mm, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, hzneg, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hzpos, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0_mm, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() hzneg, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hzpos, 1e-6); // A centered sectoral cone on both sides auto sectoralBoth = @@ -143,11 +143,11 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { auto sectoralConesPh = sectoralCones->polyhedronRepresentation(tgContext, segments); extent = sectoralConesPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0_mm, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, hzneg, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hzpos, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0_mm, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() hzneg, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hzpos, 1e-6); } } @@ -178,14 +178,14 @@ BOOST_AUTO_TEST_CASE(CylinderSurfacePolyhedrons) { BOOST_CHECK_EQUAL(fullCylinderPh.vertices.size(), expectedVertices); // Check the extent in space auto extent = fullCylinderPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, -hZ, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() -hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hZ, 1e-6); /// The full cone on one side auto sectorCentered = std::make_shared(r, phiSector, hZ); @@ -196,14 +196,14 @@ BOOST_AUTO_TEST_CASE(CylinderSurfacePolyhedrons) { // Check the extent in space extent = centerSectoredCylinderPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, r * std::cos(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -r * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, r * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, -hZ, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() r * std::cos(phiSector), 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -r * std::sin(phiSector), 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() r * std::sin(phiSector), 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() -hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hZ, 1e-6); /// The full cone on one side auto sectorShifted = @@ -215,10 +215,10 @@ BOOST_AUTO_TEST_CASE(CylinderSurfacePolyhedrons) { // Check the extent in space extent = shiftedSectoredCylinderPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binR].first, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, r, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, -hZ, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() r, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() -hZ, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() hZ, 1e-6); } } @@ -262,44 +262,44 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { BOOST_CHECK_EQUAL(fullDiscPh.vertices.size(), expectedVertices); auto extent = fullDiscPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); // Ring disc auto radial = std::make_shared(innerR, outerR); auto radialDisc = Surface::makeShared(transform, radial); auto radialPh = radialDisc->polyhedronRepresentation(tgContext, segments); extent = radialPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, innerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() innerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); // Sectoral disc - around 0. auto sector = std::make_shared(0., outerR, phiSector); auto sectorDisc = Surface::makeShared(transform, sector); auto sectorPh = sectorDisc->polyhedronRepresentation(tgContext, segments); extent = sectorPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -outerR * std::sin(phiSector), + CHECK_CLOSE_ABS((extent.range(binX).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -outerR * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, outerR * std::sin(phiSector), + CHECK_CLOSE_ABS((extent.range(binY).max() outerR * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); // Sectoral ring - around 0. auto sectorRing = std::make_shared(innerR, outerR, phiSector); @@ -308,17 +308,17 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { auto sectorRingDiscPh = sectorRingDisc->polyhedronRepresentation(tgContext, segments); extent = sectorRingDiscPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, innerR * std::cos(phiSector), + CHECK_CLOSE_ABS((extent.range(binX).min() innerR * std::cos(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -outerR * std::sin(phiSector), + CHECK_CLOSE_ABS((extent.range(binX).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -outerR * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, outerR * std::sin(phiSector), + CHECK_CLOSE_ABS((extent.range(binY).max() outerR * std::sin(phiSector), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, innerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() innerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); // Sectoral disc - shifted auto sectorRingShifted = @@ -328,10 +328,10 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { auto sectorRingDiscShiftedPh = sectorRingDiscShifted->polyhedronRepresentation(tgContext, segments); extent = sectorRingDiscShiftedPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binR].first, innerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() innerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); // Trapezoid for a disc double halfXmin = 10_mm; @@ -343,10 +343,10 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { auto trapezoidDiscSfPh = trapezoidDiscSf->polyhedronRepresentation(tgContext, segments); extent = trapezoidDiscSfPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binR].first, innerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() innerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); auto trapezoidDiscShifted = std::make_shared( halfXmin, halfXmax, innerR, outerR, averagePhi); @@ -355,10 +355,10 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { auto trapezoidDiscShiftedSfPh = trapezoidDiscShiftedSf->polyhedronRepresentation(tgContext, segments); extent = trapezoidDiscShiftedSfPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binR].first, innerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, outerR, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() innerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() outerR, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); double minRadius = 7.; double maxRadius = 12.; @@ -391,10 +391,10 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { auto shiftedPh = shiftedPlane->polyhedronRepresentation(tgContext, 1); auto shiftedExtent = shiftedPh.extent(); // Let's check the extent - CHECK_CLOSE_ABS(shiftedExtent.ranges[binX].first, -rhX, 1e-6); - CHECK_CLOSE_ABS(shiftedExtent.ranges[binX].second, rhX, 1e-6); - CHECK_CLOSE_ABS(shiftedExtent.ranges[binY].first, -rhY + shiftY, 1e-6); - CHECK_CLOSE_ABS(shiftedExtent.ranges[binY].second, rhY + shiftY, 1e-6); + CHECK_CLOSE_ABS(shifted(extent.range(binX).min() -rhX, 1e-6); + CHECK_CLOSE_ABS(shifted(extent.range(binX).max() rhX, 1e-6); + CHECK_CLOSE_ABS(shifted(extent.range(binY).min() -rhY + shiftY, 1e-6); + CHECK_CLOSE_ABS(shifted(extent.range(binY).max() rhY + shiftY, 1e-6); for (const auto& mode : testModes) { unsigned int segments = std::get(mode); @@ -407,15 +407,15 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { auto rectangularPh = rectangularPlane->polyhedronRepresentation(tgContext, segments); auto extent = rectangularPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -rhX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, rhX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -rhY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, rhY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, + CHECK_CLOSE_ABS((extent.range(binX).min() -rhX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() rhX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -rhY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() rhY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() std::sqrt(rhX * rhX + rhY * rhY), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); BOOST_CHECK(rectangularPh.vertices.size() == 4); BOOST_CHECK(rectangularPh.faces.size() == 1); std::vector expectedRect = {0, 1, 2, 3}; @@ -434,15 +434,15 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { extent = trapezoidalPh.extent(); double thX = std::max(thX1, thX2); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -thX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, thX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -thY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, thY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, + CHECK_CLOSE_ABS((extent.range(binX).min() -thX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() thX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -thY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() thY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() std::sqrt(thX * thX + thY * thY), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); BOOST_CHECK(trapezoidalPh.vertices.size() == 4); BOOST_CHECK(trapezoidalPh.faces.size() == 1); std::vector expectedTra = {0, 1, 2, 3}; @@ -456,14 +456,14 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { auto ellispoidPh = ellipsoidPlane->polyhedronRepresentation(tgContext, segments); extent = ellispoidPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -rMaxX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, rMaxX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -rMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -rMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, rMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -rMaxX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() rMaxX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); double rMinX = 10_mm; double rMinY = 20_mm; @@ -475,13 +475,14 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { ellipsoidRingPlane->polyhedronRepresentation(tgContext, segments); extent = ellispoidPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -rMaxX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, rMaxX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -rMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, rMinX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, rMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).min() -rMaxX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() rMaxX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() rMinX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() rMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); /// ConvextPolygonBounds test std::vector vtxs = { @@ -508,15 +509,15 @@ BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) { BOOST_CHECK(diamondPh.vertices.size() == 6); BOOST_CHECK(diamondPh.faces.size() == 1); extent = diamondPh.extent(); - CHECK_CLOSE_ABS(extent.ranges[binX].first, -hMedX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binX].second, hMedX, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].first, -hMinY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binY].second, hMaxY, 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binR].second, + CHECK_CLOSE_ABS((extent.range(binX).min() -hMedX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binX).max() hMedX, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).min() -hMinY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binY).max() hMaxY, 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binR).max() std::sqrt(hMaxX * hMaxX + hMaxY * hMaxY), 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].first, 0., 1e-6); - CHECK_CLOSE_ABS(extent.ranges[binZ].second, 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).min() 0., 1e-6); + CHECK_CLOSE_ABS((extent.range(binZ).max() 0., 1e-6); } }