File indexing completed on 2025-09-15 09:06:12
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/math/Algorithms.hh"
0010
0011 #include "BIHView.hh"
0012 #include "../BoundingBoxUtils.hh"
0013 #include "../OrangeData.hh"
0014 #include "../univ/detail/Types.hh"
0015
0016 namespace celeritas
0017 {
0018 namespace detail
0019 {
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 class BIHIntersectingVolFinder
0042 {
0043 public:
0044
0045
0046 using Storage = NativeCRef<BIHTreeData>;
0047
0048 struct Ray
0049 {
0050 Real3 const& pos;
0051 Real3 const& dir;
0052 };
0053
0054
0055
0056 inline CELER_FUNCTION
0057 BIHIntersectingVolFinder(BIHTree const& tree, Storage const& storage);
0058
0059
0060
0061 template<class F>
0062 inline CELER_FUNCTION Intersection
0063 operator()(Ray ray, F&& visit_vol, real_type max_search_dist) const;
0064
0065
0066
0067 template<class F>
0068 inline CELER_FUNCTION Intersection operator()(Ray ray, F&& visit_vol) const;
0069
0070 private:
0071
0072 BIHView view_;
0073
0074
0075
0076
0077 inline CELER_FUNCTION BIHNodeId next_node(BIHNodeId current_id,
0078 BIHNodeId previous_id,
0079 Ray ray,
0080 real_type min_dist) const;
0081
0082
0083
0084 inline CELER_FUNCTION bool
0085 visit_bbox(FastBBox const& bbox, Ray ray, real_type min_dist) const;
0086
0087
0088
0089 template<class F>
0090 inline CELER_FUNCTION Intersection visit_leaf(BIHLeafNode const& leaf_node,
0091 Ray ray,
0092 Intersection intersection,
0093 F&& visit_vol) const;
0094
0095
0096 template<class F>
0097 inline CELER_FUNCTION Intersection visit_inf_vols(Intersection intersection,
0098 F&& visit_vol) const;
0099 };
0100
0101
0102
0103
0104
0105
0106
0107 CELER_FUNCTION
0108 BIHIntersectingVolFinder::BIHIntersectingVolFinder(
0109 BIHTree const& tree, BIHIntersectingVolFinder::Storage const& storage)
0110 : view_(tree, storage)
0111 {
0112 CELER_EXPECT(tree);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 template<class F>
0128 CELER_FUNCTION auto
0129 BIHIntersectingVolFinder::operator()(BIHIntersectingVolFinder::Ray ray,
0130 F&& visit_vol,
0131 real_type max_search_dist) const
0132 -> Intersection
0133 {
0134 BIHNodeId previous_node;
0135 BIHNodeId current_node{0};
0136
0137 Intersection intersection{OnLocalSurface{}, max_search_dist};
0138
0139 do
0140 {
0141 if (!view_.is_inner(current_node))
0142 {
0143 intersection = this->visit_leaf(
0144 view_.leaf_node(current_node), ray, intersection, visit_vol);
0145 }
0146
0147 previous_node = exchange(
0148 current_node,
0149 this->next_node(
0150 current_node, previous_node, ray, intersection.distance));
0151
0152 } while (current_node);
0153
0154 return this->visit_inf_vols(intersection, visit_vol);
0155 }
0156
0157
0158
0159
0160
0161
0162 template<class F>
0163 CELER_FUNCTION auto
0164 BIHIntersectingVolFinder::operator()(BIHIntersectingVolFinder::Ray ray,
0165 F&& visit_vol) const -> Intersection
0166 {
0167 return (*this)(ray, visit_vol, numeric_limits<real_type>::infinity());
0168 }
0169
0170
0171
0172
0173
0174
0175
0176 CELER_FUNCTION
0177 BIHNodeId BIHIntersectingVolFinder::next_node(BIHNodeId current_id,
0178 BIHNodeId previous_id,
0179 Ray ray,
0180 real_type min_dist) const
0181 {
0182 using Side = BIHInnerNode::Side;
0183
0184 if (!view_.is_inner(current_id))
0185 {
0186
0187 CELER_EXPECT(previous_id == view_.leaf_node(current_id).parent);
0188 return previous_id;
0189 }
0190
0191 auto const& current_node = view_.inner_node(current_id);
0192 auto const& l_edge = current_node.edges[Side::left];
0193 auto const& r_edge = current_node.edges[Side::right];
0194
0195 if (previous_id == current_node.parent)
0196 {
0197
0198
0199 if (this->visit_bbox(l_edge.bbox, ray, min_dist))
0200 {
0201 return l_edge.child;
0202 }
0203 else if (this->visit_bbox(r_edge.bbox, ray, min_dist))
0204 {
0205 return r_edge.child;
0206 }
0207 else
0208 {
0209 return current_node.parent;
0210 }
0211 }
0212
0213 if (previous_id == current_node.edges[Side::left].child)
0214 {
0215
0216
0217 return this->visit_bbox(r_edge.bbox, ray, min_dist)
0218 ? r_edge.child
0219 : current_node.parent;
0220 }
0221
0222
0223 CELER_ASSERT(previous_id == current_node.edges[Side::right].child);
0224 return current_node.parent;
0225 }
0226
0227
0228
0229
0230
0231 CELER_FUNCTION
0232 bool BIHIntersectingVolFinder::visit_bbox(FastBBox const& bbox,
0233 Ray ray,
0234 real_type min_dist) const
0235 {
0236 return is_inside(bbox, ray.pos)
0237 || calc_dist_to_inside(bbox, ray.pos, ray.dir) < min_dist;
0238 }
0239
0240
0241
0242
0243
0244 template<class F>
0245 CELER_FUNCTION auto
0246 BIHIntersectingVolFinder::visit_leaf(BIHLeafNode const& leaf_node,
0247 BIHIntersectingVolFinder::Ray ray,
0248 Intersection min_intersection,
0249 F&& visit_vol) const -> Intersection
0250 {
0251 for (auto id : view_.leaf_vol_ids(leaf_node))
0252 {
0253 auto const& bbox = view_.bbox(id);
0254
0255 if (this->visit_bbox(bbox, ray, min_intersection.distance))
0256 {
0257 auto intersection = visit_vol(id, min_intersection.distance);
0258 if (intersection
0259 && intersection.distance < min_intersection.distance)
0260 {
0261 min_intersection = intersection;
0262 }
0263 }
0264 }
0265 return min_intersection;
0266 }
0267
0268
0269
0270
0271
0272 template<class F>
0273 CELER_FUNCTION auto
0274 BIHIntersectingVolFinder::visit_inf_vols(Intersection min_intersection,
0275 F&& visit_vol) const -> Intersection
0276 {
0277 for (auto id : view_.inf_vol_ids())
0278 {
0279 auto intersection = visit_vol(id, min_intersection.distance);
0280 if (intersection && intersection.distance < min_intersection.distance)
0281 {
0282 min_intersection = intersection;
0283 }
0284 }
0285 return min_intersection;
0286 }
0287
0288
0289 }
0290 }