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
meshcellgeom.h
Go to the documentation of this file.
1
23#ifndef OPENSWMMVIS_MESH_MESHCELLGEOM_H
24#define OPENSWMMVIS_MESH_MESHCELLGEOM_H
25
26#include "mesh/meshresult.h"
27
28#include <QPointF>
29#include <QVector>
30
31#include <array>
32#include <cmath>
33
34namespace mesh {
35
37constexpr int kEdgeStride = 4;
38
40constexpr int edgeSlot(int cell, int e) noexcept { return cell * kEdgeStride + e; }
42constexpr int slotCell(int slot) noexcept { return slot / kEdgeStride; }
43constexpr int slotLocal(int slot) noexcept { return slot % kEdgeStride; }
45constexpr int edgeSlotCount(int nCells) noexcept { return nCells * kEdgeStride; }
46
48inline void edgeEndpoints(const MeshTriangle &t, int k, int &a, int &b) noexcept
49{
50 const int nv = t.vertexCount();
51 a = t.vertex((k + 1) % nv);
52 b = t.vertex((k + 2) % nv);
53}
54
68inline bool rt0CellDischarge(int cell, int nv,
69 const float *flux, const float *length,
70 const float *nx, const float *ny,
71 double &qx, double &qy) noexcept
72{
73 constexpr double kQMax = 10.0;
74 double a00 = 0.0, a01 = 0.0, a11 = 0.0; // NᵀN entries
75 double b0 = 0.0, b1 = 0.0; // Nᵀ b entries
76 for (int e = 0; e < nv; ++e) {
77 const int idx = edgeSlot(cell, e);
78 const double len = length[idx];
79 if (len <= 1e-12) continue;
80 double q = double(flux[idx]) / len;
81 if (!std::isfinite(q)) continue;
82 if (q > kQMax) q = kQMax;
83 if (q < -kQMax) q = -kQMax;
84 const double enx = nx[idx], eny = ny[idx];
85 a00 += enx * enx;
86 a01 += enx * eny;
87 a11 += eny * eny;
88 b0 += enx * q;
89 b1 += eny * q;
90 }
91 const double det = a00 * a11 - a01 * a01;
92 // NaN-robust degeneracy gate: `abs(NaN) < eps` is false, so the inverted
93 // form is required to reject the cell instead of emitting NaN.
94 if (!(std::abs(det) >= 1e-12)) return false;
95 const double inv_det = 1.0 / det;
96 qx = ( a11 * b0 - a01 * b1) * inv_det;
97 qy = (-a01 * b0 + a00 * b1) * inv_det;
98 return true;
99}
100
103{
104 double area = 0.0;
105 QPointF centroid;
106 double zMean = 0.0;
107 int nSub = 1;
108 std::array<std::array<int, 3>, 2> sub{};
109 int diagCase = 0;
110};
111
121inline CellGeom cellGeom(const QVector<MeshVertex> &vertices, const MeshTriangle &t)
122{
123 CellGeom g;
124 auto triArea = [&](int a, int b, int c) {
125 const QPointF &A = vertices[a].xy, &B = vertices[b].xy, &C = vertices[c].xy;
126 return 0.5 * std::abs((B.x() - A.x()) * (C.y() - A.y()) - (C.x() - A.x()) * (B.y() - A.y()));
127 };
128 auto triCentroid = [&](int a, int b, int c) {
129 const QPointF &A = vertices[a].xy, &B = vertices[b].xy, &C = vertices[c].xy;
130 return QPointF((A.x() + B.x() + C.x()) / 3.0, (A.y() + B.y() + C.y()) / 3.0);
131 };
132 if (!t.isQuad()) {
133 g.nSub = 1;
134 g.sub[0] = {t.v0, t.v1, t.v2};
135 g.area = triArea(t.v0, t.v1, t.v2);
136 g.centroid = triCentroid(t.v0, t.v1, t.v2);
137 g.zMean = (vertices[t.v0].z + vertices[t.v1].z + vertices[t.v2].z) / 3.0;
138 return g;
139 }
140 const int v[4] = {t.v0, t.v1, t.v2, t.v3};
141 // Elevation ordering of the cyclic positions (stable insertion sort).
142 int p[4] = {0, 1, 2, 3};
143 for (int i = 1; i < 4; ++i) {
144 const int key = p[i];
145 int j = i - 1;
146 while (j >= 0 && vertices[v[p[j]]].z > vertices[v[key]].z) { p[j + 1] = p[j]; --j; }
147 p[j + 1] = key;
148 }
149 const int n1 = p[0], n2 = p[1], n3 = p[2], n4 = p[3];
150 auto adjacent = [](int a, int b) { const int d = (a - b + 4) % 4; return d == 1 || d == 3; };
151 int t1[3], t2[3];
152 if (!adjacent(n1, n4)) { g.diagCase = 1; t1[0]=n1; t1[1]=n2; t1[2]=n4; t2[0]=n1; t2[1]=n3; t2[2]=n4; }
153 else if (adjacent(n2, n1)) { g.diagCase = 2; t1[0]=n1; t1[1]=n2; t1[2]=n4; t2[0]=n2; t2[1]=n3; t2[2]=n4; }
154 else { g.diagCase = 3; t1[0]=n1; t1[1]=n3; t1[2]=n4; t2[0]=n2; t2[1]=n3; t2[2]=n4; }
155 g.nSub = 2;
156 g.sub[0] = {v[t1[0]], v[t1[1]], v[t1[2]]};
157 g.sub[1] = {v[t2[0]], v[t2[1]], v[t2[2]]};
158 const double a1 = triArea(g.sub[0][0], g.sub[0][1], g.sub[0][2]);
159 const double a2 = triArea(g.sub[1][0], g.sub[1][1], g.sub[1][2]);
160 g.area = a1 + a2;
161 const QPointF c1 = triCentroid(g.sub[0][0], g.sub[0][1], g.sub[0][2]);
162 const QPointF c2 = triCentroid(g.sub[1][0], g.sub[1][1], g.sub[1][2]);
163 g.centroid = (g.area > 0.0)
164 ? QPointF((a1 * c1.x() + a2 * c2.x()) / g.area, (a1 * c1.y() + a2 * c2.y()) / g.area)
165 : QPointF((vertices[t.v0].xy + vertices[t.v1].xy + vertices[t.v2].xy + vertices[t.v3].xy) / 4.0);
166 g.zMean = (vertices[t.v0].z + vertices[t.v1].z + vertices[t.v2].z + vertices[t.v3].z) / 4.0;
167 return g;
168}
169
171inline double cellSignedArea(const QVector<MeshVertex> &vertices, const MeshTriangle &t) noexcept
172{
173 const int nv = t.vertexCount();
174 double s = 0.0;
175 for (int k = 0; k < nv; ++k) {
176 const QPointF &a = vertices[t.vertex(k)].xy, &b = vertices[t.vertex((k + 1) % nv)].xy;
177 s += a.x() * b.y() - b.x() * a.y();
178 }
179 return 0.5 * s;
180}
181
184inline bool cellIsConvex(const QVector<MeshVertex> &vertices, const MeshTriangle &t) noexcept
185{
186 if (!t.isQuad()) return true;
187 int sign = 0;
188 for (int k = 0; k < 4; ++k) {
189 const QPointF &p = vertices[t.vertex(k)].xy;
190 const QPointF &q = vertices[t.vertex((k + 1) % 4)].xy;
191 const QPointF &r = vertices[t.vertex((k + 2) % 4)].xy;
192 const double cr = (q.x() - p.x()) * (r.y() - q.y()) - (q.y() - p.y()) * (r.x() - q.x());
193 const int s = (cr > 0.0) ? 1 : (cr < 0.0) ? -1 : 0;
194 if (s == 0 || (sign != 0 && s != sign)) return false;
195 sign = s;
196 }
197 return true;
198}
199
201inline bool cellContains(const QVector<MeshVertex> &vertices, const MeshTriangle &t,
202 const QPointF &p, double eps = 0.0) noexcept
203{
204 const CellGeom g = cellGeom(vertices, t);
205 for (int s = 0; s < g.nSub; ++s) {
206 const QPointF &a = vertices[g.sub[s][0]].xy, &b = vertices[g.sub[s][1]].xy,
207 &c = vertices[g.sub[s][2]].xy;
208 const double d = (b.y() - c.y()) * (a.x() - c.x()) + (c.x() - b.x()) * (a.y() - c.y());
209 if (std::abs(d) < 1e-300) continue;
210 const double l1 = ((b.y() - c.y()) * (p.x() - c.x()) + (c.x() - b.x()) * (p.y() - c.y())) / d;
211 const double l2 = ((c.y() - a.y()) * (p.x() - c.x()) + (a.x() - c.x()) * (p.y() - c.y())) / d;
212 const double l3 = 1.0 - l1 - l2;
213 if (l1 >= -eps && l2 >= -eps && l3 >= -eps) return true;
214 }
215 return false;
216}
217
218} // namespace mesh
219
220#endif // OPENSWMMVIS_MESH_MESHCELLGEOM_H
size_t i
Definition contourjob.cpp:27
DiagramType t
Definition diagramspec.cpp:20
double s
Scene px per model length unit.
Definition inletdrawingview.cpp:82
int e
Definition inpmeshreader.cpp:41
ArrowPlacement p
Definition linesymbollayer.cpp:27
std::vector< double > nx
Definition mesh2dresultsexport.cpp:448
std::vector< double > ny
Definition mesh2dresultsexport.cpp:448
std::vector< double > len
Definition mesh2dresultsexport.cpp:448
int k
Definition mesh2dresultsexport.cpp:549
std::vector< int > cell
Definition mesh2dresultsexport.cpp:609
const char * key
Definition meshcellparams.cpp:24
int nv
Definition meshenginesync.cpp:32
double length
Definition meshpatch.cpp:64
int b
local residual indices, a < b
Definition meshquadmatch.cpp:46
int t1
Definition meshquadmatch.cpp:40
int a
Definition meshquadmatch.cpp:46
int t2
Definition meshquadmatch.cpp:40
Definition meshcommands.h:302
bool cellContains(const QVector< MeshVertex > &vertices, const MeshTriangle &t, const QPointF &p, double eps=0.0) noexcept
Point-in-cell test on the sub-triangle fan (barycentric per sub-triangle).
Definition meshcellgeom.h:201
void edgeEndpoints(const MeshTriangle &t, int k, int &a, int &b) noexcept
Definition meshcellgeom.h:48
bool rt0CellDischarge(int cell, int nv, const float *flux, const float *length, const float *nx, const float *ny, double &qx, double &qy) noexcept
RT0 least-squares specific discharge (m²/s) of one cell from its outward-positive normal edge fluxes ...
Definition meshcellgeom.h:68
CellGeom cellGeom(const QVector< MeshVertex > &vertices, const MeshTriangle &t)
Geometry of cell t against vertices.
Definition meshcellgeom.h:121
constexpr int edgeSlot(int cell, int e) noexcept
Definition meshcellgeom.h:40
constexpr int kEdgeStride
Definition meshcellgeom.h:37
double cellSignedArea(const QVector< MeshVertex > &vertices, const MeshTriangle &t) noexcept
Signed area of the polygon (positive = counter-clockwise).
Definition meshcellgeom.h:171
bool cellIsConvex(const QVector< MeshVertex > &vertices, const MeshTriangle &t) noexcept
Convexity test for a quad (every consecutive cross product has the same non-zero sign)....
Definition meshcellgeom.h:184
constexpr int slotLocal(int slot) noexcept
Definition meshcellgeom.h:43
constexpr int slotCell(int slot) noexcept
Definition meshcellgeom.h:42
constexpr int edgeSlotCount(int nCells) noexcept
Definition meshcellgeom.h:45
QVector< int > v
pool vertex indices
Definition pslgminsize.cpp:159
Per-cell derived geometry shared by every consumer.
Definition meshcellgeom.h:103
double zMean
mean of the vertex elevations
Definition meshcellgeom.h:106
std::array< std::array< int, 3 >, 2 > sub
sub-triangle vertex indices
Definition meshcellgeom.h:108
QPointF centroid
AREA centroid (not the vertex mean for a quad)
Definition meshcellgeom.h:105
int diagCase
B&S 2007 case (1..3) for a quad; 0 for a triangle.
Definition meshcellgeom.h:109
int nSub
sub-triangles: 1 (triangle) or 2 (quad)
Definition meshcellgeom.h:107
double area
planimetric (map units²)
Definition meshcellgeom.h:104
A cell in the mesh — a triangle or (since the engine's mixed tri-quad meshes, workplans/TRI_QUAD_MESH...
Definition meshresult.h:54
double
Definition swmmpollutantpropertyadapter.cpp:50