31#ifndef OPENSWMMVIS_CONTOUR_MARCHINGTRIANGLES_H
32#define OPENSWMMVIS_CONTOUR_MARCHINGTRIANGLES_H
53 struct Stop {
double t; quint8 r, g,
b; };
54 static const Stop stops[] = {
55 {0.00, 0x44, 0x01, 0x54},
56 {0.25, 0x3b, 0x52, 0x8b},
57 {0.50, 0x21, 0x91, 0x8c},
58 {0.75, 0x5e, 0xc9, 0x62},
59 {1.00, 0xfd, 0xe7, 0x25},
61 constexpr int N = int(
sizeof(stops) /
sizeof(*stops));
62 t = std::clamp(
t, 0.0, 1.0);
64 while (
i < N - 2 && stops[
i + 1].
t <=
t) ++
i;
65 const Stop &lo = stops[
i], &hi = stops[
i + 1];
66 const double f = (hi.t > lo.t) ? (
t - lo.t) / (hi.t - lo.t) : 0.0;
67 const int r = int(lo.r + f * (hi.r - lo.r) + 0.5);
68 const int g = int(lo.g + f * (hi.g - lo.g) + 0.5);
69 const int b = int(lo.b + f * (hi.b - lo.b) + 0.5);
70 return QColor(std::clamp(r, 0, 255),
71 std::clamp(g, 0, 255),
72 std::clamp(
b, 0, 255));
104template <
typename TriRange,
typename Extract>
105std::vector<IsoLineSegment>
107 const std::vector<double> &levels,
110 std::vector<IsoLineSegment> out;
111 if (levels.empty())
return out;
113 out.reserve( levels.size() * 32);
118 for (
const auto &
t : tris) {
119 extract(
t, p0, p1, p2, v0, v1, v2);
123 const double vMin = std::min({v0, v1, v2});
124 const double vMax = std::max({v0, v1, v2});
125 if (!(vMax > vMin))
continue;
127 for (
const double level : levels) {
128 if (level < vMin || level > vMax)
continue;
132 const int below = (v0 < level ? 1 : 0)
133 | (v1 < level ? 2 : 0)
134 | (v2 < level ? 4 : 0);
135 if (below == 0 || below == 7)
continue;
140 QPointF endpoints[2];
143 auto cross = [&](
const QPointF &pa,
double va,
144 const QPointF &pb,
double vb) {
145 const double denom =
vb -
va;
150 const double t = (level -
va) / denom;
151 endpoints[
k++] = QPointF(pa.x() +
t * (pb.x() - pa.x()),
152 pa.y() +
t * (pb.y() - pa.y()));
155 const bool b0 = (below & 1);
156 const bool b1 = (below & 2);
157 const bool b2 = (below & 4);
159 if (b0 != b1) cross(p0, v0, p1, v1);
160 if (b1 != b2) cross(p1, v1, p2, v2);
161 if (b2 != b0) cross(p2, v2, p0, v0);
169 out.push_back({endpoints[0], endpoints[1], level});
185inline std::vector<double>
188 std::vector<double> out;
189 if (
count < 1 || !(vMax > vMin))
return out;
190 out.reserve(
size_t(
count));
191 const double step = (vMax - vMin) /
double(
count + 1);
193 out.push_back(vMin +
step *
double(
i));
206inline std::vector<double>
209 std::vector<double> out;
210 if (levelCount < 2 || !(vMax > vMin))
return out;
211 out.reserve(
size_t(levelCount));
212 const double step = (vMax - vMin) /
double(levelCount - 1);
213 for (
int i = 0;
i < levelCount; ++
i)
214 out.push_back(vMin +
step *
double(
i));
243 const std::vector<double> &inVals,
246 std::vector<QPointF> &outPts,
247 std::vector<double> &outVals)
251 const size_t n = inPts.size();
254 auto isInside = [&](
double v) {
255 return keepAbove ? (
v >= L) : (
v <= L);
258 for (
size_t i = 0;
i <
n; ++
i) {
259 const size_t j = (
i + 1) %
n;
260 const QPointF &pi = inPts[
i], &pj = inPts[j];
261 const double vi = inVals[
i], vj = inVals[j];
262 const bool inI = isInside(vi);
263 const bool inJ = isInside(vj);
266 outPts.push_back(pi);
267 outVals.push_back(vi);
270 const double denom = vj - vi;
272 outPts.push_back(pi);
273 outVals.push_back(L);
275 const double t = (L - vi) / denom;
276 outPts.push_back(QPointF(pi.x() +
t * (pj.x() - pi.x()),
277 pi.y() +
t * (pj.y() - pi.y())));
278 outVals.push_back(L);
302template <
typename TriRange,
typename Extract>
303std::vector<IsoBandPolygon>
305 const std::vector<double> &levels,
307 bool clampUniformOutsideRange =
true)
309 std::vector<IsoBandPolygon> out;
310 if (levels.size() < 2)
return out;
311 out.reserve( levels.size() * 32);
317 std::vector<QPointF>
a,
b;
318 std::vector<double> aV, bV;
319 a.reserve(8);
b.reserve(8);
320 aV.reserve(8); bV.reserve(8);
322 for (
const auto &
t : tris) {
323 extract(
t, p0, p1, p2, v0, v1, v2);
325 const double vMin = std::min({v0, v1, v2});
326 const double vMax = std::max({v0, v1, v2});
327 if (!(vMax > vMin)) {
340 if (!clampUniformOutsideRange
341 && (vMin < levels.front() || vMin > levels.back()))
343 const int nb = int(levels.size()) - 1;
344 int k = int(std::upper_bound(levels.begin() + 1, levels.end() - 1,
346 - (levels.begin() + 1));
347 k = std::clamp(
k, 0, nb - 1);
349 bp.
verts = {p0, p1, p2};
351 bp.
bandHi = levels[size_t(
k) + 1];
353 out.push_back(std::move(bp));
357 for (
size_t k = 0;
k + 1 < levels.size(); ++
k) {
358 const double L1 = levels[
k];
359 const double L2 = levels[
k + 1];
360 if (L2 < vMin || L1 > vMax)
continue;
361 if (!(L2 > L1))
continue;
378 out.push_back(std::move(bp));
size_t i
Definition contourjob.cpp:27
DiagramType t
Definition diagramspec.cpp:20
int vb
Definition inpmeshreader.cpp:49
int va
Definition inpmeshreader.cpp:49
std::size_t n
Definition mesh2dresultsexport.cpp:426
int k
Definition mesh2dresultsexport.cpp:549
double step
Definition meshcellparams.cpp:28
int b
local residual indices, a < b
Definition meshquadmatch.cpp:46
int a
Definition meshquadmatch.cpp:46
void clipHalfplane(const std::vector< QPointF > &inPts, const std::vector< double > &inVals, double L, bool keepAbove, std::vector< QPointF > &outPts, std::vector< double > &outVals)
Sutherland-Hodgman clip of a convex polygon against the half-plane defined by value >= L (when keepAb...
Definition marchingtriangles.h:242
Definition contourchain.h:23
std::vector< IsoLineSegment > marchingTriangles(const TriRange &tris, const std::vector< double > &levels, Extract extract)
Generate iso-line segments for every (triangle, level) pair where the level crosses the triangle's va...
Definition marchingtriangles.h:106
std::vector< double > evenlySpacedLevels(double vMin, double vMax, int count)
Convenience helper that generates N evenly-spaced contour levels between vMin and vMax (exclusive of ...
Definition marchingtriangles.h:186
std::vector< double > evenlySpacedLevelsInclusive(double vMin, double vMax, int levelCount)
Convenience helper that returns levelCount evenly-spaced break levels INCLUSIVE of both endpoints (vM...
Definition marchingtriangles.h:207
std::vector< IsoBandPolygon > marchingTrianglesIsobands(const TriRange &tris, const std::vector< double > &levels, Extract extract, bool clampUniformOutsideRange=true)
Generate filled iso-band polygons for every (triangle, band) pair.
Definition marchingtriangles.h:304
QColor viridisAt(double t)
Sample a 5-stop Viridis-inspired colour ramp at t in [0, 1].
Definition marchingtriangles.h:51
QVector< int > v
pool vertex indices
Definition pslgminsize.cpp:159
One filled-isoband polygon in scene space. Convex (Sutherland- Hodgman of a triangle yields a convex ...
Definition marchingtriangles.h:222
double bandHi
upper break level
Definition marchingtriangles.h:225
std::vector< QPointF > verts
convex polygon vertices in order
Definition marchingtriangles.h:223
int bandIndex
Definition marchingtriangles.h:226
double bandLo
lower break level
Definition marchingtriangles.h:224
A single contour iso-line segment in scene space.
Definition marchingtriangles.h:77
double level
the iso-level this segment was generated for
Definition marchingtriangles.h:80
QPointF a
Definition marchingtriangles.h:78
QPointF b
Definition marchingtriangles.h:79