Plugins
Loading...
Searching...
No Matches
river_sss.h
Go to the documentation of this file.
1//
2// Created by julian on 1/15/26.
3//
4
5#ifndef UG4_RIVER_SSS_H
6#define UG4_RIVER_SSS_H
7#include "common/common.h"
10#include "../d3f_sss.h"
11namespace ug{
12 namespace d3f{
13
18 template <int dim>
20 const AABox<MathVector<dim>>& b)
21 {
22 for (int d = 0; d < dim; ++d)
23 {
24 if (a.max[d] < b.min[d] || a.min[d] > b.max[d])
25 return false; // no overlap in this dimension
26 }
27 return true; // overlaps in all dimensions
28 }
29
35template <int dim>
37 const AABox<MathVector<dim>>& other)
38{
39 for (int d = 0; d < dim; ++d)
40 {
41 if (other.min[d] < bbox.min[d]) bbox.min[d] = other.min[d];
42 if (other.max[d] > bbox.max[d]) bbox.max[d] = other.max[d];
43 }
44}
45
50template <int dim>
52{
53 int axis = 0;
54 number max_len = box.max[0] - box.min[0];
55
56 for (int d = 1; d < dim; ++d)
57 {
58 number len = box.max[d] - box.min[d];
59 if (len > max_len)
60 {
61 max_len = len;
62 axis = d;
63 }
64 }
65 return axis;
66}
67
71 template <int dim>
74 const MathVector<dim>& b)
75 {
77 // initialize min and max component-wise
78 for (int d = 0; d < dim; ++d)
79 {
80 if (a[d] < b[d])
81 {
82 bb.min[d] = a[d];
83 bb.max[d] = b[d];
84 }
85 else
86 {
87 bb.min[d] = b[d];
88 bb.max[d] = a[d];
89 }
90 }
91
92 return bb;
93 }
94
98 template <int dim>
100 {
102 std::vector<size_t> indices;
105
106 bool is_leaf() const { return !left && !right; }
107 };
108
115template <int dim, typename TLineData>
117{
118public:
120
124 void build(std::vector<SmartPtr<line_type>>& lines)
125 {
126 std::vector<size_t> ids(lines.size());
127 for (size_t i = 0; i < ids.size(); ++i)
128 ids[i] = i;
129 m_root = build_node(lines, ids, 0);
130 }
131
137 void query(const AABox<MathVector<dim>>& box,
138 std::vector<size_t>& out) const
139 {
140 query_node(m_root.get(), box, out);
141 }
142
143private:
145
150 build_node(std::vector<SmartPtr<line_type>>& lines,
151 std::vector<size_t>& ids,
152 int depth)
153 {
154 auto node = make_sp(new LineBVHNode<dim>());
155
156 // 1. Compute the combined bounding box for all lines in this node
157 if (!ids.empty())
158 {
159 node->bbox = LineBoundingBox<dim>(
160 lines[ids[0]]->from_position(),
161 lines[ids[0]]->to_position());
162
163 for (size_t i = 1; i < ids.size(); ++i)
164 {
165 AABox<MathVector<dim>> bb = LineBoundingBox<dim>(
166 lines[ids[i]]->from_position(),
167 lines[ids[i]]->to_position());
168 expand_bbox<dim>(node->bbox, bb);
169 }
170 }
171
172 // 2. Base case: If few lines remain, create a leaf node
173 if (ids.size() <= 8)
174 {
175 node->indices = ids;
176 return node;
177 }
178
179 // 3. Choose split axis and sort lines to partition them
180 int axis = longest_axis<dim>(node->bbox);
181
182 std::sort(ids.begin(), ids.end(),
183 [&](size_t a, size_t b)
184 {
185 return lines[a]->from_position()[axis] <
186 lines[b]->from_position()[axis];
187 });
188
189 // 4. Split and recurse
190 size_t mid = ids.size() / 2;
191 std::vector<size_t> left(ids.begin(), ids.begin() + mid);
192 std::vector<size_t> right(ids.begin() + mid, ids.end());
193
194 node->left = build_node(lines, left, depth + 1);
195 node->right = build_node(lines, right, depth + 1);
196 return node;
197 }
198
202 void query_node(const LineBVHNode<dim>* node,
203 const AABox<MathVector<dim>>& box,
204 std::vector<size_t>& out) const
205 {
206 // Early exit if node is empty or query box doesn't overlap the node's volume
207 if (!node || !boxes_overlap<dim>(node->bbox, box))
208 return;
209
210 // If leaf, add all contained indices to the output
211 if (node->is_leaf())
212 {
213 out.insert(out.end(),
214 node->indices.begin(),
215 node->indices.end());
216 return;
217 }
218
219 // Recurse into children
220 query_node(node->left.get(), box, out);
221 query_node(node->right.get(), box, out);
222 }
223};
224
232 template <int dim, typename TPointData, typename TLineData = TPointData>
234{
235public:
238
239private:
240 std::vector<SmartPtr<point_sss_type>> ListP;
241 std::vector<SmartPtr<line_sss_type>> ListL;
242
244 bool m_bvh_valid = false;
245
246public:
248 {
249 ListP.push_back(p);
250 }
251
253 {
254 ListL.push_back(l);
255 m_bvh_valid = false; // Mark for rebuild on next query
256 }
257
262 {
263 m_bvh.build(ListL);
264 m_bvh_valid = true;
265 }
266
267 size_t num_lines() const { return ListL.size(); }
268 line_sss_type* line(size_t i) { return ListL[i].get(); }
269
273 template <typename TElem, typename TAAPos, typename TFVGeom>
275 {
277
279 std::vector<size_t> m_candidates;
280 size_t m_pos = 0;
281
282 TElem* m_elem;
284 TAAPos& m_aaPos;
285 const TFVGeom& m_geo;
286 size_t m_co;
287
289
290 public:
295 TElem* elem,
296 Grid& grid,
297 TAAPos& aaPos,
298 const TFVGeom& geo,
299 size_t co)
300 : m_sss(sss), m_elem(elem), m_grid(grid),
301 m_aaPos(aaPos), m_geo(geo), m_co(co)
302 {
303 if (!m_sss->m_bvh_valid)
305
306 // Find all line segments whose bounding box overlaps the element's bounding box
307 auto elem_bb = CalculateBoundingBox(elem, aaPos);
308 m_sss->m_bvh.query(elem_bb, m_candidates);
309
310 // Advance to the first segment that actually intersects the element geometry
311 advance();
312 }
313
314 bool is_over() const { return m_pos >= m_candidates.size(); }
315
317 {
318 return m_sss->ListL[m_candidates[m_pos]].get();
319 }
320
321 const MathVector<dim>& seg_start() const { return m_ls; }
322 const MathVector<dim>& seg_end() const { return m_le; }
323
325 {
326 ++m_pos;
327 advance();
328 return *this;
329 }
330
331 private:
335 void advance()
336 {
337 while (m_pos < m_candidates.size())
338 {
339 auto* l = m_sss->ListL[m_candidates[m_pos]].get();
340 // BVH only tells us if boxes overlap. corresponds_to() performs the
341 // expensive exact intersection test between the line segment and the FV cell.
342 if (l->corresponds_to(m_elem, m_grid, m_aaPos,
343 m_geo, m_co, m_ls, m_le))
344 return;
345 ++m_pos;
346 }
347 }
348 };
349};
350
354template <int dim>
356 : public FVSingularSourcesAndSinksKD<dim, river_point_sss_data<dim> ,river_line_sss_data<dim> >
357{};
358
359} // namespace d3f
360} // namespace ug
361#endif //UG4_RIVER_SSS_H
parameterString p
Definition Biogas.lua:1
Iterator class to traverse line segments that intersect a specific grid element.
Definition river_sss.h:275
void advance()
Filters the BVH candidates to find true geometric intersections.
Definition river_sss.h:335
const MathVector< dim > & seg_start() const
Definition river_sss.h:321
TAAPos & m_aaPos
Definition river_sss.h:284
const MathVector< dim > & seg_end() const
Definition river_sss.h:322
std::vector< size_t > m_candidates
Potential matches identified by the BVH.
Definition river_sss.h:279
MathVector< dim > m_ls
Definition river_sss.h:288
MathVector< dim > m_le
Definition river_sss.h:288
line_sss_type * operator*()
Definition river_sss.h:316
bool is_over() const
Definition river_sss.h:314
const TFVGeom & m_geo
Definition river_sss.h:285
size_t m_pos
Current position in the candidate list.
Definition river_sss.h:280
TElem * m_elem
Definition river_sss.h:282
line_iterator & operator++()
Definition river_sss.h:324
master_type * m_sss
Definition river_sss.h:278
line_iterator(master_type *sss, TElem *elem, Grid &grid, TAAPos &aaPos, const TFVGeom &geo, size_t co)
Initializes the iterator and performs the initial spatial query.
Definition river_sss.h:294
Manager for Singular Sources and Sinks (SSS) using a BVH for spatial optimization.
Definition river_sss.h:234
std::vector< SmartPtr< point_sss_type > > ListP
List of point sources/sinks.
Definition river_sss.h:240
void build_spatial_index()
(Re)builds the spatial index for line segments.
Definition river_sss.h:261
line_sss_type * line(size_t i)
Definition river_sss.h:268
void add_point(SmartPtr< point_sss_type > p)
Definition river_sss.h:247
void add_line(SmartPtr< line_sss_type > l)
Definition river_sss.h:252
size_t num_lines() const
Definition river_sss.h:267
std::vector< SmartPtr< line_sss_type > > ListL
List of line sources/sinks.
Definition river_sss.h:241
LineBVHTree< dim, TLineData > m_bvh
The spatial index.
Definition river_sss.h:243
bool m_bvh_valid
Flag to track if the index needs rebuilding.
Definition river_sss.h:244
A Bounding Volume Hierarchy tree for efficient spatial querying of line segments.
Definition river_sss.h:117
SmartPtr< LineBVHNode< dim > > build_node(std::vector< SmartPtr< line_type > > &lines, std::vector< size_t > &ids, int depth)
Internal recursive function to build the tree nodes.
Definition river_sss.h:150
SmartPtr< LineBVHNode< dim > > m_root
Definition river_sss.h:144
void query_node(const LineBVHNode< dim > *node, const AABox< MathVector< dim > > &box, std::vector< size_t > &out) const
Internal recursive function for spatial querying.
Definition river_sss.h:202
void build(std::vector< SmartPtr< line_type > > &lines)
Builds the BVH from a vector of line segments.
Definition river_sss.h:124
void query(const AABox< MathVector< dim > > &box, std::vector< size_t > &out) const
Finds all line segments whose bounding boxes potentially overlap with the query box.
Definition river_sss.h:137
Specialization of the optimized SSS manager for river networks.
Definition river_sss.h:357
SmartPtr< TGrid > grid()
void CalculateBoundingBox(size_t npoints, const MathVector< dim > points[], MathVector< dim > &vMinBB, MathVector< dim > &vMaxBB)
double number
bool boxes_overlap(const AABox< MathVector< dim > > &a, const AABox< MathVector< dim > > &b)
Checks if two Axis-Aligned Bounding Boxes (AABox) overlap.
Definition river_sss.h:19
void expand_bbox(AABox< MathVector< dim > > &bbox, const AABox< MathVector< dim > > &other)
Expands a bounding box to include another.
Definition river_sss.h:36
int longest_axis(const AABox< MathVector< dim > > &box)
Identifies the axis along which the bounding box has the largest extent. Used as a heuristic for spli...
Definition river_sss.h:51
AABox< MathVector< dim > > LineBoundingBox(const MathVector< dim > &a, const MathVector< dim > &b)
Computes the Axis-Aligned Bounding Box for a line segment.
Definition river_sss.h:73
SmartPtr< T, FreePolicy > make_sp(T *inst)
vector_t min
vector_t max
Node structure for the Bounding Volume Hierarchy (BVH).
Definition river_sss.h:100
SmartPtr< LineBVHNode > right
Right child node.
Definition river_sss.h:104
SmartPtr< LineBVHNode > left
Left child node.
Definition river_sss.h:103
std::vector< size_t > indices
Leaf only: indices into the original line list.
Definition river_sss.h:102
AABox< MathVector< dim > > bbox
Total bounding box of all lines in this node/subtree.
Definition river_sss.h:101
bool is_leaf() const
Definition river_sss.h:106