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
meshresolution.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2
12#ifndef OPENSWMM_MESH_RESOLUTION_H
13#define OPENSWMM_MESH_RESOLUTION_H
14
15#include <QJsonObject>
16#include "terrainpolicy.h"
17#include <QString>
18#include <algorithm>
19#include <cmath>
20#include <optional>
21
22namespace mesh
23{
24
25// Shared by project settings, Preferences and the generation dialog.
26// Physical lengths are SI; absence means no maximum, inherit minimum,
27// automatic tolerance, or match-minimum averaging respectively.
29 double minimumM = 6.096;
33 int coarsenPasses = 0;
34 double transition = 2.0;
37 std::optional<double> minimumEdgeM;
38 CoarseningOrder coarseningOrder=CoarseningOrder::LegacyFlatness;
39 TerrainTolerancePolicy terrainTolerancePolicy; // SI metres, independent of display units.
40
41 bool refineFeatures = false, alignTerrain = true;
44
54 QString validate() const
55 {
56 auto positive = [](double v) { return std::isfinite(v) && v > 0 && v <= 1e12; };
57 if (int(sizing) < 0 || int(sizing) > 2)
58 return QStringLiteral("Invalid sizing rules version or mode.");
59 if(int(cellPlanning)<0 || int(cellPlanning)>1)
60 return QStringLiteral("Invalid cell planning policy.");
62 return QStringLiteral("Unified cell planning requires verified or strict sizing rules.");
63 if(coarseningOrder!=CoarseningOrder::LegacyFlatness && coarseningOrder!=CoarseningOrder::ResolutionAware)
64 return QStringLiteral("Invalid coarsening policy version or order.");
66 return QStringLiteral("Invalid resolution-weighted terrain tolerance policy.");
67 if((coarseningOrder==CoarseningOrder::ResolutionAware || terrainTolerancePolicy.mode==TerrainToleranceMode::TargetSize) && sizing==Sizing::Legacy)
68 return QStringLiteral("Resolution-weighted terrain or coarsening requires verified sizing.");
69 if(terrainTolerancePolicy.mode==TerrainToleranceMode::TargetSize) {
70 if(terrain!=Terrain::Adaptive)return QStringLiteral("Size-weighted tolerance requires adaptive terrain refinement.");
72 return QStringLiteral("The terrain tolerance floor exceeds its resolved cap.");
73 }
74 if (minimumEdgeM && !positive(*minimumEdgeM))
75 return QStringLiteral("The separate minimum edge requirement must be a positive finite length.");
77 return QStringLiteral("Choose verified or strict sizing to request a minimum edge length.");
78 if (!positive(minimumM))
79 return QStringLiteral("Minimum target cell size must be a positive finite length.");
82 if (v && !positive(*v))
83 return QStringLiteral(
84 "Specified sizes and tolerances must be positive finite lengths.");
85 if (coarsenPasses < 0 || coarsenPasses > 10)
86 return QStringLiteral("Coarsening passes must be between 0 and 10.");
87 if (maxBreaklines < 0 || maxBreaklines > 10000000)
88 return QStringLiteral("Terrain breakline count is out of range.");
89 if (maximumM && *maximumM < minimumM)
90 return QStringLiteral(
91 "Maximum target cell size must be at least the minimum target size.");
93 return QStringLiteral("Feature target size must be at least the minimum target size.");
95 return QStringLiteral(
96 "Feature target size exceeds the maximum target size. Increase the maximum or reduce the feature target.");
97 if (!std::isfinite(transition) || transition < 1.05)
98 return QStringLiteral("Size transition rate must be finite and at least 1.05.");
99 return {};
100 }
101
109 QJsonObject toJson() const
110 {
111 auto value = [](std::optional<double> v) {
112 return v ? QJsonValue(*v) : QJsonValue(QJsonValue::Null);
113 };
114 return {{"coarseningPolicy",QJsonObject{{"version",1},{"order",int(coarseningOrder)}}},
115 {"terrainTolerancePolicy",QJsonObject{{"version",1},{"mode",int(terrainTolerancePolicy.mode)},
117 {"maximumM",terrainTolerancePolicy.maximumTolerance}}}, {"sizingVersion", 1}, {"sizingMode", int(sizing)},
118 {"cellPlanningVersion",1},{"cellPlanningMode",int(cellPlanning)},
119 {"minimumEdgeM", value(minimumEdgeM)}, {"coarsenPasses", coarsenPasses},
120 {"minimumM", minimumM},
121 {"maximumM", value(maximumM)},
122 {"featureM", value(featureM)},
123 {"elevationToleranceM", value(toleranceM)},
124 {"breaklineToleranceM", value(breaklineToleranceM)},
125 {"averagingM", value(averagingM)},
126 {"minimumBreaklineLengthM", value(minimumBreaklineLengthM)},
127 {"maxBreaklines", maxBreaklines},
128 {"transition", transition},
129 {"refineFeatures", refineFeatures},
130 {"alignTerrain", alignTerrain},
131 {"terrain", terrain == Terrain::Adaptive ? "adaptive"
132 : terrain == Terrain::Legacy ? "legacy"
133 : "off"},
134 {"reference", reference == Reference::Averaged ? "averaged"
135 : reference == Reference::Full ? "full"
136 : "direct"}};
137 }
138
149 static ResolutionSettings fromJson(const QJsonObject &o)
150 {
152 auto value = [&](const char *key) -> std::optional<double> {
153 const auto v = o.value(QLatin1String(key));
154 return v.isDouble() ? std::optional<double>(v.toDouble()) : std::nullopt;
155 };
156 r.coarsenPasses = o.value("coarsenPasses").toInt(0);
157 const auto coarsening=o.value("coarseningPolicy").toObject();
158 r.coarseningOrder=CoarseningOrder(coarsening.value("order").toInt(0));
159 if(!coarsening.isEmpty() && coarsening.value("version").toInt()!=1)r.coarseningOrder=CoarseningOrder(-1);
160 const auto tolerancePolicy=o.value("terrainTolerancePolicy").toObject();
161 r.terrainTolerancePolicy.mode=TerrainToleranceMode(tolerancePolicy.value("mode").toInt(0));
162 if(!tolerancePolicy.isEmpty() && tolerancePolicy.value("version").toInt()!=1)r.terrainTolerancePolicy.mode=TerrainToleranceMode(-1);
163 r.terrainTolerancePolicy.referenceSize=tolerancePolicy.value("referenceSizeM").toDouble(10);
164 r.terrainTolerancePolicy.minimumTolerance=tolerancePolicy.value("minimumM").toDouble(0);
165 r.terrainTolerancePolicy.maximumTolerance=tolerancePolicy.value("maximumM").toDouble(0);
166
167 r.sizing = Sizing(o.value("sizingMode").toInt(0));
168 r.cellPlanning=CellPlanning(o.value("cellPlanningMode").toInt(0));
169 if(o.contains("cellPlanningVersion") && o.value("cellPlanningVersion").toInt()!=1)r.cellPlanning=CellPlanning(-1);
170 if (o.contains("sizingVersion") && o.value("sizingVersion").toInt() != 1)
171 r.sizing = Sizing(-1);
172 r.minimumEdgeM = value("minimumEdgeM");
173 r.minimumM = o.value("minimumM").toDouble(r.minimumM);
174 r.maximumM = value("maximumM");
175 r.featureM = value("featureM");
176 r.toleranceM = value("elevationToleranceM");
177 r.breaklineToleranceM = value("breaklineToleranceM");
178 r.minimumBreaklineLengthM = value("minimumBreaklineLengthM");
179 r.maxBreaklines = o.value("maxBreaklines").toInt(0);
180 r.averagingM = value("averagingM");
181 r.transition = o.value("transition").toDouble(r.transition);
182 r.refineFeatures = o.value("refineFeatures").toBool(false);
183 r.alignTerrain = o.value("alignTerrain").toBool(true);
184 const QString mode = o.value("terrain").toString(), ref = o.value("reference").toString();
185 r.terrain = mode == "off" ? Terrain::Off
186 : mode == "legacy" ? Terrain::Legacy
188 r.reference = ref == "direct" ? Reference::Direct
189 : ref == "full" ? Reference::Full
191 return r;
192 }
193
194 // Version 1 stored distance controls in metres and combo choices as indices.
210 static ResolutionSettings migrate(const QJsonObject &c, ResolutionSettings r, double extentM)
211 {
212 r.coarsenPasses = 0;
213 r.coarseningOrder=CoarseningOrder::LegacyFlatness;
217 r.minimumEdgeM.reset();
218 double feature = c.value("meshCellSizeSpin").toDouble(r.featureM.value_or(r.minimumM));
219 if (feature <= 0)
220 feature = extentM > 0 ? extentM / 100.0 : 1.0;
221 r.featureM = feature;
222 r.minimumM = c.value("meshMinCellSizeSpin").toDouble(r.minimumM);
223 if (r.minimumM <= 0)
224 r.minimumM = feature / 4;
225 r.maximumM = feature * c.value("meshCoarsenSpin").toDouble(1000.0);
226 const double tol = c.value("meshTerrainTolSpin").toDouble(r.toleranceM.value_or(0));
227 r.toleranceM = tol > 0 ? std::optional<double>(tol) : std::nullopt;
229 r.refineFeatures = c.value("meshRefineFeaturesBox").toBool(r.refineFeatures);
230 r.alignTerrain = c.value("meshTerrainBreaklinesBox").toBool(r.alignTerrain);
231 r.maxBreaklines = c.value("meshMaxBreaklinesSpin").toInt(0);
232 r.transition = c.value("meshSizeRatioSpin").toDouble(r.transition);
233 const int mode = c.value("meshTerrainModeCombo").toInt(0),
234 ref = c.value("meshTerrainReferenceCombo").toInt(0);
236 r.reference = ref == 2 ? Reference::Direct
237 : ref == 1 ? Reference::Full
239 // Legacy zero explicitly disabled refinement, unlike adaptive auto.
240 if (r.terrain == Terrain::Legacy && !r.toleranceM)
242 return r;
243 }
244};
245}
246#endif
Definition meshcommands.h:38
int feature
Definition constraintaudit.cpp:156
NumberFormatMode mode
Definition numberformat.cpp:124
double value
Definition rasterfluxintegration.cpp:27
Definition meshresolution.h:28
CellPlanning
Definition meshresolution.h:36
enum mesh::ResolutionSettings::CellPlanning cellPlanning
Reference
Definition meshresolution.h:43
enum mesh::ResolutionSettings::Reference reference
std::optional< double > toleranceM
Definition meshresolution.h:30
Sizing
Definition meshresolution.h:35
QJsonObject toJson() const
Serialize every resolution field into the current project JSON schema.
Definition meshresolution.h:109
double minimumM
Definition meshresolution.h:29
double transition
Definition meshresolution.h:34
QString validate() const
Check numeric mesh-resolution settings without modifying or normalizing them.
Definition meshresolution.h:54
bool alignTerrain
Definition meshresolution.h:41
TerrainTolerancePolicy terrainTolerancePolicy
Definition meshresolution.h:39
enum mesh::ResolutionSettings::Sizing sizing
CoarseningOrder coarseningOrder
Definition meshresolution.h:38
std::optional< double > minimumEdgeM
Definition meshresolution.h:37
std::optional< double > breaklineToleranceM
Definition meshresolution.h:30
std::optional< double > minimumBreaklineLengthM
Definition meshresolution.h:31
static ResolutionSettings fromJson(const QJsonObject &o)
Decode current-schema resolution fields using defaults for missing or mismatched values.
Definition meshresolution.h:149
std::optional< double > maximumM
Definition meshresolution.h:30
std::optional< double > featureM
Definition meshresolution.h:30
int maxBreaklines
Definition meshresolution.h:32
enum mesh::ResolutionSettings::Terrain terrain
int coarsenPasses
Absent in older projects: retain their original mesh behaviour.
Definition meshresolution.h:33
bool refineFeatures
Definition meshresolution.h:41
Terrain
Definition meshresolution.h:42
static ResolutionSettings migrate(const QJsonObject &c, ResolutionSettings r, double extentM)
Overlay version-1 generation-dialog controls onto a supplied settings value.
Definition meshresolution.h:210
std::optional< double > averagingM
Definition meshresolution.h:30
Definition terrainpolicy.hpp:15
bool valid() const
Definition terrainpolicy.hpp:21
double tolerance(double referenceTolerance, double h) const
Definition terrainpolicy.hpp:30
double minimumTolerance
Definition terrainpolicy.hpp:18
TerrainToleranceMode mode
Definition terrainpolicy.hpp:16
double referenceSize
Definition terrainpolicy.hpp:17
double maximumTolerance
Definition terrainpolicy.hpp:19
double c
Definition terrainerrorfield.cpp:42