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
mixed.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2#pragma once
3#include "meshkit/job.hpp"
5#include "meshkit/blocks.hpp"
7#include "operation.hpp"
8#include <unordered_map>
9#include <cstring>
11{
12struct Coordinate {
13 std::uint64_t x = 0, y = 0;
14 bool operator==(const Coordinate &b) const { return x == b.x && y == b.y; }
15};
17 std::size_t operator()(Coordinate p) const
18 {
19 return p.x ^ (p.y + 0x9e3779b97f4a7c15ull + (p.x << 6) + (p.x >> 2));
20 }
21};
23{
24 double x = p.x() == 0 ? 0 : p.x(), y = p.y() == 0 ? 0 : p.y();
26 std::memcpy(&k.x, &x, 8);
27 std::memcpy(&k.y, &y, 8);
28 return k;
29}
31 std::vector<plan::PatchMesh> patches;
32 std::vector<int> regions;
33 std::vector<plan::PatchDecision> decisions;
34 std::vector<Point2> points;
35 std::vector<Path> extraPaths;
36 std::vector<std::vector<int>> boundarySources;
37 std::uint64_t cells = 0, sharedSides = 0;
38};
40 const std::function<double(const Box2 &)> &maximumSize,
41 const std::function<double(const Box2 &)> &tolerance,
42 Work &work, int attempt)
43{
45 out.points = r.points;
47 for (const auto &path : r.paths) {
48 plan::Polygon polygon;
49 for (auto index : path.vertices) {
50 if (index >= r.points.size())
51 fail("path_index", "Invalid source index before planning.");
52 polygon.append(r.points[index]);
53 }
54 if (path.kind == PathKind::Outer)
55 geometry.domains.append(polygon);
56 else if (path.kind == PathKind::Hole)
57 geometry.holes.append(polygon);
58 else
59 geometry.lines.append(polygon);
60 }
61 // Source identities that already lie on a required path are protected by its
62 // segment graph. Unattached mandatory points additionally constrain placement.
63 std::vector<bool> inPath(r.points.size(), false);
64 for (const auto &path : r.paths)
65 for (auto i : path.vertices)
66 inPath[i] = true;
67 for (std::size_t i = 0; i < r.points.size(); ++i)
68 if (!inPath[i])
69 geometry.pins.append(r.points[i]);
73 r.options.maximumSize > 0 ? r.options.maximumSize : std::max(1., r.options.minimumTarget);
74 options.maximumCells = r.options.limits.maxCells;
75 options.maximumPatchCells = r.options.maximumPatchCells;
76 options.maximumWorkspaceBytes = r.options.limits.maxWorkspaceBytes;
77 options.workBudget = r.options.limits.maxWork;
78 options.limits.minimumAngleDegrees = r.options.minimumAngleDegrees;
79 options.limits.minimumEdge = r.options.minimumEdge;
80 options.limits.maximumSize = maximumSize;
81 options.limits.cancelled = p.cancelled;
82 if (r.options.terrainTolerance > 0) {
83 options.limits.terrainTolerance = r.options.terrainTolerance;
84 options.limits.terrainToleranceForFootprint = tolerance;
85 options.limits.elevationAt = p.elevation;
86 options.limits.terrainBound = p.terrainBound;
87 }
90 bool first = true;
92 for (const auto &path : r.paths) {
94 for (auto i : path.vertices)
95 line.append(r.points[i]);
96 if (path.closed || path.kind != PathKind::Line)
97 line.append(line.first());
98 blockers.append(line);
99 if (path.kind == PathKind::Outer) {
102 first = false;
103 }
104 }
105 for (const auto &region : regions) {
106 auto line = plan::Vector<Point2>(region.ring);
107 if (!line.empty())
108 line.append(line.first());
109 blockers.append(line);
110 }
111 const double pitch =
112 std::max(4 * std::max(r.options.minimumTarget, options.defaultSize / 4),
113 std::max(bounds.width(), bounds.height()) / 256);
114 const auto grid =
115 plan::quadBlockGridFromField(bounds, pitch, maximumSize, blockers, p.cancelled);
116 if (!grid.isValid())
117 fail("planning_grid", "Automatic patch grid is invalid or cancelled.");
120 blocks.minSpacing = std::max(.5 * r.options.minimumTarget, 1e-9);
121 auto automatic = plan::placeQuadBlocks(grid, blocks);
122 int added = 0;
123 for (auto &region : automatic) {
124 const auto box = region.ring.boundingRect();
125 // Leave room for up to three rounds of terrain/metric refinement.
126 const double side =
127 region.spacing * std::sqrt(std::max(16., double(r.options.maximumPatchCells) / 64));
128 const int nx = std::max(1, int(std::ceil(box.width() / side))),
129 ny = std::max(1, int(std::ceil(box.height() / side)));
130 for (int y = 0; y < ny && added < blocks.maxBlocks; ++y)
131 for (int x = 0; x < nx && added < blocks.maxBlocks; ++x) {
132 work.tick();
133 auto tile = region;
134 const double gap = std::min(region.spacing,
135 .1 * std::min(box.width() / nx, box.height() / ny));
136 const double x0 = box.left() + x * box.width() / nx + (x ? gap : 0),
137 x1 = box.left() + (x + 1) * box.width() / nx -
138 (x + 1 < nx ? gap : 0);
139 const double y0 = box.top() + y * box.height() / ny + (y ? gap : 0),
140 y1 = box.top() + (y + 1) * box.height() / ny -
141 (y + 1 < ny ? gap : 0);
142 tile.ring = {{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}};
143 tile.automaticCandidate = true;
144 tile.isBackground = true;
145 regions.append(std::move(tile));
146 ++added;
147 }
148 }
149 }
151 options.allowQuads = false;
152 if (!r.fixedPatches.empty())
153 fail("quad_conflict", "Fixed quads conflict with triangles-only mode.");
154 }
155 geometry.fixedPatches = plan::Vector<plan::PatchMesh>(r.fixedPatches);
156 auto result = plan::planQuadRegions(regions, geometry, options);
157 work.tick(result.workUsed);
158 if (!result.ok)
159 fail("quad_plan", result.error,
160 result.cancelled ? RunStatus::Cancelled
161 : result.resourceLimited ? RunStatus::ResourceLimit
163 out.sharedSides = result.sharedSides;
164 out.decisions.assign(result.decisions.begin(), result.decisions.end());
165 for (const auto &fixed : r.fixedPatches) {
166 auto error = plan::validate(fixed);
167 if (!error.empty())
168 fail("fixed_patch", error);
169 const auto assessment = plan::assessPlannedPatch(fixed, options.limits);
170 if (!assessment.ok)
171 fail("fixed_patch", assessment.reason);
172 out.patches.push_back(fixed);
173 out.regions.push_back(-1);
174 }
175 for (std::size_t i = 0; i < result.patches.size(); ++i) {
176 out.patches.push_back(std::move(result.patches[i]));
177 out.regions.push_back(result.patchRegions[i]);
178 }
179 auto addRing = [&](const plan::Polygon &ring, PathKind kind, std::int64_t id) {
180 Path path;
181 path.kind = kind;
182 path.closed = true;
183 path.id = id;
184 for (auto point : ring) {
185 if (!finite(point))
186 fail("region_geometry", "Nonfinite region coordinate.");
187 path.vertices.push_back(Index(out.points.size()));
188 out.points.push_back(point);
189 }
190 out.extraPaths.push_back(std::move(path));
191 };
192 for (std::size_t i = 0; i < regions.size(); ++i)
193 if (!regions[i].isBackground && !regions[i].automaticCandidate)
194 addRing(regions[i].ring, PathKind::Region, -std::int64_t(i + 1));
195 for (const auto &patch : out.patches) {
196 out.cells += patch.quads.size();
197 std::vector<int> sources(patch.xy.size(), -1);
198 for (auto edge : patch.boundarySegments)
199 for (int v : {edge.first, edge.second})
200 if (sources[v] < 0) {
201 sources[v] = int(out.points.size());
202 out.points.push_back(patch.xy[v]);
203 }
204 out.boundarySources.push_back(std::move(sources));
205 }
206 if (out.cells > r.options.limits.maxCells || out.points.size() > r.options.limits.maxVertices)
207 fail("planning_limit", "Planned patch/source counts exceed the job limit.",
209 work.memoryFor({{out.cells, 192}, {out.points.size(), 256}});
210 return out;
211}
212}
Definition geometry.hpp:59
Box2 united(Box2 b) const
Definition geometry.hpp:105
Definition geometry.hpp:11
Definition storage.hpp:18
void append(const Vector &v)
Definition storage.hpp:37
std::ptrdiff_t size() const noexcept
Definition storage.hpp:49
Definition planmodel.hpp:49
Box2 boundingRect() const
Definition planmodel.hpp:55
size_t i
Definition contourjob.cpp:30
QString path
Populated by the worker only after its own successful atomic creation.
Definition extensiontimeseriesaccess.cpp:32
int line
One-based source line.
Definition guiextensionhost.cpp:63
int region
Definition job.cpp:19
ArrowPlacement p
Definition linesymbollayer.cpp:29
hid_t id
Definition mesh2dh5reader.cpp:54
std::vector< double > nx
Definition mesh2dresultsexport.cpp:571
std::vector< double > ny
Definition mesh2dresultsexport.cpp:571
int k
Definition mesh2dresultsexport.cpp:694
MeshSpatialGrid grid
Definition mesh2dresultsexport.cpp:689
Definition file.hpp:21
PreparedPatches preparePatches(const JobRequest &r, const Providers &p, const std::function< double(const Box2 &)> &maximumSize, const std::function< double(const Box2 &)> &tolerance, Work &work, int attempt)
Definition mixed.hpp:39
void fail(std::string code, std::string message, RunStatus status=RunStatus::Infeasible)
Definition operation.hpp:17
bool finite(Point2 p)
Definition operation.hpp:82
Coordinate coordinate(Point2 p)
Definition mixed.hpp:22
QuadPlan planQuadRegions(const Vector< QuadRegion > &, const QuadPlanningGeometry &, const QuadPlanningOptions &={})
Definition planning.cpp:320
Vector< QuadRegion > placeQuadBlocks(const QuadBlockGrid &grid, const QuadBlockOptions &options)
Greedily select axis-aligned mapped quad regions from approximately uniform usable grid bands.
Definition blocks.cpp:204
Text validate(const StructuredPatch &p)
Input checks. Empty string = valid.
Definition patch.cpp:407
PatchAssessment assessPlannedPatch(const PatchMesh &, const PatchLimits &)
Definition planning.cpp:211
QuadBlockGrid quadBlockGridFromField(const Box2 &, double pitch, const std::function< double(const Box2 &)> &maximumSize, const Vector< Vector< Point2 > > &blockers, const std::function< bool()> &cancelled={}, std::int64_t maximumCells=1000000)
Definition blocks.cpp:142
std::uint32_t Index
Definition mesh.hpp:12
PathKind
Definition mesh.hpp:14
Box box
Definition constraintaudit.cpp:161
const ConstraintAuditOptions & options
Definition constraintaudit.cpp:34
const Polygon & ring
Definition patch.cpp:164
PatchMesh patch
Definition planning.cpp:207
TokenKind kind
Definition queryparser.cpp:53
double maximumSize
Definition job.hpp:19
double terrainTolerance
Definition job.hpp:24
std::uint64_t maximumPatchCells
Definition job.hpp:27
double minimumTarget
Definition job.hpp:19
bool automaticBlocks
Definition job.hpp:28
double minimumEdge
Definition job.hpp:19
Limits limits
Definition job.hpp:30
int maximumAutomaticBlocks
Definition job.hpp:29
CellPlan cells
Definition job.hpp:18
double minimumAngleDegrees
Definition job.hpp:19
Definition job.hpp:32
std::vector< Point2 > points
Definition job.hpp:33
std::vector< plan::PatchMesh > fixedPatches
Definition job.hpp:41
JobOptions options
Definition job.hpp:44
std::vector< Path > paths
Definition job.hpp:34
std::vector< plan::QuadRegion > quadRegions
Definition job.hpp:40
std::uint64_t maxWorkspaceBytes
Definition mesh.hpp:61
std::uint64_t maxVertices
Definition mesh.hpp:60
std::uint64_t maxWork
Definition mesh.hpp:62
std::uint64_t maxCells
Definition mesh.hpp:60
Definition mesh.hpp:15
PathKind kind
Definition mesh.hpp:17
Definition job.hpp:46
std::size_t operator()(Coordinate p) const
Definition mixed.hpp:17
Definition mixed.hpp:12
bool operator==(const Coordinate &b) const
Definition mixed.hpp:14
std::uint64_t y
Definition mixed.hpp:13
std::uint64_t x
Definition mixed.hpp:13
std::uint64_t sharedSides
Definition mixed.hpp:37
std::vector< int > regions
Definition mixed.hpp:32
std::uint64_t cells
Definition mixed.hpp:37
std::vector< std::vector< int > > boundarySources
Definition mixed.hpp:36
std::vector< Point2 > points
Definition mixed.hpp:34
std::vector< Path > extraPaths
Definition mixed.hpp:35
std::vector< plan::PatchDecision > decisions
Definition mixed.hpp:33
std::vector< plan::PatchMesh > patches
Definition mixed.hpp:31
Definition operation.hpp:22
void memoryFor(std::initializer_list< std::pair< std::uint64_t, std::uint64_t > > terms) const
Definition operation.hpp:44
void tick(std::uint64_t count=1)
Definition operation.hpp:36
Definition blocks.hpp:49
double minSpacing
Blocks finer than this are not worth a patch.
Definition blocks.hpp:50
int maxBlocks
Definition blocks.hpp:53
Definition planning.hpp:44
Definition planning.hpp:34
double defaultSize
Definition planning.hpp:36
int y
Definition terrainerrorfield.cpp:60
double b
Definition terrainerrorfield.cpp:42
double error
Definition terrainerrorfield.cpp:42
int x
Definition terrainerrorfield.cpp:60
double y0
Definition terrainerrorfield.cpp:41
double y1
Definition terrainerrorfield.cpp:41
double x1
Definition terrainerrorfield.cpp:41
double x0
Definition terrainerrorfield.cpp:41
Sample first
Definition timeseriesrunlayer.cpp:51
QRectF bounds
Definition traceanalysislayer.cpp:165