Skip to content

Commit

Permalink
refactor!: Explicit BoundaryTolerance constructors (#3974)
Browse files Browse the repository at this point in the history
This PR makes the `BoundaryTolerance` constructors explicit. The API is largely preserved through factory functions with the original names of the boundary tolerance implementation structs that were previously auto-convertible.
  • Loading branch information
paulgessinger authored Jan 17, 2025
1 parent d26fce2 commit a3976a1
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 120 deletions.
101 changes: 56 additions & 45 deletions Core/include/Acts/Surfaces/BoundaryTolerance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,16 @@ namespace Acts {
///
class BoundaryTolerance {
public:
/// Infinite tolerance i.e. no boundary check
struct Infinite {};
struct InfiniteParams {};

/// No tolerance i.e. exact boundary check
struct None {};
struct NoneParams {};

/// Absolute tolerance in bound coordinates
struct AbsoluteBound {
struct AbsoluteBoundParams {
double tolerance0{};
double tolerance1{};

AbsoluteBound() = default;
AbsoluteBound(double tolerance0_, double tolerance1_)
AbsoluteBoundParams() = default;
AbsoluteBoundParams(double tolerance0_, double tolerance1_)
: tolerance0(tolerance0_), tolerance1(tolerance1_) {
if (tolerance0 < 0 || tolerance1 < 0) {
throw std::invalid_argument(
Expand All @@ -75,13 +72,12 @@ class BoundaryTolerance {
}
};

/// Absolute tolerance in Cartesian coordinates
struct AbsoluteCartesian {
struct AbsoluteCartesianParams {
double tolerance0{};
double tolerance1{};

AbsoluteCartesian() = default;
AbsoluteCartesian(double tolerance0_, double tolerance1_)
AbsoluteCartesianParams() = default;
AbsoluteCartesianParams(double tolerance0_, double tolerance1_)
: tolerance0(tolerance0_), tolerance1(tolerance1_) {
if (tolerance0 < 0 || tolerance1 < 0) {
throw std::invalid_argument(
Expand All @@ -94,50 +90,65 @@ class BoundaryTolerance {
}
};

/// Absolute tolerance in Euclidean distance
struct AbsoluteEuclidean {
struct AbsoluteEuclideanParams {
double tolerance{};

AbsoluteEuclidean() = default;
explicit AbsoluteEuclidean(double tolerance_) : tolerance(tolerance_) {}
AbsoluteEuclideanParams() = default;
explicit AbsoluteEuclideanParams(double tolerance_)
: tolerance(tolerance_) {}
};

/// Chi2 tolerance in bound coordinates
struct Chi2Bound {
struct Chi2BoundParams {
double maxChi2{};
SquareMatrix2 weight = SquareMatrix2::Identity();

Chi2Bound() = default;
Chi2Bound(const SquareMatrix2& weight_, double maxChi2_)
Chi2BoundParams() = default;
Chi2BoundParams(const SquareMatrix2& weight_, double maxChi2_)
: maxChi2(maxChi2_), weight(weight_) {}
};

private:
/// Underlying variant type
using Variant = std::variant<InfiniteParams, NoneParams, AbsoluteBoundParams,
AbsoluteCartesianParams, AbsoluteEuclideanParams,
Chi2BoundParams>;

/// Construct from variant
explicit BoundaryTolerance(Variant variant);

public:
/// Infinite tolerance i.e. no boundary check
static auto Infinite() { return BoundaryTolerance{InfiniteParams{}}; }

/// No tolerance i.e. exact boundary check
static auto None() { return BoundaryTolerance{NoneParams{}}; }

/// Absolute tolerance in bound coordinates
static auto AbsoluteBound(double tolerance0, double tolerance1) {
return BoundaryTolerance{AbsoluteBoundParams{tolerance0, tolerance1}};
}

/// Absolute tolerance in Cartesian coordinates
static auto AbsoluteCartesian(double tolerance0, double tolerance1) {
return BoundaryTolerance{AbsoluteCartesianParams{tolerance0, tolerance1}};
}

/// Absolute tolerance in Euclidean distance
static auto AbsoluteEuclidean(double tolerance) {
return BoundaryTolerance{AbsoluteEuclideanParams{tolerance}};
}

/// Chi2 tolerance in bound coordinates
static auto Chi2Bound(const SquareMatrix2& weight, double maxChi2) {
return BoundaryTolerance{Chi2BoundParams{weight, maxChi2}};
}

enum class ToleranceMode {
Extend, // Extend the boundary
None, // No tolerance
Shrink // Shrink the boundary
};

/// Underlying variant type
using Variant = std::variant<Infinite, None, AbsoluteBound, AbsoluteCartesian,
AbsoluteEuclidean, Chi2Bound>;

/// Construct with infinite tolerance.
BoundaryTolerance(const Infinite& infinite);
/// Construct with no tolerance.
BoundaryTolerance(const None& none);
/// Construct with absolute tolerance in bound coordinates.
BoundaryTolerance(const AbsoluteBound& AbsoluteBound);
/// Construct with absolute tolerance in Cartesian coordinates.
BoundaryTolerance(const AbsoluteCartesian& absoluteCartesian);
/// Construct with absolute tolerance in Euclidean distance.
BoundaryTolerance(const AbsoluteEuclidean& absoluteEuclidean);
/// Construct with chi2 tolerance in bound coordinates.
BoundaryTolerance(const Chi2Bound& Chi2Bound);

/// Construct from variant
BoundaryTolerance(Variant variant);

/// Check if the tolerance is infinite.
bool isInfinite() const;
/// Check if the is no tolerance.
Expand All @@ -155,16 +166,16 @@ class BoundaryTolerance {
ToleranceMode toleranceMode() const;

/// Get the tolerance as absolute bound.
AbsoluteBound asAbsoluteBound(bool isCartesian = false) const;
AbsoluteBoundParams asAbsoluteBound(bool isCartesian = false) const;
/// Get the tolerance as absolute Cartesian.
const AbsoluteCartesian& asAbsoluteCartesian() const;
const AbsoluteCartesianParams& asAbsoluteCartesian() const;
/// Get the tolerance as absolute Euclidean.
const AbsoluteEuclidean& asAbsoluteEuclidean() const;
const AbsoluteEuclideanParams& asAbsoluteEuclidean() const;
/// Get the tolerance as chi2 bound.
const Chi2Bound& asChi2Bound() const;
const Chi2BoundParams& asChi2Bound() const;

/// Get the tolerance as absolute bound if possible.
std::optional<AbsoluteBound> asAbsoluteBoundOpt(
std::optional<AbsoluteBoundParams> asAbsoluteBoundOpt(
bool isCartesian = false) const;

/// Check if the distance is tolerated.
Expand Down
2 changes: 1 addition & 1 deletion Core/src/Geometry/TrapezoidVolumeBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ bool TrapezoidVolumeBounds::inside(const Vector3& pos, double tol) const {
}
Vector2 locp(pos.x(), pos.y());
bool inside(m_faceXYTrapezoidBounds->inside(
locp, BoundaryTolerance::AbsoluteBound{tol, tol}));
locp, BoundaryTolerance::AbsoluteBound(tol, tol)));
return inside;
}

Expand Down
75 changes: 30 additions & 45 deletions Core/src/Surfaces/BoundaryTolerance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,32 @@

namespace Acts {

BoundaryTolerance::BoundaryTolerance(const Infinite& infinite)
: m_variant{infinite} {}

BoundaryTolerance::BoundaryTolerance(const None& none) : m_variant{none} {}

BoundaryTolerance::BoundaryTolerance(const AbsoluteBound& absoluteBound)
: m_variant{absoluteBound} {}

BoundaryTolerance::BoundaryTolerance(const AbsoluteCartesian& absoluteCartesian)
: m_variant{absoluteCartesian} {}

BoundaryTolerance::BoundaryTolerance(const AbsoluteEuclidean& absoluteEuclidean)
: m_variant{absoluteEuclidean} {}

BoundaryTolerance::BoundaryTolerance(const Chi2Bound& chi2Bound)
: m_variant{chi2Bound} {}

BoundaryTolerance::BoundaryTolerance(Variant variant)
: m_variant{std::move(variant)} {}

bool BoundaryTolerance::isInfinite() const {
return holdsVariant<Infinite>();
return holdsVariant<InfiniteParams>();
}

bool BoundaryTolerance::isNone() const {
return holdsVariant<None>();
return holdsVariant<NoneParams>();
}

bool BoundaryTolerance::hasAbsoluteBound(bool isCartesian) const {
return holdsVariant<None>() || holdsVariant<AbsoluteBound>() ||
(isCartesian && holdsVariant<AbsoluteCartesian>());
return holdsVariant<NoneParams>() || holdsVariant<AbsoluteBoundParams>() ||
(isCartesian && holdsVariant<AbsoluteCartesianParams>());
}

bool BoundaryTolerance::hasAbsoluteCartesian() const {
return holdsVariant<AbsoluteCartesian>();
return holdsVariant<AbsoluteCartesianParams>();
}

bool BoundaryTolerance::hasAbsoluteEuclidean() const {
return holdsVariant<AbsoluteEuclidean>();
return holdsVariant<AbsoluteEuclideanParams>();
}

bool BoundaryTolerance::hasChi2Bound() const {
return holdsVariant<Chi2Bound>();
return holdsVariant<Chi2BoundParams>();
}

BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
Expand All @@ -70,7 +53,7 @@ BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
return None;
}

if (const auto* absoluteBound = getVariantPtr<AbsoluteBound>();
if (const auto* absoluteBound = getVariantPtr<AbsoluteBoundParams>();
absoluteBound != nullptr) {
if (absoluteBound->tolerance0 == 0. && absoluteBound->tolerance1 == 0.) {
return None;
Expand All @@ -79,7 +62,7 @@ BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
return Extend;
}

if (const auto* absoluteCartesian = getVariantPtr<AbsoluteCartesian>();
if (const auto* absoluteCartesian = getVariantPtr<AbsoluteCartesianParams>();
absoluteCartesian != nullptr) {
if (absoluteCartesian->tolerance0 == 0. &&
absoluteCartesian->tolerance1 == 0.) {
Expand All @@ -89,7 +72,7 @@ BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
return Extend;
}

if (const auto* absoluteEuclidean = getVariantPtr<AbsoluteEuclidean>();
if (const auto* absoluteEuclidean = getVariantPtr<AbsoluteEuclideanParams>();
absoluteEuclidean != nullptr) {
if (absoluteEuclidean->tolerance == 0.) {
return None;
Expand All @@ -100,7 +83,7 @@ BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
}
}

if (const auto* chi2Bound = getVariantPtr<Chi2Bound>();
if (const auto* chi2Bound = getVariantPtr<Chi2BoundParams>();
chi2Bound != nullptr) {
if (chi2Bound->maxChi2 == 0.) {
return None;
Expand All @@ -115,35 +98,36 @@ BoundaryTolerance::ToleranceMode BoundaryTolerance::toleranceMode() const {
return None;
}

BoundaryTolerance::AbsoluteBound BoundaryTolerance::asAbsoluteBound(
BoundaryTolerance::AbsoluteBoundParams BoundaryTolerance::asAbsoluteBound(
bool isCartesian) const {
if (isNone()) {
return AbsoluteBound{0., 0.};
return AbsoluteBoundParams{0., 0.};
}

if (isCartesian && hasAbsoluteCartesian()) {
const auto& cartesian = getVariant<AbsoluteCartesian>();
return AbsoluteBound{cartesian.tolerance0, cartesian.tolerance1};
const auto& cartesian = getVariant<AbsoluteCartesianParams>();
return AbsoluteBoundParams{cartesian.tolerance0, cartesian.tolerance1};
}

return getVariant<AbsoluteBound>();
return getVariant<AbsoluteBoundParams>();
}

const BoundaryTolerance::AbsoluteCartesian&
const BoundaryTolerance::AbsoluteCartesianParams&
BoundaryTolerance::asAbsoluteCartesian() const {
return getVariant<AbsoluteCartesian>();
return getVariant<AbsoluteCartesianParams>();
}

const BoundaryTolerance::AbsoluteEuclidean&
const BoundaryTolerance::AbsoluteEuclideanParams&
BoundaryTolerance::asAbsoluteEuclidean() const {
return getVariant<AbsoluteEuclidean>();
return getVariant<AbsoluteEuclideanParams>();
}

const BoundaryTolerance::Chi2Bound& BoundaryTolerance::asChi2Bound() const {
return getVariant<Chi2Bound>();
const BoundaryTolerance::Chi2BoundParams& BoundaryTolerance::asChi2Bound()
const {
return getVariant<Chi2BoundParams>();
}

std::optional<BoundaryTolerance::AbsoluteBound>
std::optional<BoundaryTolerance::AbsoluteBoundParams>
BoundaryTolerance::asAbsoluteBoundOpt(bool isCartesian) const {
return hasAbsoluteBound(isCartesian)
? std::optional(asAbsoluteBound(isCartesian))
Expand All @@ -161,13 +145,13 @@ bool BoundaryTolerance::isTolerated(
return distance == Vector2::Zero();
}

if (const auto* absoluteBound = getVariantPtr<AbsoluteBound>();
if (const auto* absoluteBound = getVariantPtr<AbsoluteBoundParams>();
absoluteBound != nullptr) {
return std::abs(distance[0]) <= absoluteBound->tolerance0 &&
std::abs(distance[1]) <= absoluteBound->tolerance1;
}

if (const auto* chi2Bound = getVariantPtr<Chi2Bound>();
if (const auto* chi2Bound = getVariantPtr<Chi2BoundParams>();
chi2Bound != nullptr) {
// Mahalanobis distances mean is 2 in 2-dim. cut is 1-d sigma.
double chi2 = distance.transpose() * chi2Bound->weight * distance;
Expand All @@ -187,13 +171,13 @@ bool BoundaryTolerance::isTolerated(
cartesianDistance = jacobian * distance;
}

if (const auto* absoluteCartesian = getVariantPtr<AbsoluteCartesian>();
if (const auto* absoluteCartesian = getVariantPtr<AbsoluteCartesianParams>();
absoluteCartesian != nullptr) {
return std::abs(cartesianDistance[0]) <= absoluteCartesian->tolerance0 &&
std::abs(cartesianDistance[1]) <= absoluteCartesian->tolerance1;
}

if (const auto* absoluteEuclidean = getVariantPtr<AbsoluteEuclidean>();
if (const auto* absoluteEuclidean = getVariantPtr<AbsoluteEuclideanParams>();
absoluteEuclidean != nullptr) {
if (absoluteEuclidean->tolerance < 0) {
return cartesianDistance.norm() > std::abs(absoluteEuclidean->tolerance);
Expand All @@ -214,7 +198,8 @@ SquareMatrix2 BoundaryTolerance::getMetric(
bool isCartesian = !jacobianOpt.has_value();
SquareMatrix2 metric = SquareMatrix2::Identity();

if (const auto* chi2Bound = getVariantPtr<BoundaryTolerance::Chi2Bound>();
if (const auto* chi2Bound =
getVariantPtr<BoundaryTolerance::Chi2BoundParams>();
chi2Bound != nullptr) {
metric = chi2Bound->weight;
} else if (!isCartesian) {
Expand Down
4 changes: 2 additions & 2 deletions Examples/Io/Root/src/RootAthenaDumpReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ RootAthenaDumpReader::readMeasurements(

bool inside =
surface->isOnSurface(gctx, cluster.globalPosition, {},
Acts::BoundaryTolerance::AbsoluteEuclidean{
m_cfg.absBoundaryTolerance},
Acts::BoundaryTolerance::AbsoluteEuclidean(
m_cfg.absBoundaryTolerance),
std::numeric_limits<double>::max());

if (!inside) {
Expand Down
8 changes: 4 additions & 4 deletions Tests/Benchmarks/AnnulusBoundsBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ int main(int /*argc*/, char** /*argv[]*/) {
cov << 1.0, 0, 0, 0.05;

BoundaryTolerance bcAbs = BoundaryTolerance::None();
BoundaryTolerance bcTol0 = BoundaryTolerance::AbsoluteBound{1.0, 0};
BoundaryTolerance bcTol1 = BoundaryTolerance::AbsoluteBound{0, 0.2};
BoundaryTolerance bcTol01 = BoundaryTolerance::AbsoluteBound{1.0, 0.2};
BoundaryTolerance bcCov = BoundaryTolerance::Chi2Bound{cov, 1};
BoundaryTolerance bcTol0 = BoundaryTolerance::AbsoluteBound(1.0, 0.0);
BoundaryTolerance bcTol1 = BoundaryTolerance::AbsoluteBound(0.0, 0.2);
BoundaryTolerance bcTol01 = BoundaryTolerance::AbsoluteBound(1.0, 0.2);
BoundaryTolerance bcCov = BoundaryTolerance::Chi2Bound(cov, 1.0);

// visualization to make sense of things
for (std::size_t i = 0; i < 10000; i++) {
Expand Down
Loading

0 comments on commit a3976a1

Please sign in to comment.