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
cellsurfaceinterp.h
Go to the documentation of this file.
1
38#ifndef CELL_SURFACE_INTERP_H
39#define CELL_SURFACE_INTERP_H
40
41#include <QPointF>
42
43#include <algorithm>
44
46{
47
74inline double depthAt(const QPointF &p,
75 const QPointF &a, const QPointF &b, const QPointF &c,
76 double z0, double z1, double z2,
77 double sd0, double sd1, double sd2,
78 bool *degenerate = nullptr)
79{
80 if (degenerate) *degenerate = false;
81
82 const double v0x = c.x() - a.x(), v0y = c.y() - a.y();
83 const double v1x = b.x() - a.x(), v1y = b.y() - a.y();
84 const double v2x = p.x() - a.x(), v2y = p.y() - a.y();
85 const double d00 = v0x * v0x + v0y * v0y;
86 const double d01 = v0x * v1x + v0y * v1y;
87 const double d11 = v1x * v1x + v1y * v1y;
88 const double d20 = v2x * v0x + v2y * v0y;
89 const double d21 = v2x * v1x + v2y * v1y;
90 const double denom = d00 * d11 - d01 * d01;
91 if (denom == 0.0) {
92 if (degenerate) *degenerate = true;
93 return 0.0;
94 }
95 const double u = (d11 * d20 - d01 * d21) / denom; // weight for c
96 const double v = (d00 * d21 - d01 * d20) / denom; // weight for b
97 const double w = 1.0 - u - v; // weight for a
98
99 // Only WET corners (sd > 0 — water actually stands above their bed)
100 // SUPPLY surface. The other two states carry no water at their corner:
101 // sd == 0 no data — η undefined;
102 // sd < 0 η valid but below the corner's own bed — informational only.
103 // A below-bed corner must neither drag the blend down (a thin flank film
104 // pooled at a wall base would notch the pool surface toward the wall)
105 // nor raise the driving-head cap (a high bank corner with η above the
106 // pool would license the blend to climb the wall face) — both were the
107 // residual profile artifacts after the first iteration of this fix.
108 const bool wet[3] = { sd0 > 0.0, sd1 > 0.0, sd2 > 0.0 };
109 const int nWet = int(wet[0]) + int(wet[1]) + int(wet[2]);
110 // Vertex-scoped dryness: no wet corner → nothing can flood this cell.
111 if (nWet == 0) return 0.0;
112
113 const double eta[3] = { z0 + sd0, z1 + sd1, z2 + sd2 };
114 const double groundInterp = w * z0 + v * z1 + u * z2;
115
116 // Driving-head cap over the WET corners' η — the head the water actually
117 // supplies; guards extrapolating weights at/outside the edge.
118 bool any = false;
119 double maxEta = 0.0;
120 for (int k = 0; k < 3; ++k) {
121 if (!wet[k]) continue;
122 if (!any || eta[k] > maxEta) { maxEta = eta[k]; any = true; }
123 }
124
125 double blend;
126 if (nWet == 3) {
127 // All corners wet — the signed-depth blend equals η_blend − ground
128 // algebraically; computed in sd space so the fully-wet case stays
129 // bit-identical to the pre-extrapolation implementation.
130 blend = w * sd0 + v * sd1 + u * sd2;
131 } else {
132 // Renormalized wet-corner blend: η is the weight-renormalized average
133 // of the wet corners' η. On an all-wet edge this equals the plain
134 // barycentric lerp (continuous with fully-wet neighbours); toward a
135 // non-supplying corner the weights shrink together, so η holds level
136 // (zero gradient in the dry direction) and depth = max(0, η − ground)
137 // lands the waterline at the sub-cell bed intercept — the surface
138 // extends flat to the wall face instead of stopping at a cell edge.
139 double wetW = 0.0, wetE = 0.0;
140 const double wgt[3] = { w, v, u };
141 for (int k = 0; k < 3; ++k) {
142 if (!wet[k]) continue;
143 wetW += wgt[k];
144 wetE += wgt[k] * eta[k];
145 }
146 // Degenerate weight mass (sample at/beyond the dry corner, where the
147 // wet weights cancel): fall back to the driving head — the cap and
148 // the 0-floor still confine the result to the physical band.
149 const double etaS = (wetW > 1e-12) ? wetE / wetW : maxEta;
150 blend = etaS - groundInterp;
151 }
152
153 const double capDepth = maxEta - groundInterp;
154 return std::max(0.0, std::min(blend, capDepth));
155}
156
157} // namespace CellSurfaceInterp
158
159#endif // CELL_SURFACE_INTERP_H
int e
Definition inpmeshreader.cpp:41
ArrowPlacement p
Definition linesymbollayer.cpp:27
int w
Definition mesh2dresultsexport.cpp:387
int k
Definition mesh2dresultsexport.cpp:549
int b
local residual indices, a < b
Definition meshquadmatch.cpp:46
int a
Definition meshquadmatch.cpp:46
Definition cellsurfaceinterp.h:46
double depthAt(const QPointF &p, const QPointF &a, const QPointF &b, const QPointF &c, double z0, double z1, double z2, double sd0, double sd1, double sd2, bool *degenerate=nullptr)
Water depth at p inside the triangle (a,b,c).
Definition cellsurfaceinterp.h:74
QVector< int > v
pool vertex indices
Definition pslgminsize.cpp:159