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
meshquadquality.h
Go to the documentation of this file.
1
16#ifndef OPENSWMMVIS_MESH_MESHQUADQUALITY_H
17#define OPENSWMMVIS_MESH_MESHQUADQUALITY_H
18
19#include "mesh/meshresult.h"
20
21#include <QPointF>
22#include <QVector>
23#include <algorithm>
24#include <cmath>
25#include <limits>
26
27namespace mesh {
28
33{
34 double minAngleDeg = 60.0;
35 double maxAngleDeg = 120.0;
36 double minScaledJacobian = 0.866;
37 double maxAspect = 2.0;
38};
39
41{
42 double minAngleDeg = 0.0;
43 double maxAngleDeg = 0.0;
44 double scaledJacobian = 0.0;
45 double rectangularity = 0.0;
46 double aspect = 1.0;
47 double skew = 0.0;
48 double area = 0.0;
49 bool convex = false;
50};
51
53inline QuadQuality quadQuality(const QPointF &a, const QPointF &b,
54 const QPointF &c, const QPointF &d)
55{
57 const QPointF p[4] = {a, b, c, d};
58 double area2 = 0.0;
59 for (int i = 0; i < 4; ++i)
60 {
61 const QPointF &u = p[i], &v = p[(i + 1) % 4];
62 area2 += u.x() * v.y() - v.x() * u.y();
63 }
64 q.area = 0.5 * std::abs(area2);
65 const double orient = area2 >= 0.0 ? 1.0 : -1.0;
66
67 q.minAngleDeg = 360.0; q.maxAngleDeg = 0.0;
68 q.scaledJacobian = 2.0;
69 q.convex = true;
70 double maxDev = 0.0;
71 double side[4];
72 for (int i = 0; i < 4; ++i)
73 {
74 const QPointF &prev = p[(i + 3) % 4], &cur = p[i], &next = p[(i + 1) % 4];
75 const QPointF e1 = prev - cur, e2 = next - cur;
76 const double l1 = std::hypot(e1.x(), e1.y()), l2 = std::hypot(e2.x(), e2.y());
77 side[i] = l2;
78 if (l1 <= 0.0 || l2 <= 0.0) { q.convex = false; q.scaledJacobian = 0.0; continue; }
79 const double cross = e2.x() * e1.y() - e2.y() * e1.x(); // sign: + when turning consistently with `orient`
80 const double dot = e1.x() * e2.x() + e1.y() * e2.y();
81 const double ang = std::atan2(std::abs(cross), dot) * 180.0 / M_PI;
82 const double sj = cross * orient / (l1 * l2); // signed sine of the interior angle
83 if (sj <= 0.0) q.convex = false;
84 q.scaledJacobian = std::min(q.scaledJacobian, sj);
85 q.minAngleDeg = std::min(q.minAngleDeg, ang);
86 q.maxAngleDeg = std::max(q.maxAngleDeg, ang);
87 maxDev = std::max(maxDev, std::abs(ang - 90.0));
88 }
89 q.scaledJacobian = std::min(q.scaledJacobian, 1.0); // rounding can give sin θ = 1 + ε for a rectangle
90 q.rectangularity = std::max(0.0, 1.0 - maxDev / 90.0);
91 const double s02 = 0.5 * (side[0] + side[2]), s13 = 0.5 * (side[1] + side[3]);
92 const double lo = std::min(s02, s13), hi = std::max(s02, s13);
93 q.aspect = lo > 0.0 ? hi / lo : std::numeric_limits<double>::infinity();
94 const QPointF d1 = c - a, d2 = d - b;
95 const double ld1 = std::hypot(d1.x(), d1.y()), ld2 = std::hypot(d2.x(), d2.y());
96 q.skew = (ld1 > 0.0 && ld2 > 0.0)
97 ? std::abs((d1.x() * d2.x() + d1.y() * d2.y()) / (ld1 * ld2)) : 1.0;
98 return q;
99}
100
102inline QuadQuality quadQuality(const QVector<MeshVertex> &vertices, const MeshTriangle &t)
103{
104 return quadQuality(vertices[t.v0].xy, vertices[t.v1].xy,
105 vertices[t.v2].xy, vertices[t.v3].xy);
106}
107
109inline bool quadAcceptable(const QuadQuality &q, const QuadQualityBounds &b)
110{
111 if (!q.convex) return false;
112 if (q.minAngleDeg < b.minAngleDeg || q.maxAngleDeg > b.maxAngleDeg) return false;
113 if (q.scaledJacobian < b.minScaledJacobian) return false;
114 if (b.maxAspect > 0.0 && q.aspect > b.maxAspect) return false;
115 return true;
116}
117
120inline double quadScore(const QuadQuality &q, const QuadQualityBounds &b)
121{
122 if (!q.convex || q.scaledJacobian <= 0.0) return 0.0;
123 const double aspectTerm = (b.maxAspect > 0.0 && q.aspect > b.maxAspect)
124 ? b.maxAspect / q.aspect : 1.0;
125 return q.scaledJacobian * aspectTerm * std::sqrt(std::max(0.0, 1.0 - q.skew));
126}
127
131inline double triangleScaledJacobian(const QPointF &a, const QPointF &b, const QPointF &c)
132{
133 const QPointF p[3] = {a, b, c};
134 double mn = 2.0;
135 double area2 = (b.x() - a.x()) * (c.y() - a.y()) - (c.x() - a.x()) * (b.y() - a.y());
136 const double orient = area2 >= 0.0 ? 1.0 : -1.0;
137 for (int i = 0; i < 3; ++i)
138 {
139 const QPointF e1 = p[(i + 2) % 3] - p[i], e2 = p[(i + 1) % 3] - p[i];
140 const double l1 = std::hypot(e1.x(), e1.y()), l2 = std::hypot(e2.x(), e2.y());
141 if (l1 <= 0.0 || l2 <= 0.0) return 0.0;
142 mn = std::min(mn, (e2.x() * e1.y() - e2.y() * e1.x()) * orient / (l1 * l2));
143 }
144 return std::min(mn, 1.0);
145}
146
148inline double cellCornerAngleDeg(const QVector<MeshVertex> &v, const MeshTriangle &t, int i)
149{
150 const int n = t.vertexCount();
151 const QPointF &prev = v[t.vertex((i + n - 1) % n)].xy;
152 const QPointF &cur = v[t.vertex(i)].xy;
153 const QPointF &next = v[t.vertex((i + 1) % n)].xy;
154 const QPointF e1 = prev - cur, e2 = next - cur;
155 return std::atan2(std::abs(e2.x() * e1.y() - e2.y() * e1.x()),
156 e1.x() * e2.x() + e1.y() * e2.y()) * 180.0 / M_PI;
157}
158
159} // namespace mesh
160
161#endif // OPENSWMMVIS_MESH_MESHQUADQUALITY_H
size_t i
Definition contourjob.cpp:27
DiagramType t
Definition diagramspec.cpp:20
ArrowPlacement p
Definition linesymbollayer.cpp:27
std::size_t n
Definition mesh2dresultsexport.cpp:426
int b
local residual indices, a < b
Definition meshquadmatch.cpp:46
int a
Definition meshquadmatch.cpp:46
Definition meshcommands.h:302
QuadQuality quadQuality(const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d)
Metrics for corners a,b,c,d in cyclic order.
Definition meshquadquality.h:53
bool quadAcceptable(const QuadQuality &q, const QuadQualityBounds &b)
Hard acceptance test (convex + angle bounds + SJ floor + aspect cap).
Definition meshquadquality.h:109
double quadScore(const QuadQuality &q, const QuadQualityBounds &b)
Combined score in [0,1] (plan §5): SJ · min(1, aspectMax/aspect) · sqrt(1 - skew)....
Definition meshquadquality.h:120
double cellCornerAngleDeg(const QVector< MeshVertex > &v, const MeshTriangle &t, int i)
Interior angle at corner i of a cell (degrees), triangles and quads.
Definition meshquadquality.h:148
double triangleScaledJacobian(const QPointF &a, const QPointF &b, const QPointF &c)
Minimum sine of a triangle's angles (1 is unattainable; equilateral = 0.866; right isosceles = 0....
Definition meshquadquality.h:131
QVector< int > v
pool vertex indices
Definition pslgminsize.cpp:159
A cell in the mesh — a triangle or (since the engine's mixed tri-quad meshes, workplans/TRI_QUAD_MESH...
Definition meshresult.h:54
Acceptance bounds shared by pairing, cleanup, smoothing and the legacy tri-pair merge....
Definition meshquadquality.h:33
double minAngleDeg
Definition meshquadquality.h:34
double maxAspect
longest / shortest side (opposite-side means). <= 0 = unbounded.
Definition meshquadquality.h:37
double maxAngleDeg
Definition meshquadquality.h:35
double minScaledJacobian
Definition meshquadquality.h:36
Definition meshquadquality.h:41
bool convex
all four cross products share the sign of the total area.
Definition meshquadquality.h:49
double aspect
mean(s0,s2) vs mean(s1,s3), >= 1.
Definition meshquadquality.h:46
double scaledJacobian
min_i sin(theta_i), signed (negative = folded).
Definition meshquadquality.h:44
double maxAngleDeg
Definition meshquadquality.h:43
double rectangularity
1 - max_i |theta_i - 90| / 90.
Definition meshquadquality.h:45
double skew
|cos(angle between diagonals)|, 0 for a rectangle.
Definition meshquadquality.h:47
double minAngleDeg
Definition meshquadquality.h:42
double area
shoelace, absolute.
Definition meshquadquality.h:48