1414#include " detray/definitions/indexing.hpp"
1515#include " detray/definitions/math.hpp"
1616#include " detray/definitions/units.hpp"
17+ #include " detray/geometry/coordinates/cartesian3D.hpp"
1718#include " detray/geometry/coordinates/polar2D.hpp"
1819#include " detray/geometry/detail/shape_utils.hpp"
1920#include " detray/geometry/detail/vertexer.hpp"
@@ -160,11 +161,60 @@ class annulus2D {
160161 std::numeric_limits<dscalar<algebra_t >>::epsilon(),
161162 const dscalar<algebra_t> edge_tol = 0.f) const {
162163
163- // Get the full local position
164- const dpoint2D<algebra_t > loc_p =
165- local_frame_type<algebra_t >::global_to_local (trf, glob_p, {});
164+ using scalar_t = dscalar<algebra_t >;
165+
166+ // Move point to local plane: Focal frame in cartesian coordinates
167+ const auto loc_3D{
168+ cartesian3D<algebra_t >::global_to_local (trf, glob_p, {})};
169+
170+ // Shift local 3D position into beam frame to check the radius
171+ const scalar_t new_x{loc_3D[0 ] + bounds[e_shift_x]};
172+ const scalar_t new_y{loc_3D[1 ] + bounds[e_shift_y]};
173+
174+ const scalar_t r_beam{
175+ math::sqrt (math::fma (new_x, new_x, new_y * new_y))};
176+
177+ auto inside_mask = ((r_beam + tol) >= bounds[e_min_r]) &&
178+ (r_beam <= (bounds[e_max_r] + tol));
179+
180+ // Try to avoid the costly phi calculation
181+ auto phi_focal{detail::invalid_value<scalar_t >()};
182+ if (detail::any_of (inside_mask)) {
183+ // Get phi for phi-bounds check and rotate by average phi
184+ phi_focal = vector::phi (loc_3D) - bounds[e_average_phi];
185+ // Estimate angular tolerance along r
186+ const scalar_t phi_tol{detail::phi_tolerance (tol, r_beam)};
187+
188+ inside_mask = (phi_focal >= (bounds[e_min_phi_rel] - phi_tol)) &&
189+ (phi_focal <= (bounds[e_max_phi_rel] + phi_tol)) &&
190+ inside_mask;
191+ }
192+
193+ decltype (inside_mask) inside_edge{false };
194+ if (detail::any_of (edge_tol > 0 .f )) {
195+ // Edge tolerance
196+ const scalar_t full_tol{tol + edge_tol};
197+
198+ inside_edge = ((r_beam + full_tol) >= bounds[e_min_r]) &&
199+ (r_beam <= (bounds[e_max_r] + full_tol));
200+
201+ if (detail::any_of (inside_edge)) {
202+ // If phi had not been calculated before, do it now
203+ if (detail::is_invalid_value (phi_focal)) {
204+ phi_focal = vector::phi (loc_3D) - bounds[e_average_phi];
205+ }
206+
207+ const scalar_t phi_tol_full{
208+ detail::phi_tolerance (full_tol, r_beam)};
209+
210+ inside_edge =
211+ (phi_focal >= (bounds[e_min_phi_rel] - phi_tol_full)) &&
212+ (phi_focal <= (bounds[e_max_phi_rel] + phi_tol_full)) &&
213+ inside_edge;
214+ }
215+ }
166216
167- return check_boundaries (bounds, loc_p, tol, edge_tol) ;
217+ return result_type< decltype (inside_mask)>{inside_mask, inside_edge} ;
168218 }
169219
170220 // / @note the point is expected to be given in local coordinates by the
@@ -188,36 +238,54 @@ class annulus2D {
188238
189239 // Check phi boundaries, which are well def. in focal frame
190240 const scalar_t phi_tol = detail::phi_tolerance (tol, loc_p[0 ]);
191- const auto phi_check =
192- !((phi_focal < (bounds[e_min_phi_rel] - phi_tol)) ||
193- (phi_focal > (bounds[e_max_phi_rel] + phi_tol)));
241+ auto inside_mask = !((phi_focal < (bounds[e_min_phi_rel] - phi_tol)) ||
242+ (phi_focal > (bounds[e_max_phi_rel] + phi_tol)));
243+
244+ // Try to avoid the costly r_beam calculation
245+ auto r_beam2{detail::invalid_value<scalar_t >()};
246+ if (detail::any_of (inside_mask)) {
194247
195- const auto r_beam2 = get_r2_beam_frame (bounds, loc_p);
248+ r_beam2 = get_r2_beam_frame (bounds, loc_p);
196249
197- // Apply tolerances as squares: 0 <= a, 0 <= b: a^2 <= b^2 <=> a <= b
198- const scalar_t minR_tol =
199- math::max (bounds[e_min_r] - tol, scalar_t (0 .f ));
200- const scalar_t maxR_tol = bounds[e_max_r] + tol;
250+ // Apply tolerances as squares: 0 <= a, 0 <= b: a^2 <= b^2 <=> a <=
251+ // b
252+ const scalar_t minR_tol =
253+ math::max (bounds[e_min_r] - tol, scalar_t (0 .f ));
254+ const scalar_t maxR_tol = bounds[e_max_r] + tol;
201255
202- assert (detail::all_of (minR_tol >= scalar_t (0 .f )));
256+ assert (detail::all_of (minR_tol >= scalar_t (0 .f )));
203257
204- auto inside_mask{( (r_beam2 >= (minR_tol * minR_tol)) &&
205- (r_beam2 <= (maxR_tol * maxR_tol))) &&
206- phi_check};
258+ inside_mask = (r_beam2 >= (minR_tol * minR_tol)) &&
259+ (r_beam2 <= (maxR_tol * maxR_tol)) && inside_mask;
260+ }
207261
208262 decltype (inside_mask) inside_edge{false };
209263 if (detail::any_of (edge_tol > 0 .f )) {
210264 // Edge tolerance
211265 const scalar_t full_tol{tol + edge_tol};
212- const scalar_t minR_tol_edge =
213- math::max (bounds[e_min_r] - full_tol, scalar_t (0 .f ));
214- const scalar_t maxR_tol_edge = bounds[e_max_r] + full_tol;
266+ const scalar_t phi_tol_full =
267+ detail::phi_tolerance (full_tol, loc_p[0 ]);
268+
269+ const auto phi_check_edge =
270+ (phi_focal >= (bounds[e_min_phi_rel] - phi_tol_full)) &&
271+ (phi_focal <= (bounds[e_max_phi_rel] + phi_tol_full));
272+
273+ if (detail::any_of (inside_edge)) {
274+ // If phi had not been calculated before, do it now
275+ if (detail::is_invalid_value (r_beam2)) {
276+ r_beam2 = get_r2_beam_frame (bounds, loc_p);
277+ }
278+
279+ const scalar_t minR_tol_edge =
280+ math::max (bounds[e_min_r] - full_tol, scalar_t (0 .f ));
281+ const scalar_t maxR_tol_edge = bounds[e_max_r] + full_tol;
215282
216- assert (detail::all_of (minR_tol_edge >= scalar_t (0 .f )));
283+ assert (detail::all_of (minR_tol_edge >= scalar_t (0 .f )));
217284
218- inside_edge = ((r_beam2 >= (minR_tol_edge * minR_tol_edge)) &&
219- (r_beam2 <= (maxR_tol_edge * maxR_tol_edge))) &&
220- phi_check;
285+ inside_edge = (r_beam2 >= (minR_tol_edge * minR_tol_edge)) &&
286+ (r_beam2 <= (maxR_tol_edge * maxR_tol_edge)) &&
287+ phi_check_edge;
288+ }
221289 }
222290
223291 return result_type<decltype (inside_mask)>{inside_mask, inside_edge};
0 commit comments