12#include "detray/definitions/algebra.hpp"
13#include "detray/definitions/containers.hpp"
14#include "detray/definitions/detail/qualifiers.hpp"
15#include "detray/definitions/indexing.hpp"
16#include "detray/definitions/math.hpp"
17#include "detray/definitions/units.hpp"
18#include "detray/geometry/coordinates/cartesian3D.hpp"
19#include "detray/geometry/coordinates/polar2D.hpp"
20#include "detray/geometry/detail/shape_utils.hpp"
21#include "detray/geometry/detail/vertexer.hpp"
51 static constexpr std::string_view
name =
"(stereo) annulus2D";
66 template <concepts::scalar scalar_t>
70 template <concepts::algebra algebra_t>
74 template <
typename bool_t>
78 static constexpr std::size_t
dim{2u};
81 template <concepts::scalar scalar_t>
85 return 2.f * math::atan(bounds[e_shift_y] / bounds[e_shift_x]);
91 template <concepts::scalar scalar_t, concepts::po
int po
int_t>
95 return loc_p[1] - bounds[e_average_phi];
101 template <concepts::scalar scalar_t, concepts::po
int po
int_t>
108 shift_xy[0u] = -bounds[e_shift_x];
109 shift_xy[1u] = -bounds[e_shift_y];
110 const scalar_t shift_r = vector::perp(shift_xy);
111 const scalar_t shift_phi = vector::phi(shift_xy);
113 return shift_r * shift_r + loc_p[0] * loc_p[0] +
114 2.f * shift_r * loc_p[0] *
128 template <concepts::scalar scalar_t, concepts::po
int po
int_t>
134 const scalar_t phi_rel_focal =
get_phi_rel(bounds, loc_p);
137 const scalar_t min_phi_dist =
138 math::min(math::fabs(phi_rel_focal - bounds[e_min_phi_rel]),
139 math::fabs(bounds[e_max_phi_rel] - phi_rel_focal));
143 const scalar_t min_r_dist = math::min(math::fabs(r_beam - bounds[e_min_r]),
144 math::fabs(bounds[e_max_r] - r_beam));
147 return math::min(min_r_dist,
148 2.f * loc_p[0] * math::sin(0.5f * min_phi_dist));
160 template <concepts::algebra algebra_t>
173 const scalar_t new_x{loc_3D[0] + bounds[e_shift_x]};
174 const scalar_t new_y{loc_3D[1] + bounds[e_shift_y]};
176 const scalar_t r_beam{math::sqrt(math::fma(new_x, new_x, new_y * new_y))};
178 auto inside_mask = ((r_beam + tol) >= bounds[e_min_r]) &&
179 (r_beam <= (bounds[e_max_r] + tol));
182 auto phi_focal{detail::invalid_value<scalar_t>()};
183 if (detail::any_of(inside_mask)) {
185 phi_focal = vector::phi(loc_3D) - bounds[e_average_phi];
187 const scalar_t phi_tol{detail::phi_tolerance(tol, r_beam)};
189 inside_mask = (phi_focal >= (bounds[e_min_phi_rel] - phi_tol)) &&
190 (phi_focal <= (bounds[e_max_phi_rel] + phi_tol)) &&
194 decltype(inside_mask) inside_edge{
false};
195 if (detail::any_of(edge_tol > 0.f)) {
197 const scalar_t full_tol{tol + edge_tol};
199 inside_edge = ((r_beam + full_tol) >= bounds[e_min_r]) &&
200 (r_beam <= (bounds[e_max_r] + full_tol));
202 if (detail::any_of(inside_edge)) {
204 if (detail::is_invalid_value(phi_focal)) {
205 phi_focal = vector::phi(loc_3D) - bounds[e_average_phi];
208 const scalar_t phi_tol_full{detail::phi_tolerance(full_tol, r_beam)};
210 inside_edge = (phi_focal >= (bounds[e_min_phi_rel] - phi_tol_full)) &&
211 (phi_focal <= (bounds[e_max_phi_rel] + phi_tol_full)) &&
216 return result_type<
decltype(inside_mask)>{inside_mask, inside_edge};
229 template <concepts::scalar scalar_t, concepts::po
int po
int_t>
232 const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
233 const scalar_t edge_tol = 0.f)
const {
237 const scalar_t phi_focal =
get_phi_rel(bounds, loc_p);
240 const scalar_t phi_tol = detail::phi_tolerance(tol, loc_p[0]);
241 auto inside_mask = !((phi_focal < (bounds[e_min_phi_rel] - phi_tol)) ||
242 (phi_focal > (bounds[e_max_phi_rel] + phi_tol)));
245 auto r_beam2{detail::invalid_value<scalar_t>()};
246 if (detail::any_of(inside_mask)) {
251 const scalar_t minR_tol =
252 math::max(bounds[e_min_r] - tol,
static_cast<scalar_t
>(0.f));
253 const scalar_t maxR_tol = bounds[e_max_r] + tol;
255 assert(detail::all_of(minR_tol >=
static_cast<scalar_t
>(0.f)));
257 inside_mask = (r_beam2 >= (minR_tol * minR_tol)) &&
258 (r_beam2 <= (maxR_tol * maxR_tol)) && inside_mask;
261 decltype(inside_mask) inside_edge{
false};
262 if (detail::any_of(edge_tol > 0.f)) {
264 const scalar_t full_tol{tol + edge_tol};
265 const scalar_t phi_tol_full = detail::phi_tolerance(full_tol, loc_p[0]);
267 const auto phi_check_edge =
268 (phi_focal >= (bounds[e_min_phi_rel] - phi_tol_full)) &&
269 (phi_focal <= (bounds[e_max_phi_rel] + phi_tol_full));
271 if (detail::any_of(inside_edge)) {
273 if (detail::is_invalid_value(r_beam2)) {
277 const scalar_t minR_tol_edge =
278 math::max(bounds[e_min_r] - full_tol,
static_cast<scalar_t
>(0.f));
279 const scalar_t maxR_tol_edge = bounds[e_max_r] + full_tol;
281 assert(detail::all_of(minR_tol_edge >=
static_cast<scalar_t
>(0.f)));
283 inside_edge = (r_beam2 >= (minR_tol_edge * minR_tol_edge)) &&
284 (r_beam2 <= (maxR_tol_edge * maxR_tol_edge)) &&
289 return result_type<
decltype(inside_mask)>{inside_mask, inside_edge};
300 template <concepts::scalar scalar_t>
301 DETRAY_HOST_DEVICE
constexpr scalar_t
measure(
312 template <concepts::scalar scalar_t>
313 DETRAY_HOST_DEVICE
constexpr scalar_t
area(
315 return detail::invalid_value<scalar_t>();
324 template <concepts::scalar scalar_t>
328 assert(bounds[e_average_phi] == o_bounds[e_average_phi]);
329 assert(bounds[e_shift_x] == o_bounds[e_shift_x]);
330 assert(bounds[e_shift_y] == o_bounds[e_shift_y]);
334 new_bounds[e_min_r] = math::min(bounds[e_min_r], o_bounds[e_min_r]);
335 new_bounds[e_max_r] = math::max(bounds[e_max_r], o_bounds[e_max_r]);
336 new_bounds[e_min_phi_rel] =
337 math::min(bounds[e_min_phi_rel], o_bounds[e_min_phi_rel]);
338 new_bounds[e_max_phi_rel] =
339 math::max(bounds[e_max_phi_rel], o_bounds[e_max_phi_rel]);
340 new_bounds[e_average_phi] = bounds[e_average_phi];
341 new_bounds[e_shift_x] = bounds[e_shift_x];
342 new_bounds[e_shift_y] = bounds[e_shift_y];
357 template <concepts::algebra algebra_t>
367 const auto c_pos =
corners(bounds);
369 const scalar_t o_x{bounds[e_shift_x]};
370 const scalar_t o_y{bounds[e_shift_y]};
373 const point_t b{c_pos[4] * math::cos(c_pos[5]) - o_x,
374 c_pos[4] * math::sin(c_pos[5]) - o_y};
375 const point_t c{c_pos[6] * math::cos(c_pos[7]) - o_x,
376 c_pos[6] * math::sin(c_pos[7]) - o_y};
380 const point_t t = bounds[e_max_r] * vector::normalize(c + b);
384 c_pos[0] * math::cos(c_pos[1]) - o_x, t[0]};
386 c_pos[0] * math::sin(c_pos[1]) - o_y, t[1]};
388 constexpr scalar_t inv{detail::invalid_value<scalar_t>()};
391 scalar_t max_x{-inv};
392 scalar_t max_y{-inv};
393 for (
unsigned int i{0u}; i < 5u; ++i) {
394 min_x = x_pos[i] < min_x ? x_pos[i] : min_x;
395 max_x = x_pos[i] > max_x ? x_pos[i] : max_x;
396 min_y = y_pos[i] < min_y ? y_pos[i] : min_y;
397 max_y = y_pos[i] > max_y ? y_pos[i] : max_y;
400 return {min_x - env, min_y - env, -env, max_x + env, max_y + env, env};
412 template <concepts::scalar scalar_t>
419 auto get_strips_pc_r = [&bounds](
const scalar_t R,
420 const scalar_t phi) -> scalar_t {
422 const scalar_t f2{bounds[e_shift_x] * bounds[e_shift_x] +
423 bounds[e_shift_y] * bounds[e_shift_y]};
427 const scalar_t f_sin_phi{bounds[e_shift_x] * math::cos(phi) +
428 bounds[e_shift_y] * math::sin(phi)};
430 return f_sin_phi + math::sqrt(f_sin_phi * f_sin_phi - f2 + R * R);
434 const scalar_t min_phi{bounds[e_average_phi] + bounds[e_min_phi_rel]};
435 const scalar_t max_phi{bounds[e_average_phi] + bounds[e_max_phi_rel]};
438 corner_pos[0] = get_strips_pc_r(bounds[e_min_r], min_phi);
439 corner_pos[1] = min_phi;
441 corner_pos[2] = get_strips_pc_r(bounds[e_min_r], max_phi);
442 corner_pos[3] = max_phi;
444 corner_pos[4] = get_strips_pc_r(bounds[e_max_r], max_phi);
445 corner_pos[5] = max_phi;
447 corner_pos[6] = get_strips_pc_r(bounds[e_max_r], min_phi);
448 corner_pos[7] = min_phi;
457 template <concepts::algebra algebra_t>
463 const auto crns =
corners(bounds);
466 const scalar_t r{0.25f * (crns[0] + crns[2] + crns[4] + crns[6])};
467 const scalar_t phi{bounds[e_average_phi]};
470 static_cast<scalar_t
>(0)};
479 template <concepts::algebra algebra_t>
486 scalar_t min_r = bounds[e_min_r];
487 scalar_t max_r = bounds[e_max_r];
488 scalar_t min_phi = bounds[e_average_phi] + bounds[e_min_phi_rel];
489 scalar_t max_phi = bounds[e_average_phi] + bounds[e_max_phi_rel];
490 scalar_t origin_x = bounds[e_shift_x];
491 scalar_t origin_y = bounds[e_shift_y];
493 point2_t origin_m = {origin_x, origin_y};
496 auto circIx = [](scalar_t O_x, scalar_t O_y, scalar_t r,
497 scalar_t phi) -> point2_t {
508 scalar_t m = math::tan(phi);
509 point2_t dir = {math::cos(phi), math::sin(phi)};
510 scalar_t x1 = (O_x + O_y * m -
511 math::sqrt(-math::pow(O_x, 2.f) * math::pow(m, 2.f) +
512 2.f * O_x * O_y * m - math::pow(O_y, 2.f) +
513 math::pow(m, 2.f) * math::pow(r, 2.f) +
514 math::pow(r, 2.f))) /
515 (math::pow(m, 2.f) + 1.f);
516 scalar_t x2 = (O_x + O_y * m +
517 math::sqrt(-math::pow(O_x, 2.f) * math::pow(m, 2.f) +
518 2.f * O_x * O_y * m - math::pow(O_y, 2.f) +
519 math::pow(m, 2.f) * math::pow(r, 2.f) +
520 math::pow(r, 2.f))) /
521 (math::pow(m, 2.f) + 1.f);
523 if (point2_t v1 = {x1, m * x1}; vector::dot(v1, dir) > 0.f) {
530 point2_t ul_xy = circIx(origin_x, origin_y, max_r, max_phi);
531 point2_t ll_xy = circIx(origin_x, origin_y, min_r, max_phi);
532 point2_t ur_xy = circIx(origin_x, origin_y, max_r, min_phi);
533 point2_t lr_xy = circIx(origin_x, origin_y, min_r, min_phi);
535 auto inner_phi = detail::phi_values(vector::phi(lr_xy - origin_m),
536 vector::phi(ll_xy - origin_m), n_seg);
537 auto outer_phi = detail::phi_values(vector::phi(ul_xy - origin_m),
538 vector::phi(ur_xy - origin_m), n_seg);
541 annulus_vertices.reserve(inner_phi.size() + outer_phi.size());
542 for (scalar_t iphi : inner_phi) {
543 annulus_vertices.push_back(point3_t{min_r * math::cos(iphi) + origin_x,
544 min_r * math::sin(iphi) + origin_y,
548 for (scalar_t ophi : outer_phi) {
549 annulus_vertices.push_back(point3_t{max_r * math::cos(ophi) + origin_x,
550 max_r * math::sin(ophi) + origin_y,
554 return annulus_vertices;
563 template <concepts::scalar scalar_t>
566 constexpr auto tol{10.f * std::numeric_limits<scalar_t>::epsilon()};
568 if (math::signbit(bounds[e_min_r]) || bounds[e_max_r] < tol) {
569 os <<
"DETRAY ERROR (HOST): Radial bounds must be in the range [0, "
573 if (bounds[e_min_r] >= bounds[e_max_r] ||
574 math::fabs(bounds[e_min_r] - bounds[e_max_r]) < tol) {
575 os <<
"DETRAY ERROR (HOST): Min radius must be smaller than max "
585 os <<
"DETRAY ERROR (HOST): Angles must map onto [-pi, pi] range.";
588 if (bounds[e_min_phi_rel] >= bounds[e_max_phi_rel] ||
589 math::fabs(bounds[e_min_phi_rel] - bounds[e_max_phi_rel]) < tol) {
590 os <<
"DETRAY ERROR (HOST): Min relative angle must be smaller "
Geometrical shape of a stereo annulus that is used for the ITk strip endcaps.
Definition annulus2D.hpp:48
constexpr bounds_type< scalar_t > merge(const bounds_type< scalar_t > &bounds, const bounds_type< scalar_t > &o_bounds) const
Merge two annulus shapes.
Definition annulus2D.hpp:325
constexpr bool check_consistency(const bounds_type< scalar_t > &bounds, std::ostream &os) const
Check consistency of boundary values.
Definition annulus2D.hpp:564
constexpr scalar_t area(const bounds_type< scalar_t > &) const
The area of a the shape.
Definition annulus2D.hpp:313
scalar_t get_phi_rel(const bounds_type< scalar_t > &bounds, const point_t &loc_p) const
Definition annulus2D.hpp:92
darray< dscalar< algebra_t >, 6 > local_min_bounds(const bounds_type< dscalar< algebra_t > > &bounds, const dscalar< algebra_t > env=std::numeric_limits< dscalar< algebra_t > >::epsilon()) const
Lower and upper point for minimal axis aligned bounding box.
Definition annulus2D.hpp:358
constexpr scalar_t measure(const bounds_type< scalar_t > &bounds) const
Measure of the shape: Area.
Definition annulus2D.hpp:301
dpoint3D< algebra_t > centroid(const bounds_type< dscalar< algebra_t > > &bounds) const
Definition annulus2D.hpp:458
scalar_t min_dist_to_boundary(const bounds_type< scalar_t > &bounds, const point_t &loc_p) const
Find the minimum distance to any boundary.
Definition annulus2D.hpp:129
darray< scalar_t, 8 > corners(const bounds_type< scalar_t > &bounds) const
Stereo annulus corners in polar strip system.
Definition annulus2D.hpp:413
dvector< dpoint3D< algebra_t > > vertices(const bounds_type< dscalar< algebra_t > > &bounds, dindex n_seg) const
Generate vertices in local cartesian frame.
Definition annulus2D.hpp:480
static constexpr std::string_view name
The name for this shape.
Definition annulus2D.hpp:51
polar2D< algebra_t > local_frame_type
Local coordinate frame ( focal system ).
Definition annulus2D.hpp:71
darray< scalar_t, 8 > stereo_angle(const bounds_type< scalar_t > &bounds) const
Definition annulus2D.hpp:82
detail::boundary_check_result< bool_t > result_type
Result type of a boundary check.
Definition annulus2D.hpp:75
darray< scalar_t, boundaries::e_size > bounds_type
Container definition for the shape boundary values.
Definition annulus2D.hpp:67
constexpr auto check_boundaries(const bounds_type< scalar_t > &bounds, const point_t &loc_p, const scalar_t tol=std::numeric_limits< scalar_t >::epsilon(), const scalar_t edge_tol=0.f) const
Definition annulus2D.hpp:230
constexpr result_type< dbool< algebra_t > > check_boundaries(const bounds_type< dscalar< algebra_t > > &bounds, const dtransform3D< algebra_t > &trf, const dpoint3D< algebra_t > &glob_p, const dscalar< algebra_t > tol=std::numeric_limits< dscalar< algebra_t > >::epsilon(), const dscalar< algebra_t > edge_tol=0.f) const
Check boundary values for a local point.
Definition annulus2D.hpp:161
static constexpr std::size_t dim
Dimension of the local coordinate system.
Definition annulus2D.hpp:78
scalar_t get_r2_beam_frame(const bounds_type< scalar_t > &bounds, const point_t &loc_p) const
Definition annulus2D.hpp:102
boundaries
Names for the mask boundary values.
Definition annulus2D.hpp:54
Detray include(s).
Definition array_operators.hpp:18
get_scalar_t< A, T > dscalar
Scalar type for algebra A and value type T.
Definition algebra.hpp:64
vecmem::vector< value_t > dvector
Vector container backed by vecmem.
Definition containers.hpp:34
unsigned int dindex
Default index type.
Definition indexing.hpp:18
std::array< value_t, kDIM > darray
Fixed-size array container.
Definition containers.hpp:30
get_transform3D_t< A, T > dtransform3D
Three-dimensional transform type for algebra A and value type T.
Definition algebra.hpp:84
get_point3D_t< A, T > dpoint3D
Three-dimensional point type for algebra A and value type T.
Definition algebra.hpp:72
get_point2D_t< A, T > dpoint2D
Two-dimensional point type for algebra A and value type T.
Definition algebra.hpp:68
static loc_point global_to_local(const transform3_type &trf, const point3_type &p, const vector3_type &)
This method transforms a point from a global cartesian 3D frame to a local 3D cartesian point Convert...
Definition cartesian3D.hpp:57
static constexpr scalar_t pi
π
Definition units.hpp:136
Projection into a polar coordinate frame.
Definition polar2D.hpp:20