SWMMVis  6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
sourcechains.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2#pragma once
3#include "mixed.hpp"
4#include <queue>
6{
7// Spatial index over actual constrained cell edges only, not every free grid
8// edge. Reconstruct shared source chains across CDT and fixed patch ownership.
10{
11 struct Node {
13 int begin, end, left = -1, right = -1;
14 };
15 const Mesh &mesh_;
16 Work &work_;
17 std::vector<Edge> edges_;
18 std::vector<Node> nodes_;
19 Box2 bounds(Edge e) const
20 {
21 const auto &a = mesh_.vertices[e.a], &b = mesh_.vertices[e.b];
22 Point2 p[2] = {{a.x, a.y}, {b.x, b.y}};
23 return box(p, 2);
24 }
25 int build(int first, int last)
26 {
27 const int at = int(nodes_.size());
28 auto b = bounds(edges_[first]);
29 for (int i = first + 1; i < last; ++i) {
30 work_.tick();
31 b = b.united(bounds(edges_[i]));
32 }
33 nodes_.push_back({b, first, last});
34 if (last - first > 8) {
35 int middle = first + (last - first) / 2;
36 bool x = b.width() >= b.height();
37 std::nth_element(edges_.begin() + first, edges_.begin() + middle, edges_.begin() + last,
38 [&](Edge a, Edge b) {
39 work_.tick();
40 return x ? bounds(a).center().x() < bounds(b).center().x()
41 : bounds(a).center().y() < bounds(b).center().y();
42 });
43 int l = build(first, middle), r = build(middle, last);
44 nodes_[at].left = l;
45 nodes_[at].right = r;
46 }
47 return at;
48 }
49 template <class F> void query(Box2 b, F &f, int at = 0) const
50 {
51 if (nodes_.empty() || !meets(nodes_[at].bounds, b))
52 return;
53 work_.tick();
54 const auto &n = nodes_[at];
55 if (n.left < 0) {
56 for (int i = n.begin; i < n.end; ++i)
57 if (meets(bounds(edges_[i]), b))
58 f(edges_[i]);
59 } else {
60 query(b, f, n.left);
61 query(b, f, n.right);
62 }
63 }
64
65public:
66 SourceChains(const Mesh &m, std::vector<Edge> edges, Work &w) : mesh_(m), work_(w)
67 {
68 std::unordered_set<std::uint64_t> unique;
69 edges_.reserve(edges.size());
70 for (auto e : edges) {
71 work_.tick();
72 if (e.a != e.b && unique.insert(edgeKey(e.a, e.b)).second)
73 edges_.push_back(e);
74 }
75 work_.memoryFor({{edges_.size(), 128}, {m.vertices.size(), 36}, {m.cells.size(), 32}});
76 if (!edges_.empty())
77 build(0, int(edges_.size()));
78 }
79 std::vector<Index> chain(Index from, Index to) const
80 {
81 const auto &a = mesh_.vertices[from], &b = mesh_.vertices[to];
82 const long double dx = static_cast<long double>(b.x) - a.x,
83 dy = static_cast<long double>(b.y) - a.y, length2 = dx * dx + dy * dy;
84 const double length = std::hypot(double(dx), double(dy));
85 if (!(length > 0))
86 return {};
87 const double eps =
88 32 * std::numeric_limits<double>::epsilon() *
89 std::max({1., length, std::abs(a.x), std::abs(a.y), std::abs(b.x), std::abs(b.y)});
90 Point2 points[2] = {{a.x, a.y}, {b.x, b.y}};
91 auto bnd = box(points, 2).adjusted(-eps, -eps, eps, eps);
92 std::unordered_map<Index, std::vector<Index>> next;
93 auto visit = [&](Edge e) {
94 const auto &p = mesh_.vertices[e.a], &q = mesh_.vertices[e.b];
95 auto parameter = [&](const Point3 &p) {
96 return ((static_cast<long double>(p.x) - a.x) * dx +
97 (static_cast<long double>(p.y) - a.y) * dy) /
98 length2;
99 };
100 const auto t0 = parameter(p), t1 = parameter(q);
101 auto distance = [&](const Point3 &p, long double t) {
102 return std::hypot(static_cast<long double>(p.x) - a.x - t * dx,
103 static_cast<long double>(p.y) - a.y - t * dy);
104 };
105 if (std::min(t0, t1) < -eps / length || std::max(t0, t1) > 1 + eps / length ||
106 distance(p, t0) > eps || distance(q, t1) > eps)
107 return;
108 if (t0 <= t1)
109 next[e.a].push_back(e.b);
110 if (t1 <= t0)
111 next[e.b].push_back(e.a);
112 };
113 query(bnd, visit);
114 std::unordered_map<Index, Index> previous;
115 std::vector<Index> pending{from};
116 previous[from] = from;
117 for (std::size_t at = 0; at < pending.size() && !previous.count(to); ++at) {
118 work_.tick();
119 auto found = next.find(pending[at]);
120 if (found == next.end())
121 continue;
122 for (auto v : found->second)
123 if (previous.emplace(v, pending[at]).second)
124 pending.push_back(v);
125 }
126 if (!previous.count(to))
127 return {};
128 std::vector<Index> result{to};
129 while (result.back() != from)
130 result.push_back(previous[result.back()]);
131 std::reverse(result.begin(), result.end());
132 return result;
133 }
134};
135}
Definition geometry.hpp:59
Definition geometry.hpp:11
constexpr double x() const noexcept
Definition geometry.hpp:17
Definition sourcechains.hpp:10
std::vector< Index > chain(Index from, Index to) const
Definition sourcechains.hpp:79
SourceChains(const Mesh &m, std::vector< Edge > edges, Work &w)
Definition sourcechains.hpp:66
int begin
Definition constraints.cpp:103
int end
Definition constraints.cpp:103
size_t i
Definition contourjob.cpp:30
DiagramType t
Definition diagramspec.cpp:23
ArrowPlacement p
Definition linesymbollayer.cpp:29
MaskMode m
Definition maskspec.cpp:21
int w
Definition mesh2dresultsexport.cpp:477
std::vector< float > dx
Definition mesh2dresultsexport.cpp:765
std::vector< float > dy
Green–Gauss only, parallel to cell
Definition mesh2dresultsexport.cpp:765
Definition file.hpp:21
std::uint64_t edgeKey(Index a, Index b)
Definition operation.hpp:62
bool meets(const Box2 &a, const Box2 &b)
Definition operation.hpp:77
Definition blocks.hpp:25
std::uint32_t Index
Definition mesh.hpp:12
int right
Definition constraintaudit.cpp:162
std::vector< Edge > edges
Definition constraintaudit.cpp:192
Box box
Definition constraintaudit.cpp:161
int at
Definition constraintaudit.cpp:156
int left
Definition constraintaudit.cpp:162
double length
Definition patch.cpp:102
QString from
Definition raingageassignment.cpp:301
QString to
Definition raingageassignment.cpp:301
Definition mesh.hpp:27
Index b
Definition mesh.hpp:28
Index a
Definition mesh.hpp:28
Definition mesh.hpp:48
Definition geometry.hpp:111
Definition operation.hpp:22
double a
Definition terrainerrorfield.cpp:42
double b
Definition terrainerrorfield.cpp:42
int x
Definition terrainerrorfield.cpp:60
Sample last
Definition timeseriesrunlayer.cpp:51
Sample first
Definition timeseriesrunlayer.cpp:51
QRectF bounds
Definition traceanalysislayer.cpp:165