src/tools/liang_barsky.h
Utility to perform Liang-Barsky clipping checks on volumes. More…
Namespaces
Name |
---|
allpix Helper class to hold support layers for a detector model. |
Classes
Name | |
---|---|
class | allpix::LiangBarsky |
Detailed Description
Utility to perform Liang-Barsky clipping checks on volumes.
See: Liang, Y. D., and Barsky, B., “A New Concept and Method for Line Clipping”, ACM Transactions on Graphics, 3(1):1–22 for an in-depth explanation. This method requires the position to be in the coordinate system of the box to be tested for intersections, with the box center at its origin and the box sides aligned with the coordinate axes.
Copyright: Copyright (c) 2022-2024 CERN and the Allpix Squared authors. This software is distributed under the terms of the MIT License, copied verbatim in the file “LICENSE.md”. In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an Intergovernmental Organization or submit itself to any jurisdiction. SPDX-License-Identifier: MIT
Source code
#ifndef ALLPIX_LIANG_BARSKY_H
#define ALLPIX_LIANG_BARSKY_H
#include <Math/Point3D.h>
#include <Math/Vector3D.h>
#include <optional>
#include <utility>
namespace allpix {
class LiangBarsky {
public:
static std::optional<std::pair<double, double>> intersectionDistances(const ROOT::Math::XYZVector& direction,
const ROOT::Math::XYZPoint& position,
const ROOT::Math::XYZVector& box) {
auto clip = [](double denominator, double numerator, double& t0, double& t1) {
if(denominator > 0) {
if(numerator > denominator * t1) {
return false;
}
if(numerator > denominator * t0) {
t0 = numerator / denominator;
}
return true;
} else if(denominator < 0) {
if(numerator > denominator * t0) {
return false;
}
if(numerator > denominator * t1) {
t1 = numerator / denominator;
}
return true;
} else {
return numerator <= 0;
}
};
// Clip the particle track against the six possible box faces
double t0 = std::numeric_limits<double>::lowest(), t1 = std::numeric_limits<double>::max();
bool intersect = clip(direction.X(), -position.X() - box.X() / 2, t0, t1) &&
clip(-direction.X(), position.X() - box.X() / 2, t0, t1) &&
clip(direction.Y(), -position.Y() - box.Y() / 2, t0, t1) &&
clip(-direction.Y(), position.Y() - box.Y() / 2, t0, t1) &&
clip(direction.Z(), -position.Z() - box.Z() / 2, t0, t1) &&
clip(-direction.Z(), position.Z() - box.Z() / 2, t0, t1);
if(intersect) {
return std::make_pair(t0, t1);
}
return std::nullopt;
}
static std::optional<ROOT::Math::XYZPoint> closestIntersection(const ROOT::Math::XYZVector& direction,
const ROOT::Math::XYZPoint& position,
const ROOT::Math::XYZVector& box) {
auto intersect = intersectionDistances(direction, position, box);
if(!intersect) {
return std::nullopt;
}
// The intersection is a point P + t * D. Return closest impact point if positive (i.e. in direction of the
// motion)
auto [t0, t1] = intersect.value();
if(t0 > 0 && t1 > 0) {
return (position + std::min(t0, t1) * direction);
} else if(t0 > 0) {
return (position + t0 * direction);
} else if(t1 > 0) {
return (position + t1 * direction);
}
// Otherwise: there is no intersection in positive direction
return std::nullopt;
}
};
} // namespace allpix
#endif /* ALLPIX_LIANG_BARSKY_H */
Updated on 2024-12-13 at 08:31:37 +0000