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
swmmmodellayer.h
Go to the documentation of this file.
1
11#ifndef SWMMMODELLAYER_H
12#define SWMMMODELLAYER_H
13
16#include "core/preferencesmanager.h" // NewProjectSpec defaults structs
17#include "render/labelconfig.h"
18#include "render/iattributeprovider.h" // Slice DM.3
19#include "render/markershape.h"
20#include "render/legendsymbolitem.h" // X4 — legend-as-editor facade
21
22#include <cstdint>
23#include <memory>
24#include <optional>
25#include <vector>
26
27// Forward declaration — nanoflann types are confined to swmmmodellayer.cpp
28// so the header stays free of the nanoflann.hpp template machinery.
29struct SWMMKdTrees;
30
31#include <QColor>
32#include <QDateTime>
33
34#include <openswmm/engine/openswmm_callbacks.h> // SWMM_Engine typedef
35#include <openswmm/engine/openswmm_infrastructure.h> // SWMM_InletUsage (by value)
36#include <QFont>
37#include <QMap>
38#include <QPen>
39#include <QBrush>
40#include <QPointer>
41#include <QPolygonF>
42#include <QSet>
43#include <QVariantMap>
44
47class MapCanvas; // setEditCanvas() — undo-stack host for mediated edits
48
49namespace OpenSWMM::Render {
50class IFeatureRenderer;
51class GraduatedRenderer; // classifyGraduatedIfNeeded — data-derived breaks.
52class RuleList; // Slice B.4 — see ruleList() override below.
53enum class ClassEditKind; // X4 — legend-as-editor facade (full def in ifeaturerenderer.h)
54}
55
56// Slice BS Phase 6.9.2 — hydrograph MVC layer. Forward-declared so the
57// header doesn't drag in <QAbstractItemModel>; accessors return pointers
58// that consumers can wire to QTableView / QListView. See
59// include/layers/hydrographmodels.h.
64
65namespace openswmmvis::ui {
66class UserFlagsModel; // [USER_FLAGS] / [USER_FLAG_VALUES] store — see ensureUserFlagsModel().
67}
68
69// Persistent per-kind symbol adapter set — see elementSymbolAdapter().
71
77{
78 QColor fillColor = Qt::blue;
79 QColor outlineColor = Qt::darkBlue;
80 double outlineWidth = 1.0;
81 double size = 8.0;
87 bool showLabel = false;
88 QFont labelFont;
89 QColor labelColor = Qt::black;
90
91 // Slice BI Phase 8.13.8-mini (2026-05-24) — flow-direction arrows
92 // for link kinds (Conduits / Pumps / Orifices / Weirs / Outlets).
93 // Ignored for point / polygon kinds. The arrow points from the
94 // link's upstream node to its downstream node — i.e. follows the
95 // polyline tangent at the midpoint of the visible polyline.
100 bool showArrows = false;
101 double arrowSize = 16.0;
108 double arrowWidth = 8.0;
109 QColor arrowColor = QColor(34, 34, 34);
110 // Slice FX.1 — was `true` by default, but that gates arrows on a
111 // bound `.out` (every link has flow=0 pre-simulation). Users who
112 // toggle "Show flow arrows" expect arrows to appear immediately,
113 // independent of whether a sim has run. The flow-positive filter
114 // remains opt-in via the Arrows tab → "Only when flow > 0".
116};
117
132 public OpenSWMM::Render::IAttributeProvider // Slice DM.3
133{
134 Q_OBJECT
135 Q_INTERFACES(OpenSWMM::Render::IAttributeProvider) // Slice DM.3
136
137 // The batched scene-item renderer reads the SoA + GDAL transform
138 // directly so paint() is a single tight pass over the cached data.
139 friend class SWMMLayerItem;
140 // Phase B.RHI — the QSG renderer reads the same flat buffers to
141 // populate its QSGGeometryNode vertex data on geometry change.
143
144public:
155 using Category = OpenSWMMVis::SwmmCategory;
168
198
199 Q_PROPERTY(QString modelFilePath READ modelFilePath NOTIFY modelFilePathChanged)
200 Q_PROPERTY(bool showNodes READ showNodes WRITE setShowNodes
201 NOTIFY showNodesChanged)
202 Q_PROPERTY(bool showLinks READ showLinks WRITE setShowLinks
203 NOTIFY showLinksChanged)
208 Q_PROPERTY(bool showLabels READ showLabels WRITE setShowLabels
209 NOTIFY showLabelsChanged)
210
211public:
212
213 explicit SWMMModelLayer(const QString &modelFilePath,
214 OpenSWMMVisWorkspace *parent = nullptr);
215
216 ~SWMMModelLayer() override;
217
218 // ----- Model file -----------------------------------------------------
219
220 [[nodiscard]] QString modelFilePath() const;
221 void setModelFilePath(const QString &path);
222
223 // ----- Self-description for the Layer Properties dialog ----------------
224 [[nodiscard]] QString sourceDescription() const override;
225 [[nodiscard]] QVector<QPair<QString, QString>> extendedMetadata() const override;
226
228 [[nodiscard]] SWMM_Engine engine() const;
229
238 [[nodiscard]] bool crsAssigned() const noexcept { return m_crsAssigned; }
239
244 bool loadModel(QList<QString> &warnings, QList<QString> &errors);
245
257 static SWMM_Engine openEngineForPath(const QString &path,
258 QString *errorDetail,
259 qint64 *openMs = nullptr);
260
276 qint64 *soaMsOut = nullptr, qint64 *geomMsOut = nullptr);
277
286 QList<QString> &warnings, QList<QString> &errors,
287 qint64 openMs = -1, qint64 soaMs = 0, qint64 geomMs = 0);
288
290 void closeEngine();
291
292 // ----- In-memory new project (File → New) -----------------------------
293
304
313 QString *errorDetail);
314
321 bool adoptNewEngine(const NewProjectSpec &spec,
322 QList<QString> &warnings, QList<QString> &errors);
323
324 // ----- Element visibility toggles -------------------------------------
325
326 [[nodiscard]] bool showNodes() const;
327 void setShowNodes(bool show);
328
329 [[nodiscard]] bool showLinks() const;
330 void setShowLinks(bool show);
331
332 [[nodiscard]] bool showSubcatchments() const;
333 void setShowSubcatchments(bool show);
334
335 [[nodiscard]] bool showRainGages() const;
336 void setShowRainGages(bool show);
337
338 [[nodiscard]] bool showLabels() const;
339 void setShowLabels(bool show);
340
349 // VS.10 — labelConfig() inherited from OpenSWMMVisLayer; only the setter
350 // is overridden to keep the legacy m_showLabels flag in sync.
351 void setLabelConfig(const OpenSWMM::Render::LabelConfig &cfg) override;
352
372 enum QsgKind : quint8 {
373 QsgNone = 0x00,
374 QsgNodes = 0x01,
375 QsgLinks = 0x02,
376 QsgCatch = 0x04,
377 QsgGages = 0x08,
378 };
379 Q_DECLARE_FLAGS(QsgKinds, QsgKind)
380
381 [[nodiscard]] QsgKinds qsgRenderKinds() const noexcept { return m_qsgKinds; }
382 void setQsgRenderKinds(QsgKinds kinds);
383
388 [[nodiscard]] bool qsgOwnsKind(QsgKind k) const noexcept
389 { return m_qsgKinds.testFlag(k); }
390
395 [[nodiscard]] bool glRenderingEnabled() const noexcept
396 { return m_qsgKinds != QsgNone; }
399 : QsgKinds(QsgNone)); }
400
401 // ----- Per-object visibility (Slice O) --------------------------------
402
413 [[nodiscard]] bool isObjectVisible(const QString &name) const;
414
422 [[nodiscard]] bool isObjectVisible(const QString &name, Category c) const;
423 void setObjectVisible(const QString &name, bool visible);
424
431 void setObjectsVisible(const QList<QString> &names, bool visible);
432
437 [[nodiscard]] QSet<QString> hiddenObjects() const { return m_hiddenObjects; }
438
451 [[nodiscard]] double maxMarkerHalfBoundPx() const;
452
453 // ----- Category-aware API (consumed by SWMMObjectTreeModel) -----------
454
458 [[nodiscard]] int categoryCount(Category c) const;
459
465 [[nodiscard]] QString objectNameAt(Category c, int row) const;
466
490 [[nodiscard]] int soaIndexAt(Category c, int row) const;
491
503 [[nodiscard]] int dataObjectCount(DataCategory c) const;
504
509 [[nodiscard]] QString dataObjectNameAt(DataCategory c, int row) const;
510
529 [[nodiscard]] QString suggestUniqueDataObjectName(DataCategory c) const;
530
552 [[nodiscard]] QStringList tableIdsOfType(int tableType) const;
553
580 [[nodiscard]] bool createDataObject(DataCategory c,
581 const QString &name,
582 const QVariantMap &options,
583 QString *outError = nullptr);
584
592 [[nodiscard]] Qt::CheckState categoryCheckState(Category c) const;
593
602 void setObjectVisibleAt(Category c, int row, bool visible);
603
610 void setCategoryVisible(Category c, bool visible);
611
619 [[nodiscard]] qreal categoryOpacity(Category c) const;
620 void setCategoryOpacity(Category c, qreal opacity);
621
629 bool findObjectLocation(const QString &name,
630 Category *cat, int *row) const;
631
632 // ----- Category ordering (Slice T.2) ----------------------------------
633
644 [[nodiscard]] QVector<Category> categoryOrder() const;
645
650 void setCategoryOrder(const QVector<Category> &order);
651
652 // ----- Intra-category object ordering (Slice T.3) ---------------------
653
672 void setObjectOrder(Category cat, const QVector<int> &soaIndices);
673
676 void clearObjectOrder(Category cat);
677
680 [[nodiscard]] QVector<int> objectOrder(Category cat) const;
681
686 [[nodiscard]] QVector<int> defaultObjectOrder(Category cat) const;
687
688 // ----- Symbology ------------------------------------------------------
689
690 [[nodiscard]] SWMMElementSymbol junctionSymbol() const;
692
693 [[nodiscard]] SWMMElementSymbol outfallSymbol() const;
695
696 [[nodiscard]] SWMMElementSymbol storageSymbol() const;
698
699 [[nodiscard]] SWMMElementSymbol dividerSymbol() const;
701
702 [[nodiscard]] SWMMElementSymbol virtualJunctionSymbol() const;
704
707 [[nodiscard]] SWMMElementSymbol inletJunctionSymbol() const;
709
712 [[nodiscard]] SWMMElementSymbol inletConnectorSymbol() const;
714
715 [[nodiscard]] SWMMElementSymbol conduitSymbol() const;
717
718 [[nodiscard]] SWMMElementSymbol pumpSymbol() const;
719 void setPumpSymbol(const SWMMElementSymbol &s);
720
721 [[nodiscard]] SWMMElementSymbol orificeSymbol() const;
723
724 [[nodiscard]] SWMMElementSymbol weirSymbol() const;
725 void setWeirSymbol(const SWMMElementSymbol &s);
726
732 [[nodiscard]] SWMMElementSymbol outletSymbol() const;
734
735 [[nodiscard]] SWMMElementSymbol subcatchmentSymbol() const;
737
738 [[nodiscard]] SWMMElementSymbol rainGageSymbol() const;
740
752 [[nodiscard]] std::vector<std::unique_ptr<openswmmvis::ui::ILayerStyleSubject>>
753 styleSubjects() override;
754
762 [[nodiscard]] SwmmElementSymbolAdapter *
763 elementSymbolAdapter(const QString &routingId);
764
768 [[nodiscard]] quint64 editRevision() const { return m_editRevision; }
769
770 // ----- Renderer (Slice BI Phase 8.13.6.5) -----------------------------
771 // The renderer is the §J.2 seam every future paint path will go through.
772 // Sub-phase 8.13.6.5 is API plumbing only — the existing paint loop in
773 // SWMMLayerItem still reads the per-kind SWMMElementSymbol members
774 // (m_junctionSym, m_conduitSym, …) directly. The paint refactor lands
775 // later (after Slice BB Phase 8.6.1 provides a proper ColorRamp type),
776 // at which point the default renderer will be swapped from this
777 // placeholder SingleSymbolRenderer to a MultiKindRenderer adapter that
778 // delegates to the 11 per-category symbols.
779
787 [[nodiscard]] OpenSWMM::Render::IFeatureRenderer *renderer() const override;
788
795 void setRenderer(std::unique_ptr<OpenSWMM::Render::IFeatureRenderer> r) override;
796
797 // ----- Per-kind renderer (Slice BI-MK.1 / BI-MK.LT, 2026-05-24) --------
798 //
799 // Stores 11 per-kind IFeatureRenderer entries, indexed by Category, so
800 // SymbologyDialog's left-pane kind picker and LayerTreePanel's sub-row
801 // right-click menu can drive per-kind styling independently. Single-
802 // symbol renderers double-bind to the legacy `m_*Sym` SWMMElementSymbol
803 // fields (write-through both ways) so the current bucketed paint code
804 // in SWMMLayerItem keeps working without a full per-feature symbolFor()
805 // refactor. Graduated/Categorized renderers are stored + drive legends
806 // / persistence; canvas painting from them is deferred to the full
807 // Phase 8.13.6.4 paint-loop refactor.
808
811
818 std::unique_ptr<OpenSWMM::Render::IFeatureRenderer> r);
819
824
827 [[nodiscard]] static QString kindKey(Category c);
828
829 // ----- X4: legend-as-editor facade ------------------------------------
830 // The model layer is multi-kind, so it has no single IFeatureRenderer for
831 // the legend dock to drive. These mirror the IFeatureRenderer class-edit
832 // contract but aggregate across the 11 per-kind renderers: legend rows
833 // carry a kind-qualified classKey ("Junctions␟<inner>"), and the
834 // colour/size accessors decode the kind and delegate to the matching
835 // kindRenderer() — i.e. edits land on the very objects the painter reads
836 // (single source of truth). Mutating setters rebuild that kind's
837 // per-feature override cache and request a repaint.
838 [[nodiscard]] QList<OpenSWMM::Render::LegendSymbolItem> legendSymbolItems() const;
840 [[nodiscard]] QColor colorForClass(const QString &classKey) const;
841 void setColorForClass(const QString &classKey, const QColor &color);
842 [[nodiscard]] qreal sizeForClass(const QString &classKey) const;
843 void setSizeForClass(const QString &classKey, qreal size);
844
845 // ----- Rule Model (Slice B.4, Phase B) --------------------------------
846 //
847 // 11 kindRenderer slots → 11 Rules, one per Category. The RuleList
848 // is lazy-built on first access; each Rule holds a CLONE of the
849 // matching kindRenderer at construction time. Rule-side renderer
850 // swaps (via Z.3b's setRendererById) propagate back to the layer
851 // via setKindRenderer, which keeps the legacy paint-time + override
852 // cache code paths intact.
853 //
854 // Limitation: external calls to setKindRenderer (e.g. from undo
855 // commands) don't re-sync the RuleList. The user must reopen the
856 // Layer Style dialog to see fresh state — acceptable for B.4; full
857 // bidirectional sync lands in a follow-up if it surfaces a real
858 // problem.
859 [[nodiscard]] OpenSWMM::Render::RuleList *ruleList() override;
860 [[nodiscard]] const OpenSWMM::Render::RuleList *ruleList() const override;
861
862 // ----- IAttributeProvider (Slice DM.3) --------------------------------
863 //
864 // Returns the per-kind static engine fields a user can theme by
865 // (length, slope, diameter, invertElev, area, impervPct, …). All
866 // entries are isDynamic=false (statics don't change per animation
867 // frame). Drives the attribute combo in the Graduated / Categorized
868 // renderer panels — see RENDERING_DIALOG_DEMO_PLAN.md §2.
869 [[nodiscard]] QVector<OpenSWMM::Render::AttributeField>
871
872 // ----- Flow-direction arrows (Slice BI Phase 8.13.8-mini, 2026-05-24) -
873 //
874 // Per-link-kind toggle for arrowheads drawn at the polyline midpoint
875 // pointing upstream → downstream. Wraps the showArrows / arrowSize /
876 // arrowColor / arrowOnlyWhenFlowPos fields on the corresponding
877 // SWMMElementSymbol so the painter can drive arrows from a single
878 // place. `c` must be a link kind (Conduits / Pumps / Orifices /
879 // Weirs / Outlets); other categories silently no-op the setter and
880 // return false from the getter.
881
883 [[nodiscard]] bool linkArrowsEnabled(Category c) const;
884
886 void setLinkArrowsEnabled(Category c, bool enabled);
887
888 // Slice FX.1 — per-kind arrow size / colour / flow-positive filter.
889 // Mirror the linkArrowsEnabled getter+setter shape; setters emit
890 // repaintRequested when the underlying field actually changes.
891 [[nodiscard]] double linkArrowSize(Category c) const;
892 void setLinkArrowSize(Category c, double pixels);
894 [[nodiscard]] double linkArrowWidth(Category c) const;
895 void setLinkArrowWidth(Category c, double pixels);
896 [[nodiscard]] QColor linkArrowColor(Category c) const;
897 void setLinkArrowColor(Category c, const QColor &col);
898 [[nodiscard]] bool linkArrowOnlyWhenFlowPos(Category c) const;
899 void setLinkArrowOnlyWhenFlowPos(Category c, bool onlyPos);
900
904 [[nodiscard]] double linkFlow(int linkIdx) const;
905
914 [[nodiscard]] bool kindUsesOverrides(Category c) const;
915
920 [[nodiscard]] QColor featureColor(Category c, int idx) const;
921
926 [[nodiscard]] double featureSize(Category c, int idx) const;
927
931 [[nodiscard]] int featureShape(Category c, int idx) const;
932
940 [[nodiscard]] double featureOffset(Category c, int idx) const;
941
946 [[nodiscard]] bool kindHasAnyOffset(Category c) const;
947
954
965
966 // ----- Selection ------------------------------------------------------
967
974 static constexpr quint8 kKindNode = 0x01;
975 static constexpr quint8 kKindLink = 0x02;
976 static constexpr quint8 kKindCatch = 0x04;
977 static constexpr quint8 kKindGage = 0x08;
978 static constexpr quint8 kKindAll = 0x0F;
979
984 [[nodiscard]] static quint8 kindBitForCategory(Category c) noexcept;
985
995 QString name;
996 quint8 kinds = 0;
997 bool operator==(const SelectedElement &o) const
998 { return kinds == o.kinds && name == o.name; }
999 };
1000
1004 [[nodiscard]] QStringList selectedElementNames() const;
1005
1011 [[nodiscard]] const QVector<SelectedElement> &selectedElements() const
1012 { return m_selectedElements; }
1013
1017 void setSelectedElements(const QVector<SelectedElement> &sel);
1018
1025 void setSelectedElementNames(const QStringList &names);
1026
1027 void clearSelection();
1028
1029 // ----- Identify -------------------------------------------------------
1030
1040 [[nodiscard]] QVariantMap identifyAt(double mapX, double mapY,
1041 const SpatialReferenceSystem *canvasSRS,
1042 double tolerance = 1e-6) const;
1043
1047 [[nodiscard]] QVariantMap identifyAt(double mapX, double mapY,
1048 double tolerance = 1e-6) const;
1049
1064 [[nodiscard]] QVariantMap identifyByName(const QString &name,
1065 quint8 kindMask = kKindAll) const;
1066
1078 [[nodiscard]] class MapExtent objectExtent(const QString &name) const;
1079
1080 // ----- Spatial-index queries (O(log N + k), backed by nanoflann KD-tree) ---
1081
1091 [[nodiscard]] QStringList nodesInRect(double canvasMinX, double canvasMinY,
1092 double canvasMaxX, double canvasMaxY) const;
1093
1114 [[nodiscard]] bool snapNearestPoint(double mapX, double mapY, double mapRadius,
1115 QPointF &outPt,
1116 std::optional<QPointF> excludePos = std::nullopt) const;
1117
1122 [[nodiscard]] QStringList gagesInRect(double canvasMinX, double canvasMinY,
1123 double canvasMaxX, double canvasMaxY) const;
1124
1136 [[nodiscard]] QStringList linksInRect(double canvasMinX, double canvasMinY,
1137 double canvasMaxX, double canvasMaxY) const;
1138
1144 [[nodiscard]] QStringList subcatchmentsInRect(double canvasMinX, double canvasMinY,
1145 double canvasMaxX, double canvasMaxY) const;
1146
1147 // ----- Polygon (lasso) queries ----------------------------------------
1148 // Same contract as the *InRect queries above, but the test region is an
1149 // arbitrary polygon given in canvas CRS. Candidates are first gathered
1150 // with the polygon's bounding box (reusing the accelerated *InRect path),
1151 // then refined with an exact point-in-polygon test performed in layer CRS
1152 // (nodes/gages at their coordinate; links/subcatchments at their bbox
1153 // centre). Hidden objects are excluded. \p canvasPoly needs >= 3 vertices.
1154
1155 [[nodiscard]] QStringList nodesInPolygon(const QPolygonF &canvasPoly) const;
1156 [[nodiscard]] QStringList gagesInPolygon(const QPolygonF &canvasPoly) const;
1157 [[nodiscard]] QStringList linksInPolygon(const QPolygonF &canvasPoly) const;
1158 [[nodiscard]] QStringList subcatchmentsInPolygon(const QPolygonF &canvasPoly) const;
1159
1160 // ----- OpenSWMMVisLayer interface -----------------------------------------
1161
1162 void populateScene(QGraphicsScene *scene,
1163 const MapExtent &canvasExtent,
1164 const SpatialReferenceSystem *canvasSRS) override;
1165
1166 void depopulateScene(QGraphicsScene *scene) override;
1167
1168 void refreshScene(QGraphicsScene *scene,
1169 const MapExtent &canvasExtent,
1170 const SpatialReferenceSystem *canvasSRS) override;
1171
1172 void onCanvasCRSChanged(const SpatialReferenceSystem *newCanvasSRS) override;
1173
1180 void reloadGeometry();
1181
1194 bool transformCanvasToLayer(double cx, double cy,
1195 double &lx, double &ly) const;
1196
1203 [[nodiscard]] QPolygonF polygonCanvasToLayer(const QPolygonF &poly) const;
1204
1219 bool transformLayerToCanvas(double lx, double ly,
1220 double &cx, double &cy) const;
1221
1232 [[nodiscard]] int objectTypeFor(const QString &name) const;
1233
1234 // ----- Geometry editing API (Phase 2) --------------------------------
1235
1240 [[nodiscard]] int nodeIndex(const QString &name) const;
1241
1246 [[nodiscard]] int linkIndex(const QString &name) const;
1247
1252 bool cachedNodeCoord(int idx, double *x, double *y) const;
1253
1261 bool elementPosition(const QString &name, double *x, double *y) const;
1262
1267 [[nodiscard]] QVector<QPointF> cachedLinkPolyline(int idx) const;
1268
1275 [[nodiscard]] QVector<QPointF> cachedLinkInteriorVertices(int idx) const;
1276
1286 [[nodiscard]] int renderLinkCount() const
1287 { return int(m_linkVertexCount.size()); }
1288
1297 [[nodiscard]] bool renderLinkHidden(int idx) const
1298 {
1299 return idx >= 0 && size_t(idx) < m_linkHiddenFlag.size()
1300 && m_linkHiddenFlag[size_t(idx)] != 0;
1301 }
1302
1309 [[nodiscard]] QVector<QPointF> cachedSubcatchVertices(int idx) const;
1310
1316 [[nodiscard]] int cachedSubcatchCount() const;
1317
1320 [[nodiscard]] int cachedNodeCount() const;
1321 [[nodiscard]] int cachedLinkCount() const;
1322 [[nodiscard]] int cachedGageCount() const;
1323
1339 [[nodiscard]] bool cachedGageCoord(int idx, double *x, double *y) const;
1340
1345 [[nodiscard]] quint64 geomRevision() const { return m_geomRevision; }
1346
1347 // ----- Simulation-options pass-through (Slice U) ----------------------
1348
1360 [[nodiscard]] QString getOption(const QByteArray &key,
1361 const QString &fallback = {}) const;
1362
1371 bool setOption(const QByteArray &key, const QString &value);
1372
1378 int setOptions(const QMap<QByteArray, QString> &values);
1379
1384 [[nodiscard]] double engineLinkLength(int linkIdx) const;
1385
1400 [[nodiscard]] double polylineLengthInModelUnits(
1401 const QVector<QPointF> &vertices) const;
1402
1408 [[nodiscard]] bool isConduit(int linkIdx) const;
1409
1410 // ----- Tool-facing hit-test (Slice R Phase 3) -------------------------
1411
1421 struct PickResult {
1422 bool valid = false;
1424 int soaIndex = -1;
1425 QString name;
1426 };
1427
1439 [[nodiscard]] PickResult pickAt(double sceneX, double sceneY,
1440 double tolerance) const;
1441
1449 bool previewNodeMove(int idx, double newX, double newY);
1450
1457 bool previewGageMove(int idx, double newX, double newY);
1458
1462 [[nodiscard]] QVector<int> linksAttachedToNode(int nodeIdx) const;
1463
1468 [[nodiscard]] int linkEndForNode(int linkIdx, int nodeIdx) const;
1469
1471 [[nodiscard]] int linkFromNodeIdx(int linkIdx) const;
1472
1474 [[nodiscard]] int linkToNodeIdx(int linkIdx) const;
1475
1486 bool applyNodeMove(int idx, double newX, double newY);
1487
1492 bool applyLinkLength(int linkIdx, double length);
1493
1509 void convertLinkOffsets(bool toElevation, bool convertValues);
1510
1518 bool applyLinkXsect(int linkIdx, int shape,
1519 double g1, double g2, double g3, double g4);
1520
1525 bool applyLinkBarrels(int linkIdx, int barrels);
1526
1531 bool applyLinkCulvertCode(int linkIdx, int code);
1532
1546 bool applyNodeConvert(const QString &name, int newNodeType,
1547 QStringList *outCleared = nullptr,
1548 QStringList *outWarnings = nullptr,
1549 QString *outError = nullptr);
1550
1557 bool applyLinkConvert(const QString &name, int newLinkType,
1558 QStringList *outCleared = nullptr,
1559 QStringList *outWarnings = nullptr,
1560 QString *outError = nullptr);
1561
1582 bool applyLinkFlip(int linkIdx);
1583
1584 // ===== Virtual junctions ==============================================
1585 // Engine-side split/fuse semantics (swmm_conduit_split /
1586 // swmm_virtual_junction_fuse / swmm_node_set_virtual) so CLI, Python,
1587 // MCP and GUI share one implementation. See
1588 // workplans/VIRTUAL_JUNCTION_GUI_PLAN_2026-08-01.md.
1589
1591 bool nodeIsVirtual(int soaIdx) const {
1592 return soaIdx >= 0 && soaIdx < m_nodes.size() &&
1593 m_nodes[soaIdx].isVirtual != 0;
1594 }
1595
1602 bool applySetVirtual(const QString &name, bool makeVirtual,
1603 QString *outError = nullptr);
1604
1614 bool applyInsertVirtualJunction(const QString &linkName, double t,
1615 const QString &newNodeName,
1616 const QString &newLinkName,
1617 int *outNodeIdx = nullptr,
1618 int *outLinkIdx = nullptr,
1619 QString *outError = nullptr);
1620
1627 bool applyFuseVirtualJunction(const QString &nodeName,
1628 QString *outError = nullptr);
1629
1637 bool applyInsertJunctionSplit(const QString &linkName, double t,
1638 const QString &newNodeName,
1639 const QString &newLinkName,
1640 int *outNodeIdx = nullptr,
1641 int *outLinkIdx = nullptr,
1642 QString *outError = nullptr);
1643
1656 bool applyFuseJunctionSplit(const QString &nodeName,
1657 QString *outError = nullptr);
1658
1661 static QString virtualJunctionRuleText(int engineErrorCode);
1662
1663 // ===== Inlet junctions and inlet usage ================================
1664 // Engine surface: swmm_node_is_inlet / _inlet_eligible / _set_inlet
1665 // (openswmm_nodes.h), swmm_inlet_usage_* (openswmm_infrastructure.h),
1666 // swmm_conduit_split_inlet / swmm_inlet_junction_fuse (openswmm_edit.h).
1667 // See workplans/INLET_EDITOR_AND_INLET_JUNCTION_GUI_PLAN_2026-09-05.md.
1668
1672 [[nodiscard]] bool nodeIsInlet(int soaIdx) const {
1673 return soaIdx >= 0 && soaIdx < m_nodes.size() &&
1674 m_nodes[soaIdx].isInlet != 0;
1675 }
1676
1681 [[nodiscard]] bool engineSupportsInletJunctions() const;
1682
1686 [[nodiscard]] bool inletUsageFor(int hostKind, int hostIdx,
1687 SWMM_InletUsage *out) const;
1688
1692 bool applySetInletUsage(const SWMM_InletUsage &usage,
1693 QString *outError = nullptr);
1694
1697 bool applyRemoveInletUsage(int hostKind, int hostIdx,
1698 QString *outError = nullptr);
1699
1703 bool applySetInlet(const QString &name, bool makeInlet,
1704 QString *outError = nullptr);
1705
1710 bool applyInsertInletJunction(const QString &linkName, double t,
1711 const QString &newNodeName,
1712 const QString &newLinkName,
1713 const QString &inletId,
1714 const QString &captureNode,
1715 int *outNodeIdx = nullptr,
1716 int *outLinkIdx = nullptr,
1717 QString *outError = nullptr);
1718
1721 bool applyFuseInletJunction(const QString &nodeName,
1722 QString *outError = nullptr);
1723
1729 QPointF host;
1730 QPointF capture;
1731 };
1732
1736 [[nodiscard]] const QVector<InletConnector> &inletConnectors() const;
1737
1749 void setEditCanvas(MapCanvas *canvas);
1750 [[nodiscard]] MapCanvas *editCanvas() const;
1751
1755 bool pushInletUsageEdit(const SWMM_InletUsage &usage);
1757 bool pushInletUsageRemoval(int hostKind, int hostIdx);
1758
1763 bool applyLinkInteriorVertices(int linkIdx, const QVector<QPointF> &interior);
1764
1769 bool applySubcatchVertices(int idx, const QVector<QPointF> &vertices);
1770 bool applySubcatchArea(int idx, double areaInModelUnits);
1771
1787 bool applySubcatchSetGage(int idx, const QString &gageName);
1788
1798 bool applyNodeAdd(const QString &name, int nodeType,
1799 double x, double y,
1800 int *outIdx = nullptr);
1801
1809 bool rollbackTailNodeAdd(const QString &name);
1810
1820 bool applyLinkAdd(const QString &name, int linkType,
1821 const QString &fromNodeName, const QString &toNodeName,
1822 const QVector<QPointF> &interiorVertices,
1823 int *outIdx = nullptr);
1824
1826 bool rollbackTailLinkAdd(const QString &name);
1827
1839 bool applyGageMove(int idx, double newX, double newY);
1840
1842 bool applyGageAdd(const QString &name, double x, double y,
1843 int *outIdx = nullptr);
1844
1846 bool rollbackTailGageAdd(const QString &name);
1847
1849 bool applySubcatchAdd(const QString &name,
1850 const QVector<QPointF> &polygon,
1851 int *outIdx = nullptr);
1852
1854 bool rollbackTailSubcatchAdd(const QString &name);
1855
1878 bool applyRename(const QString &oldName, const QString &newName,
1879 quint8 kindHint = kKindAll);
1880
1881 // ===== Bulk edit — coalesce the per-object cache-rebuild storm =======
1882 //
1883 // Every applyXxxAdd / applyXxxDelete rebuilds the whole derived cache
1884 // (category index, model extent, link spatial grid) and then emits
1885 // repaintRequested() + geometryChanged(), whose listeners each do
1886 // O(model) work of their own. That is affordable for one object and
1887 // quadratic for a selection: deleting 100 junctions from a 104k-node
1888 // model costs ~21 s, of which only ~4.6 s is the engine.
1889 //
1890 // Inside a bulk edit the engine call and the SoA removal/append still
1891 // happen IMMEDIATELY — only the derived work is deferred. That is
1892 // deliberate: it keeps the "SoA index == engine index" invariant true
1893 // at every instant, which the rest of this class relies on.
1894 //
1895 // Always use the RAII BulkEdit guard; never call beginBulkEdit() /
1896 // endBulkEdit() by hand. A batch that begins and never ends would
1897 // leave the layer permanently signal-blocked with stale caches.
1899 {
1900 public:
1901 explicit BulkEdit(SWMMModelLayer *layer) : m_layer(layer)
1902 {
1903 if (m_layer) m_layer->beginBulkEdit();
1904 }
1906 {
1907 if (m_layer) m_layer->endBulkEdit();
1908 }
1909 BulkEdit(const BulkEdit &) = delete;
1910 BulkEdit &operator=(const BulkEdit &) = delete;
1911
1912 private:
1913 QPointer<SWMMModelLayer> m_layer;
1914 };
1915
1918 void beginBulkEdit();
1919
1923 void endBulkEdit();
1924
1927 [[nodiscard]] bool bulkEditActive() const { return m_bulkDepth > 0; }
1928
1936 bool applyNodeDelete(const QString &name,
1937 QStringList *cascadeLinkNames = nullptr);
1938
1940 bool applyLinkDelete(const QString &name);
1941
1943 bool applyGageDelete(const QString &name);
1944
1946 bool applySubcatchDelete(const QString &name);
1947
1962 bool applyDeleteMany(const QStringList &nodeNames,
1963 const QStringList &linkNames,
1964 const QStringList &subcatchNames,
1965 const QStringList &gageNames,
1966 QStringList *cascadeLinkNames = nullptr);
1967
1968 // ===== Slice BS Phase 6.9.2 — hydrograph + RDII decay MVC layer ======
1969 //
1970 // Every mutation to [HYDROGRAPHS] / [RDII_DECAY] data routes through one
1971 // of the helpers below — never call `swmm_hydrograph_*` /
1972 // `swmm_rdii_decay_*` directly from a dialog. On success each helper
1973 // emits hydrographChanged(uhName) so all subscribed Qt models refresh in
1974 // lock-step. The model layer is the single Qt-side mediator over the
1975 // engine's BS-02 C API.
1976 //
1977 // See: docs/GUI_IMPLEMENTATION_PLAN.md Slice BS Phase 6.9.2.
1978
1983 bool applyHydrographAddGroup(const QString &name,
1984 const QString &gageName,
1985 int initialResponse);
1986
1989 bool applyHydrographRemoveGroup(const QString &name);
1990
1994 bool applyHydrographRenameGroup(const QString &oldName, const QString &newName);
1995
1998 bool applyHydrographSetGage(const QString &name, const QString &gageName);
1999
2001 bool applyHydrographSetRtk(const QString &name, int month, int response,
2002 double r, double t, double k);
2003
2006 bool applyHydrographSetIa(const QString &name, int month, int response,
2007 double dmax, double drecov, double dinit);
2008
2010 bool applyHydrographRemoveEntry(const QString &name, int month, int response);
2011
2015 bool applyHydrographClearMonths(const QString &name);
2016
2020 bool applyRdiiDecaySet(const QString &name, int response,
2021 double k_dep, double k_0, double k_T,
2022 double T_ref, double theta_rec, double T_freeze,
2023 bool snowOn = false, double snow_T = 1.0,
2024 double snow_ddf = 0.0);
2025
2028 bool applyRdiiDecayRemove(const QString &name, int response);
2029
2033
2037
2041
2046
2054 QObject *ensureTimeseriesRegistry();
2055
2058 QObject *ensurePatternRegistry();
2059
2061 QObject *ensureCurveRegistry();
2062
2063 // ===== Slice BR Phase 6.8.1 — control-rule MVC layer ====================
2064 //
2065 // Mirrors the hydrograph pattern at Phase 6.9.2 (`applyHydrograph*` +
2066 // `hydrographChanged`) and the curve/pattern/timeseries `ensureXRegistry`
2067 // accessors above. The four `applyControlRule*` helpers are the **only**
2068 // place engine `swmm_control_*` mutation calls live; all UI surfaces
2069 // (RulesEditorDialog, SWMMControlRulePropertyAdapter, Object Browser)
2070 // route through them and re-render off the `controlRulesChanged(name)`
2071 // signal.
2072 //
2073 // The engine has no per-rule mutator (DA-ENG-11), so each apply helper
2074 // snapshots every rule, modifies the target slot in the snapshot, calls
2075 // `swmm_control_clear_rules`, and re-`swmm_control_add_rule`s the
2076 // snapshot. This matches today's `SWMMControlRulePropertyAdapter
2077 // ::setRuleText` round-trip.
2078
2083 bool applyControlRuleAdd(const QString &name, const QString &body,
2084 QString *outError = nullptr);
2085
2089 bool applyControlRuleReplace(const QString &name, const QString &newBody,
2090 QString *outError = nullptr);
2091
2096 bool applyControlRuleRename(const QString &oldName, const QString &newName,
2097 QString *outError = nullptr);
2098
2101 bool applyControlRuleRemove(const QString &name,
2102 QString *outError = nullptr);
2103
2110 QObject *ensureControlRuleRegistry();
2111
2112 // ===== Slice BQ Phase 6.7.4 — transect MVC layer =========================
2113 //
2114 // Mirrors the curve / pattern / control-rule pattern. The applyTransect*
2115 // helpers are the only place engine `swmm_transect_*` mutation calls
2116 // live; all UI surfaces (TransectEditorDialog, SWMMTransectPropertyAdapter,
2117 // Object Browser) route through them and re-render off
2118 // `transectChanged(name)`.
2119
2121 bool applyTransectAdd(const QString &name, QString *outError = nullptr);
2122
2124 bool applyTransectRename(const QString &oldName, const QString &newName,
2125 QString *outError = nullptr);
2126
2128 bool applyTransectRemove(const QString &name, QString *outError = nullptr);
2129
2130 bool applyTransectSetComments(const QString &name, const QString &comments);
2131 bool applyTransectSetRoughness(const QString &name,
2132 double nLeft, double nRight, double nChannel);
2133 bool applyTransectSetBankStations(const QString &name, double xLeft, double xRight);
2134 bool applyTransectSetEncroachmentStations(const QString &name,
2135 double xLeft, double xRight);
2136 bool applyTransectSetModifiers(const QString &name,
2137 double stationMul, double elevOffset, double meander);
2139 bool applyTransectSetStations(const QString &name,
2140 const QVector<QPair<double,double>> &stations);
2141
2143 QObject *ensureTransectRegistry();
2144
2146 QObject *ensureStreetRegistry();
2147
2149 QObject *ensurePollutantRegistry();
2150
2152 QObject *ensureLandUseRegistry();
2153
2155 QObject *ensureAquiferRegistry();
2156
2158 QObject *ensureSnowpackRegistry();
2159
2161 QObject *ensureInletRegistry();
2162
2164 QObject *ensureLidControlRegistry();
2165
2166 // ===== User flags ([USER_FLAGS] / [USER_FLAG_VALUES]) ==================
2167 //
2168 // Phase 1 of docs/USER_FLAGS_UI_PLAN_2026-06-03.md. Same lazy-init /
2169 // engine-handle-guard pattern as the registries above. All engine
2170 // user-flag mutation calls live in UserFlagsModel; UI surfaces (User
2171 // Flags Manager dialog, Attribute Table flag columns, Attribute Panel
2172 // rows) share this instance and re-render off its defsChanged() /
2173 // valueChanged() signals.
2174
2178
2179public slots:
2186 void markEdited() { emit modelEdited(); }
2187
2188signals:
2189 void modelFilePathChanged(const QString &path);
2190 void showNodesChanged(bool show);
2191 void showLinksChanged(bool show);
2193 void showRainGagesChanged(bool show);
2194 void showLabelsChanged(bool show);
2195
2196 // VS.10 — labelConfigChanged() is inherited from OpenSWMMVisLayer.
2197
2198 void selectionChanged(const QStringList &selectedNames);
2200 void modelLoadError(const QString &errorMessage);
2204
2217 void optionsChanged(const QStringList &keys);
2218
2224
2231
2236 void attributeChanged(const QString &objectName);
2237
2243 void qsgRenderKindsChanged(QsgKinds kinds);
2244
2252 void hydrographChanged(const QString &uhName);
2253
2261 void controlRulesChanged(const QString &ruleName);
2262
2268 void transectChanged(const QString &transectName);
2269
2280
2296
2297private:
2298 // X4 — decode a kind-qualified legend class key ("<kindKey><sep><inner>")
2299 // back to its Category + inner class key. Returns false when the key
2300 // isn't kind-qualified or the kind is unknown.
2301 bool decodeLegendClassKey(const QString &key, Category *catOut,
2302 QString *innerOut) const;
2303
2304 struct NodeGeom { double x, y; int objectType; int nodeType;
2305 int isVirtual = 0;
2309 int isInlet = 0;
2310 QString name; };
2311 struct LinkGeom {
2312 QVector<QPointF> vertices; // interior bend points only (no node endpoints)
2313 int linkType = -1;
2314 int fromNodeIdx = -1;
2315 int toNodeIdx = -1;
2316 QString name;
2317 };
2318 struct CatchGeom { QVector<QPointF> vertices; QString name; };
2319
2321 struct OutletLine { QLineF line; int catchIdx; };
2322
2323 void buildGeometryCache();
2324 void rebuildTransform(const SpatialReferenceSystem *canvasSRS);
2325 void rebuildKdTrees() const;
2326 void ensureKdTrees() const;
2327
2342 void rebuildSceneCoords();
2343 void refreshSceneCoordsForNode(int nodeIdx);
2344 void refreshSceneCoordsForLink(int linkIdx);
2345 void refreshSceneCoordsForSubcatch(int catchIdx);
2346 void refreshCatchOutletLinesForNode(int nodeIdx);
2347
2348 // Incremental scene/cache mutations — O(1) per element plus an
2349 // O(L) spatial-grid touch where unavoidable. These let single
2350 // add / rename / delete operations skip the full O(N·V) OGR
2351 // re-transform that rebuildSceneCoords() does on every feature.
2352 void appendNodeSceneEntry();
2353 void appendLinkSceneEntry();
2354 void appendCatchSceneEntry();
2355 void appendGageSceneEntry();
2356 void compactNodeSceneEntry(int nodeIdx);
2357 void compactLinkSceneEntry(int linkIdx);
2358 void compactCatchSceneEntry(int catchIdx);
2359 void compactGageSceneEntry(int gageIdx);
2360
2380 void syncLinkEndpointIndicesFromEngine();
2381
2394 void renameInIndices(const QString &oldName, const QString &newName,
2395 quint8 renamedKind);
2396
2399 void recomputeExtentFromCaches();
2400
2401 // Incremented at the end of every rebuildSceneCoords() call.
2402 // SWMMLayerQSGRenderer uses this to invalidate its subcatchment
2403 // triangulation cache without needing a signal or pointer comparison.
2404 quint64 m_geomRevision = 0;
2405
2406 // Bulk-edit scope depth, and whether anything inside it actually
2407 // mutated. m_bulkDirty gates the batch-end rebuild so an all-failed
2408 // batch costs nothing — and so a batch of pure no-ops does not emit a
2409 // spurious geometryChanged().
2410 int m_bulkDepth = 0;
2411 bool m_bulkDirty = false;
2412
2413 // See crsAssigned(). Set by srsChanged after load; the load path resets
2414 // it to whether the .inp itself carried a CRS.
2415 bool m_crsAssigned = false;
2416
2439 struct LinkSpatialGrid
2440 {
2441 QRectF extent;
2442 double cellW = 0.0;
2443 double cellH = 0.0;
2444 int cols = 0;
2445 int rows = 0;
2446 QVector<QVector<int>> cells;
2447
2448 void clear() { extent = {}; cellW = cellH = 0.0; cols = rows = 0; cells.clear(); }
2449 [[nodiscard]] bool isEmpty() const { return cells.isEmpty(); }
2450
2454 void rebuild(const QVector<QRectF> &linkBBoxes);
2455
2459 [[nodiscard]] QVector<int> query(const QRectF &rect) const;
2460 };
2461 LinkSpatialGrid m_linkGrid;
2462
2471 void rebuildCategoryIndex();
2472
2473 SWMM_Engine m_engine = nullptr;
2474
2475 QString m_modelFilePath;
2476 bool m_showNodes = true;
2477 bool m_showLinks = true;
2478 bool m_showSubcatchments = true;
2479 bool m_showRainGages = true;
2480 bool m_showLabels = false;
2481 // VS.10 — m_labelConfig moved to OpenSWMMVisLayer (base owns it now).
2482 // Per-kind QSG scope (see QsgKind / qsgRenderKinds() above).
2483 // Default empty means the QSG overlay never runs and every kind is
2484 // drawn by the CPU SWMMLayerItem path — matches pre-§QSG-1 behaviour
2485 // and is what the Preferences toggle inverts when the user enables
2486 // the experimental GPU path.
2487 QsgKinds m_qsgKinds = QsgNone;
2488
2489 // Slice O — per-object hidden set. Names listed here are skipped by
2490 // populateScene. NOTE: SWMM names are per-type namespaces — real
2491 // models routinely pair every subcatchment with a same-named rain
2492 // gage, and links may share names with nodes — so membership alone
2493 // cannot say WHICH kind the user hid. m_hiddenKindMask below carries
2494 // that type information; this set stays the name-keyed canonical
2495 // membership for the legacy API and .oswp persistence.
2496 QSet<QString> m_hiddenObjects;
2497
2498 // Per-name bitmask of hidden kinds. Invariant: a name is in
2499 // m_hiddenObjects iff its mask entry exists and is non-zero. Names
2500 // hidden through the legacy name-only API carry kKindAll.
2501 QHash<QString, quint8> m_hiddenKindMask;
2502
2503 // Per-name bitmask of SELECTED kinds — canonical typed selection.
2504 // m_selectedNames mirrors the keys for legacy name-based readers.
2505 // Names selected through the legacy name-only API carry kKindAll.
2506 QHash<QString, quint8> m_selectedKindMask;
2507
2508 QVector<NodeGeom> m_nodes;
2509 QVector<LinkGeom> m_links;
2510 QVector<CatchGeom> m_catchments;
2511 QVector<NodeGeom> m_gages;
2512
2513 // Per-feature bbox caches, parallel to m_links / m_catchments.
2514 // Computed once in buildGeometryCache() and refreshed on edits
2515 // that touch coords (applyNodeMove / applyLinkInteriorVertices /
2516 // applyNodeAdd). linksInRect / subcatchmentsInRect iterate these
2517 // arrays directly — no per-call name lookup, no per-call vertex
2518 // loop. Big-model rubber-band selects went from O(N²) (linkIndex
2519 // linear scan + per-link vertex bbox) to O(N) with constant work
2520 // per item.
2521 QVector<MapExtent> m_linkBboxes;
2522 QVector<MapExtent> m_catchBboxes;
2523
2524 // Scene-space coordinate cache, parallel to the SoAs above. Computed
2525 // once in rebuildSceneCoords() (on geometry change or CRS change) and
2526 // refreshed incrementally by edit paths. SWMMLayerItem::paint reads
2527 // from these directly — no per-vertex Transform()/toScene() call on
2528 // the paint hot path. Per-feature scene-space bounding rects support
2529 // viewport cull without a per-paint per-link bbox compute.
2530 QVector<QPointF> m_nodeScenePts;
2531 QVector<QRectF> m_linkSceneBBoxes;
2532 QVector<QVector<QPointF>> m_catchScenePts;
2533 QVector<QRectF> m_catchSceneBBoxes;
2534 QVector<QPointF> m_gageScenePts;
2535 QVector<OutletLine> m_catchOutletLines;
2536
2537 // Phase A.3 — flat-array link scene-coords. Replaces the previous
2538 // per-link QVector<QPointF> with one big std::vector<double> of
2539 // interleaved (x, y) pairs, plus per-link (offset, count). At 5M
2540 // links this saves ~120 MB of QVector overhead and gives the GL
2541 // pipeline (Phase B) a buffer it can stream into a VBO.
2542 //
2543 // m_linkSceneFlat[(m_linkVertexOffset[i] + v) * 2 + 0] = x
2544 // m_linkSceneFlat[(m_linkVertexOffset[i] + v) * 2 + 1] = y (Y-flipped)
2545 // v in [0, m_linkVertexCount[i])
2546 //
2547 // Doubles, not floats: SWMM models in projected CRS (state plane
2548 // feet, UTM meters) routinely have 6-7 digit coordinates, where
2549 // float's ~7 significant digits leaves ~0.5-1 m of quantisation
2550 // error. That shows up at high zoom as a visible gap between a
2551 // node glyph (drawn from the double m_nodeScenePts) and the link
2552 // endpoint that should be coincident with it. Y is pre-flipped so
2553 // paint feeds straight into QPainter::drawLines without per-vertex
2554 // math. GPU renderers that need single-precision VBOs subtract a
2555 // local origin and downcast on upload. Any vertex-count change
2556 // (rare; only when an editor adds/removes a vertex) triggers a
2557 // full rebuildSceneCoords; in-place node moves only rewrite the
2558 // affected link's slice of m_linkSceneFlat.
2559 std::vector<double> m_linkSceneFlat;
2560 std::vector<uint32_t> m_linkVertexOffset; // size == m_links.size()
2561 std::vector<uint32_t> m_linkVertexCount; // size == m_links.size()
2562
2563 // Phase A.2 of the 5M-rendering plan: selection / hidden state as
2564 // dense byte arrays parallel to the SoAs. SWMMLayerItem::paint reads
2565 // these directly instead of hashing each name into a QSet<QString>
2566 // every frame. Maintained alongside m_selectedNames / m_hiddenObjects
2567 // — those QString-keyed members remain the canonical state (used by
2568 // identify, attribute panel, persistence) but the flag arrays are
2569 // the fast path on the paint loop. Kept coherent by
2570 // setSelectedElementNames / setObjectVisible* / rebuildCategoryIndex.
2571 std::vector<uint8_t> m_nodeSelectedFlag; // 1 if m_nodes[i] selected
2572 std::vector<uint8_t> m_linkSelectedFlag;
2573 std::vector<uint8_t> m_catchSelectedFlag;
2574 std::vector<uint8_t> m_gageSelectedFlag;
2575 std::vector<uint8_t> m_nodeHiddenFlag;
2576 std::vector<uint8_t> m_linkHiddenFlag;
2577 std::vector<uint8_t> m_catchHiddenFlag;
2578 std::vector<uint8_t> m_gageHiddenFlag;
2579
2580 // Per-category row → SoA-index buckets. Built in buildGeometryCache,
2581 // cleared in closeEngine. Used by the virtualised Object Browser tree
2582 // model to resolve QModelIndex (category, row) → backing name in O(1)
2583 // without scanning the whole SoA on every data() call.
2584 QVector<int> m_nodesByType[4]; // junction/outfall/storage/divider
2585 QVector<int> m_linksByType[5]; // conduit/pump/orifice/weir/outlet
2586
2587 // Per-category count of hidden members. Kept in sync by
2588 // setObjectVisible, setObjectVisibleAt, setCategoryVisible so
2589 // categoryCheckState() is O(1). Seeded to 0 at cache rebuild.
2590 int m_hiddenCountByCategory[NumCategories] = {};
2591
2592 // Per-kind (sub-layer) opacity in [0,1], default 1.0. Multiplies each
2593 // feature's alpha in both paint paths; edited via the layer-tree Opacity
2594 // column on kind rows. NumCategories entries, brace-init below leaves
2595 // them 0 — the ctor fills 1.0 (see swmmmodellayer.cpp).
2596 qreal m_categoryOpacity[NumCategories];
2597
2598 // User-controlled display order for the Object Browser (Slice T.2).
2599 // Seeded to the enum sequence in rebuildCategoryIndex() so a fresh
2600 // model starts with the default order.
2601 QVector<Category> m_categoryOrder;
2602
2603 // Per-category object order overrides (Slice T.3). Absent key =
2604 // category uses its default bucket order; present key = visible
2605 // row r maps to `m_objectOrderOverrides[c][r]`, which is the SoA
2606 // index for nodes (m_nodes) / links (m_links) / catch (m_catchments)
2607 // / gages (m_gages). Sparse by design: only categories the user
2608 // actually reordered carry memory. Cleared on geometry rebuild so
2609 // stale indices can't survive an add/remove.
2610 QHash<Category, QVector<int>> m_objectOrderOverrides;
2611
2612 // name → (category, row) lookup seeded at cache time. Serves the
2613 // legacy name-based setObjectVisible(name, bool) entry point and
2614 // the SelectionManager → model-index mapping in the Object Browser
2615 // without a full O(N) scan of m_nodes / m_links per call.
2616 QHash<QString, QPair<Category, int>> m_objectLocation;
2617
2618 // Phase A.2 — name → (kind, SoA index) for the flag-array paint
2619 // path. `kind` selects which array (m_nodes / m_links /
2620 // m_catchments / m_gages) the SoA index addresses. Built alongside
2621 // m_objectLocation in rebuildCategoryIndex and kept coherent on
2622 // edits. Distinct from m_objectLocation because that one stores
2623 // *display* row inside per-category buckets, whereas paint needs
2624 // the raw SoA index — different translation, different consumers.
2625 enum class SoaKind : int8_t { Node = 0, Link = 1, Catch = 2, Gage = 3 };
2626 struct SoaLocation { SoaKind kind; int soaIdx; };
2627 QHash<QString, SoaLocation> m_nameToSoa;
2628
2629 // Per-kind name → SoA index. Deliberately SEPARATE from m_nameToSoa,
2630 // which cannot serve these lookups: it is single-keyed, and while nodes
2631 // beat links there (links insert only when absent), catchments and gages
2632 // insert UNCONDITIONALLY and therefore overwrite a colliding node or
2633 // link. identifyByName / nodeIndex / linkIndex must instead resolve
2634 // node → link → catchment → gage, which is what the linear scans they
2635 // replace did. SWMM keeps a separate namespace per kind, so such
2636 // collisions are legal and do occur in real models.
2637 //
2638 // Within a kind, first definition wins — matching the scans' behaviour
2639 // of returning the lowest index. Maintained in lockstep with
2640 // m_nameToSoa: rebuilt in rebuildCategoryIndex(), swapped in
2641 // renameObject(), extended in appendNodeSceneEntry() /
2642 // appendLinkSceneEntry(). Deletions always go through
2643 // rebuildCategoryIndex(), so no incremental erase path is needed.
2644 QHash<QString, int> m_nodeByName;
2645 QHash<QString, int> m_linkByName;
2646 QHash<QString, int> m_catchByName;
2647 QHash<QString, int> m_gageByName;
2648
2654 void rebuildFlagArrays();
2655
2668 void forgetStaleObjectState(const QString &name, quint8 kindBit);
2669
2670 SWMMElementSymbol m_junctionSym;
2673 SWMMElementSymbol m_virtualJunctionSym;
2676 SWMMElementSymbol m_inletJunctionSym;
2679 SWMMElementSymbol m_inletConnectorSym;
2680
2683 mutable QVector<InletConnector> m_inletConnectors;
2684 mutable bool m_inletConnectorsDirty = true;
2686 mutable int m_inletJunctionSupport = -1;
2689 QPointer<MapCanvas> m_editCanvas;
2691 void rebuildInletConnectors() const;
2692
2697 void syncSplitCaches(int li, int newNode, int newLink,
2698 const QString &newNodeName,
2699 const QString &newLinkName,
2700 const QString &origLinkName,
2701 int isVirtual, int isInlet);
2702
2706 void syncFuseCaches(int ni, int dn, int surviving);
2707 SWMMElementSymbol m_outfallSym;
2708 SWMMElementSymbol m_storageSym;
2709 SWMMElementSymbol m_dividerSym;
2710 SWMMElementSymbol m_conduitSym;
2711 SWMMElementSymbol m_pumpSym;
2712 SWMMElementSymbol m_orificeSym;
2713 SWMMElementSymbol m_weirSym;
2714 SWMMElementSymbol m_outletSym; // Slice FX.1 — Outlets honor showArrows independently of Conduits.
2715 SWMMElementSymbol m_subcatchSym;
2716 SWMMElementSymbol m_gageSym;
2717
2718 // Persistent per-kind symbol adapters keyed by subject routing id
2719 // ("model.junctions" …). Lazily built by elementSymbolAdapter(); owned
2720 // via QObject parenting. set*Symbol keeps their cached structs truthful
2721 // through resyncSymbolAdapter().
2722 QHash<QString, SwmmElementSymbolAdapter *> m_symbolAdapters;
2725 void resyncSymbolAdapter(const QString &routingId,
2726 const SWMMElementSymbol &s);
2727
2728 // Data-edit epoch for derived style/label caches. Bumped whenever
2729 // modelEdited or attributeChanged fires (self-connections in the ctor)
2730 // so consumers (SWMMLayerItem's label cache) can detect staleness
2731 // without wiring their own signal plumbing. Distinct from
2732 // m_geomRevision, which tracks scene-coordinate rebuilds only.
2733 quint64 m_editRevision = 0;
2737 bool m_derivedStyleCachesPending = false;
2742 void invalidateDerivedStyleCaches();
2743
2744 // Slice BI Phase 8.13.6.5 — renderer plumbing. Eagerly initialised in
2745 // the ctor (default placeholder: SingleSymbolRenderer) so renderer()
2746 // never returns null. The existing paint loop still reads the per-kind
2747 // m_*Sym members; the paint refactor sub-phase swaps in a
2748 // MultiKindRenderer adapter and flips the paint path.
2749 std::unique_ptr<OpenSWMM::Render::IFeatureRenderer> m_renderer;
2750
2751 // Slice BI-MK.1 / BI-MK.LT (2026-05-24) — per-kind renderer storage.
2752 // Indexed by Category ordinal; size == NumCategories. SymbologyDialog's
2753 // left-pane picker and the layer-tree sub-row right-click menu drive
2754 // edits here. Single-symbol entries are kept in sync with the legacy
2755 // m_*Sym fields (write-through both directions) so the existing paint
2756 // loop reflects user edits without a per-feature symbolFor() refactor.
2757 std::vector<std::unique_ptr<OpenSWMM::Render::IFeatureRenderer>> m_kindRenderers;
2758
2759 // Slice B.4 — RuleList mirroring the per-kind renderers. Lazy-built
2760 // on first ruleList() call (cloned from m_kindRenderers). mutable
2761 // so the const override can populate on first read.
2762 mutable std::unique_ptr<OpenSWMM::Render::RuleList> m_ruleList;
2763 void buildRuleListLazy() const;
2764 // M1 — set when a kind renderer changes after the RuleList was built, so
2765 // the next ruleList() rebuilds from the live per-kind renderers instead
2766 // of handing back a stale mirror (the "dialog doesn't match what's drawn
2767 // on open" bug). Rebuild happens only at read time (dialog open), never
2768 // mid-session, so an open dialog's rule pointers stay valid.
2769 mutable bool m_ruleListDirty = false;
2770
2771 // M2 — keep the per-kind renderer (the single source of truth)
2772 // consistent when a legacy struct setter is called directly (e.g.
2773 // preferences / project load). Updates only SingleSymbol renderers (in
2774 // place — no signal, no recursion); classified renderers are left intact
2775 // since the struct is the single-symbol fallback. Marks the RuleList
2776 // dirty so the next dialog open reflects the change.
2777 void syncSingleRendererFromStruct(Category c, const SWMMElementSymbol &s);
2778
2779 // Slice BI Phase 8.13.6.4 (2026-05-24) — per-feature colour-override
2780 // cache populated when a kind's renderer is Graduated / Categorized /
2781 // RuleBased. Indexed by Category × SoA index. The painter checks
2782 // m_kindUsesOverrides[c] to switch between the legacy bucketed fast
2783 // path and the per-feature override path.
2784 QVector<QColor> m_kindFeatureColors[NumCategories];
2785 QVector<double> m_kindFeatureSizes[NumCategories];
2786 QVector<double> m_kindFeatureOffsets[NumCategories];
2787 QVector<int> m_kindFeatureShapes[NumCategories];
2788 bool m_kindHasAnyOffset[NumCategories] = {};
2789 bool m_kindUsesOverrides[NumCategories] = {};
2790
2791 QStringList m_selectedNames;
2792 // Canonical typed selection (ordered). m_selectedNames and
2793 // m_selectedKindMask are derived mirrors, rebuilt atomically in
2794 // setSelectedElements().
2795 QVector<SelectedElement> m_selectedElements;
2796
2797 // Engine-table partition cache (curves vs. timeseries). The engine
2798 // stores both in the same unified table list keyed by type; without
2799 // this cache, the Object Browser data-category views and pickers
2800 // re-walked the entire table list on every row count / name lookup —
2801 // O(N) per call × N rows = O(N²) per refresh. Filled lazily in
2802 // ensureTablePartition(); invalidated when a curve or timeseries is
2803 // added / removed / renamed, and on every modelLoaded().
2804 mutable QVector<int> m_curveTableIdx;
2805 mutable QVector<int> m_tsTableIdx;
2806 mutable bool m_tablePartitionDirty = true;
2807 void ensureTablePartition() const;
2808
2809public:
2814 void invalidateDataObjectCache() { m_tablePartitionDirty = true; }
2815
2816private:
2817
2818 // GDAL transform (layer CRS → canvas CRS)
2819 class OGRCoordinateTransformation *m_transform = nullptr;
2820
2821 // Cached inverse (canvas CRS → layer CRS); built lazily on first
2822 // transformCanvasToLayer() call and invalidated whenever m_transform is
2823 // rebuilt or destroyed. Mutable so the public const accessor can populate.
2824 mutable class OGRCoordinateTransformation *m_inverseTransform = nullptr;
2825
2826 // The (layer CRS, canvas CRS) pair m_transform was last built from, so
2827 // rebuildTransform() can no-op when nothing about the projection
2828 // changed. One srsChanged emission reaches this layer through two
2829 // independent listeners (see rebuildTransform), and each arrival
2830 // otherwise redoes rebuildSceneCoords over every node, link and
2831 // subcatchment vertex. WKT rather than the authority string because a
2832 // Local CRS has no authority code — precisely the case on the models
2833 // where the redundant rebuild costs the most.
2834 QString m_transformLayerWkt;
2835 QString m_transformCanvasWkt;
2836 bool m_transformValid = false;
2837
2838 // Dirty flag — skip scene rebuild when only the view extent changed
2839 bool m_needsRebuild = true;
2840
2841 // KD-tree spatial index for point-feature queries (nodes + gages).
2842 // Mutable so const query methods (identifyAt, nodesInRect, …) can
2843 // trigger a lazy rebuild without breaking const-correctness.
2844 mutable bool m_kdDirty = true;
2845 mutable std::unique_ptr<SWMMKdTrees> m_kdTrees;
2846
2847 // Batched scene renderer (created in populateScene). Edit paths that
2848 // mutate SoA coordinates call refreshBoundingRect() on it so the
2849 // scene's BSP index stays aligned after moves beyond the prior
2850 // extent. Cleared in depopulateScene.
2851 class SWMMLayerItem *m_batchedItem = nullptr;
2852
2853 // Slice BS Phase 6.9.2 — hydrograph MVC models, lazily constructed on
2854 // first accessor call. Owned by the layer (parented through the
2855 // QObject tree, destroyed with it). Shared across all consumer UIs.
2856 HydrographGroupListModel *m_uhGroupListModel = nullptr;
2857 HydrographRtkTableModel *m_uhRtkModel = nullptr;
2858 HydrographIaTableModel *m_uhIaModel = nullptr;
2859 HydrographDecayTableModel *m_uhDecayModel = nullptr;
2860
2861 // Lazy-loaded data-object registries scoped to the current engine
2862 // handle. Forward-declared as `QObject*` to keep this header free of
2863 // the registry includes; the .cpp downcasts to the concrete type.
2864 // Shared across every UI that mutates these data objects so all
2865 // views see the same provider instances.
2866 QObject *m_tsRegistry = nullptr;
2867 void *m_tsRegistryEngineHandle = nullptr;
2868 QObject *m_patternRegistry = nullptr;
2869 void *m_patternRegistryEngineHandle = nullptr;
2870 QObject *m_curveRegistry = nullptr;
2871 void *m_curveRegistryEngineHandle = nullptr;
2872
2873 // Slice BR Phase 6.8.1 — control-rule registry mirror.
2874 QObject *m_controlRuleRegistry = nullptr;
2875 void *m_controlRuleRegistryEngineHandle = nullptr;
2876
2877 // Slice BQ Phase 6.7.4 — transect registry mirror.
2878 QObject *m_transectRegistry = nullptr;
2879 void *m_transectRegistryEngineHandle = nullptr;
2880
2881 // Street registry mirror (parametric [STREETS] cross-sections).
2882 QObject *m_streetRegistry = nullptr;
2883 void *m_streetRegistryEngineHandle = nullptr;
2884
2885 // Pollutant registry mirror ([POLLUTANTS]).
2886 QObject *m_pollutantRegistry = nullptr;
2887 void *m_pollutantRegistryEngineHandle = nullptr;
2888
2889 // Land-use registry mirror ([LANDUSES]).
2890 QObject *m_landUseRegistry = nullptr;
2891 void *m_landUseRegistryEngineHandle = nullptr;
2892
2893 // Aquifer registry mirror ([AQUIFERS]).
2894 QObject *m_aquiferRegistry = nullptr;
2895 void *m_aquiferRegistryEngineHandle = nullptr;
2896
2897 // Snowpack registry mirror ([SNOWPACKS]).
2898 QObject *m_snowpackRegistry = nullptr;
2899 void *m_snowpackRegistryEngineHandle = nullptr;
2900
2901 // Inlet registry mirror ([INLETS]).
2902 QObject *m_inletRegistry = nullptr;
2903 void *m_inletRegistryEngineHandle = nullptr;
2904
2905 // LID-control registry mirror ([LID_CONTROLS]).
2906 QObject *m_lidControlRegistry = nullptr;
2907 void *m_lidControlRegistryEngineHandle = nullptr;
2908
2909 // User-flags store — see ensureUserFlagsModel().
2910 openswmmvis::ui::UserFlagsModel *m_userFlagsModel = nullptr;
2911 void *m_userFlagsModelEngineHandle = nullptr;
2912};
2913
2914Q_DECLARE_METATYPE(SWMMModelLayer *)
2915Q_DECLARE_METATYPE(SWMMElementSymbol)
2916Q_DECLARE_OPERATORS_FOR_FLAGS(SWMMModelLayer::QsgKinds)
2917
2918#endif // SWMMMODELLAYER_H
Definition hydrographmodels.h:161
Definition hydrographmodels.h:46
Definition hydrographmodels.h:118
Definition hydrographmodels.h:80
The central map display widget — QGIS-style hybrid rendering.
Definition mapcanvas.h:63
An axis-aligned bounding box in the coordinate space of a given CRS.
Definition mapextent.h:26
Classifies a numeric attribute into bins and assigns a colour per bin.
Definition graduatedrenderer.h:63
Interface every themeable layer implements so renderer panels can populate attribute combos without h...
Definition iattributeprovider.h:73
Abstract interface — every vector layer's paint path goes here.
Definition ifeaturerenderer.h:85
Ordered owning container for Rules on one layer.
Definition rulelist.h:48
Abstract base class for all layers displayed in the MapCanvas.
Definition openswmmvislayer.h:116
double opacity() const
Returns the layer opacity in the range [0.0, 1.0]. 0.0 = fully transparent; 1.0 = fully opaque.
Definition openswmmvislayer.cpp:103
QString name() const
Returns the user-visible name of this layer.
Definition openswmmvislayer.cpp:62
Top-level project container managing sessions, the SWMM model layer, and persistence paths for one SW...
Definition openswmmvisworkspace.h:42
Definition swmmlayeritem.h:41
Definition swmmlayerqsgrenderer.h:42
Definition swmmmodellayer.h:1899
BulkEdit(SWMMModelLayer *layer)
Definition swmmmodellayer.h:1901
BulkEdit & operator=(const BulkEdit &)=delete
~BulkEdit()
Definition swmmmodellayer.h:1905
BulkEdit(const BulkEdit &)=delete
Renders the SWMM network elements (nodes, links, subcatchments, rain gages) for one OpenSWMMEngine mo...
Definition swmmmodellayer.h:133
QObject * ensureInletRegistry()
Lazy accessor for the project-scoped InletRegistry.
Definition swmmmodellayer.cpp:7183
QStringList gagesInPolygon(const QPolygonF &canvasPoly) const
Definition swmmmodellayer.cpp:8968
bool kindHasAnyOffset(Category c) const
Definition swmmmodellayer.cpp:3296
void controlRulesChanged(const QString &ruleName)
void setCategoryVisible(Category c, bool visible)
Bulk-toggle every member of a category. Used by the group-header checkbox in the Object Browser; emit...
Definition swmmmodellayer.cpp:2313
int featureShape(Category c, int idx) const
Definition swmmmodellayer.cpp:3280
bool rollbackTailSubcatchAdd(const QString &name)
Definition swmmmodellayer.cpp:5976
void setInletJunctionSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2566
void modelFilePathChanged(const QString &path)
PickResult pickAt(double sceneX, double sceneY, double tolerance) const
Definition swmmmodellayer.cpp:4334
QSet< QString > hiddenObjects() const
Names currently hidden via per-object toggles. Used by the Object Browser to seed leaf-row check stat...
Definition swmmmodellayer.h:437
QObject * ensureTimeseriesRegistry()
Definition swmmmodellayer.cpp:6576
void qsgRenderKindsChanged(QsgKinds kinds)
qreal sizeForClass(const QString &classKey) const
Definition swmmmodellayer.cpp:3002
void showLinksChanged(bool show)
bool isConduit(int linkIdx) const
Returns true when the link at linkIdx is a conduit (the only link type whose length is stored as an i...
Definition swmmmodellayer.cpp:4578
bool applyTransectAdd(const QString &name, QString *outError=nullptr)
Create a new transect. Refuses on duplicate or empty name.
Definition swmmmodellayer.cpp:7260
void setInletConnectorSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2568
void setOutletSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2573
bool applyInsertInletJunction(const QString &linkName, double t, const QString &newNodeName, const QString &newLinkName, const QString &inletId, const QString &captureNode, int *outNodeIdx=nullptr, int *outLinkIdx=nullptr, QString *outError=nullptr)
Split STREET conduit linkName at t, inserting an inlet junction wired to inletId / captureNode,...
Definition swmmmodellayer.cpp:5456
bool applySubcatchDelete(const QString &name)
Definition swmmmodellayer.cpp:6352
int nodeIndex(const QString &name) const
Returns the cache index of the node with the given name, or -1 if none matches.
Definition swmmmodellayer.cpp:4215
QObject * ensureTransectRegistry()
Lazy accessor for the project-scoped TransectRegistry.
Definition swmmmodellayer.cpp:7014
void modelLoaded()
static SWMM_Engine openEngineForPath(const QString &path, QString *errorDetail, qint64 *openMs=nullptr)
Create + open an engine for path (worker-thread safe).
Definition swmmmodellayer.cpp:798
OpenSWMM::Render::IFeatureRenderer * kindRenderer(Category c) const
Definition swmmmodellayer.cpp:2909
bool setOption(const QByteArray &key, const QString &value)
Write a single SWMM OPTIONS key. On success emits optionsChanged({key}). Returns true on success,...
Definition swmmmodellayer.cpp:4553
bool applyLinkBarrels(int linkIdx, int barrels)
Slice SC.1 — Write the parallel-barrels count. Emits attributeChanged on success.
Definition swmmmodellayer.cpp:4798
HydrographRtkTableModel * hydrographRtkModel()
Definition swmmmodellayer.cpp:6558
bool applyControlRuleReplace(const QString &name, const QString &newBody, QString *outError=nullptr)
Replace the body of an existing rule (typically the user- edited text from the code editor)....
Definition swmmmodellayer.cpp:6863
bool cachedNodeCoord(int idx, double *x, double *y) const
Cached layer-CRS coordinate of a node by index.
Definition swmmmodellayer.cpp:4230
QString getOption(const QByteArray &key, const QString &fallback={}) const
Read a single SWMM OPTIONS key from the engine. Returns the fallback when the engine has no value for...
Definition swmmmodellayer.cpp:4542
void setShowLabels(bool show)
Definition swmmmodellayer.cpp:1402
static constexpr Category CatOrifices
Definition swmmmodellayer.h:162
SWMMElementSymbol inletJunctionSymbol() const
Definition swmmmodellayer.cpp:2525
bool linkArrowOnlyWhenFlowPos(Category c) const
Definition swmmmodellayer.cpp:2849
QString objectNameAt(Category c, int row) const
Object name at (category, row). O(1) — reads through the per-category index buckets populated in buil...
Definition swmmmodellayer.cpp:1586
OpenSWMMVis::SwmmCategory Category
The SWMM-element Category enum.
Definition swmmmodellayer.h:155
void setShowRainGages(bool show)
Definition swmmmodellayer.cpp:1398
void resetKindRendererToDefaults(Category c)
Definition swmmmodellayer.cpp:3522
bool showNodes
Definition swmmmodellayer.h:201
bool applyLinkInteriorVertices(int linkIdx, const QVector< QPointF > &interior)
Apply interior vertices to a link: engine + cache, rebuilding the cached polyline from the node endpo...
Definition swmmmodellayer.cpp:7437
void modelLoadError(const QString &errorMessage)
void setGlRenderingEnabled(bool on)
Definition swmmmodellayer.h:397
double polylineLengthInModelUnits(const QVector< QPointF > &vertices) const
Compute polyline length in the SWMM model's expected linear unit (feet for US-customary FLOW_UNITS — ...
Definition swmmmodellayer.cpp:4495
void setOrificeSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2571
void geometryChanged()
bool crsAssigned() const noexcept
Whether the layer's CRS was ASSIGNED — read from the .inp's [OPTIONS] CRS, or set after load by the u...
Definition swmmmodellayer.h:238
bool applyTransectRemove(const QString &name, QString *outError=nullptr)
Remove a transect by name.
Definition swmmmodellayer.cpp:7312
QStringList linksInRect(double canvasMinX, double canvasMinY, double canvasMaxX, double canvasMaxY) const
Names of all links whose polyline bbox overlaps the canvas-CRS rectangle. Backed by a per-link bbox c...
Definition swmmmodellayer.cpp:8879
void setColorForClass(const QString &classKey, const QColor &color)
Definition swmmmodellayer.cpp:2986
bool applyFuseInletJunction(const QString &nodeName, QString *outError=nullptr)
Inverse of applyInsertInletJunction — drops the usage row and re-fuses the conduit pair (swmm_inlet_j...
Definition swmmmodellayer.cpp:5501
bool adoptNewEngine(const NewProjectSpec &spec, QList< QString > &warnings, QList< QString > &errors)
In-memory sibling of the loadModel path: createBlankEngine → buildFromEngine → adoptOpenEngine,...
Definition swmmmodellayer.cpp:1020
int categoryCount(Category c) const
Number of objects in the given category. O(1).
Definition swmmmodellayer.cpp:1570
bool previewGageMove(int idx, double newX, double newY)
Definition swmmmodellayer.cpp:4463
void setKindRenderer(Category c, std::unique_ptr< OpenSWMM::Render::IFeatureRenderer > r)
Definition swmmmodellayer.cpp:3021
static QString virtualJunctionRuleText(int engineErrorCode)
Actionable text for a virtual-junction / inlet-junction rule code (609..621 VJ, 623....
Definition swmmmodellayer.cpp:4984
bool applyLinkLength(int linkIdx, double length)
Write the conduit length for a link. No-op if the link is not a conduit.
Definition swmmmodellayer.cpp:4764
bool applySubcatchArea(int idx, double areaInModelUnits)
Definition swmmmodellayer.cpp:8197
void populateScene(QGraphicsScene *scene, const MapExtent &canvasExtent, const SpatialReferenceSystem *canvasSRS) override
Creates / updates QGraphicsItems representing this layer in the scene.
Definition swmmmodellayer.cpp:4089
static SWMM_Engine createBlankEngine(const NewProjectSpec &spec, QString *errorDetail)
Create a blank BUILDING-state engine (swmm_engine_new) and stamp the spec's defaults on it via the op...
Definition swmmmodellayer.cpp:872
QObject * ensureCurveRegistry()
Definition swmmmodellayer.cpp:6695
void setObjectsVisible(const QList< QString > &names, bool visible)
Batch form — apply the same visibility to every name in names with a single repaintRequested emission...
Definition swmmmodellayer.cpp:1502
static quint8 kindBitForCategory(Category c) noexcept
Definition swmmmodellayer.cpp:1444
int linkFromNodeIdx(int linkIdx) const
Definition swmmmodellayer.cpp:4614
QVector< QPointF > cachedLinkInteriorVertices(int idx) const
Cached interior-only polyline of a link (endpoints stripped).
Definition swmmmodellayer.cpp:4295
bool pushInletUsageRemoval(int hostKind, int hostIdx)
Undoable counterpart of applyRemoveInletUsage().
Definition swmmmodellayer.cpp:5555
bool applyControlRuleRename(const QString &oldName, const QString &newName, QString *outError=nullptr)
Rename oldName to newName. Rewrites the RULE <name> header on the target slot's body so the engine ro...
Definition swmmmodellayer.cpp:6896
int linkToNodeIdx(int linkIdx) const
Definition swmmmodellayer.cpp:4623
QPolygonF polygonCanvasToLayer(const QPolygonF &poly) const
Transform every vertex of a canvas-CRS polygon into layer CRS.
Definition swmmmodellayer.cpp:8937
void setObjectVisible(const QString &name, bool visible)
Definition swmmmodellayer.cpp:1462
bool applyInsertVirtualJunction(const QString &linkName, double t, const QString &newNodeName, const QString &newLinkName, int *outNodeIdx=nullptr, int *outLinkIdx=nullptr, QString *outError=nullptr)
Split conduit linkName at normalized polyline position t, inserting a virtual junction,...
Definition swmmmodellayer.cpp:5129
bool engineSupportsInletJunctions() const
Tri-state capability probe, cached for the layer's lifetime: true when the bound engine exposes the i...
Definition swmmmodellayer.cpp:5329
void reloadGeometry()
Re-read every node / link / subcatchment coordinate from the engine and rebuild the geometry cache + ...
Definition swmmmodellayer.cpp:4189
openswmmvis::ui::UserFlagsModel * ensureUserFlagsModel()
Lazy accessor for the project-scoped UserFlagsModel. Returns nullptr if the engine isn't open.
Definition swmmmodellayer.cpp:7239
SWMM_Engine engine() const
Definition swmmmodellayer.cpp:716
bool applySetVirtual(const QString &name, bool makeVirtual, QString *outError=nullptr)
Set or clear a node's virtual-junction flag via swmm_node_set_virtual (full engine validation)....
Definition swmmmodellayer.cpp:5017
QObject * ensurePatternRegistry()
Definition swmmmodellayer.cpp:6651
void setSelectedElements(const QVector< SelectedElement > &sel)
Replaces the selection with typed entries (kind-exact).
Definition swmmmodellayer.cpp:3562
QVariantMap identifyByName(const QString &name, quint8 kindMask=kKindAll) const
Identify an object by name (instead of by map coordinates).
Definition swmmmodellayer.cpp:3626
QStringList nodesInPolygon(const QPolygonF &canvasPoly) const
Definition swmmmodellayer.cpp:8949
QObject * ensureControlRuleRegistry()
Lazy accessor for the project-scoped ControlRuleRegistry. Lifetime is bound to the layer; the registr...
Definition swmmmodellayer.cpp:6993
void setObjectOrder(Category cat, const QVector< int > &soaIndices)
Install a user-defined display order for the given category. soaIndices is a permutation of the under...
Definition swmmmodellayer.cpp:2231
class MapExtent objectExtent(const QString &name) const
Layer-CRS bounding box of a cached object by name.
Definition swmmmodellayer.cpp:3814
SWMMElementSymbol dividerSymbol() const
Definition swmmmodellayer.cpp:2523
static constexpr Category CatWeirs
Definition swmmmodellayer.h:163
bool qsgOwnsKind(QsgKind k) const noexcept
Definition swmmmodellayer.h:388
bool showLinks
Definition swmmmodellayer.h:203
SWMMElementSymbol virtualJunctionSymbol() const
Definition swmmmodellayer.cpp:2524
void rendererChanged()
Slice BI Phase 8.13.6.5 — emitted when setRenderer() swaps the renderer pointer.
int linkEndForNode(int linkIdx, int nodeIdx) const
Which end of a link is attached to nodeIdx: 0 = from, 1 = to, or -1 if the node is not an endpoint of...
Definition swmmmodellayer.cpp:4602
void rebuildKindFeatureColors(Category c)
Definition swmmmodellayer.cpp:3344
bool showRainGages
Definition swmmmodellayer.h:207
QVector< Category > categoryOrder() const
User-configurable display order of categories in the Object Browser. Defaults to the enum sequence at...
Definition swmmmodellayer.cpp:2393
double engineLinkLength(int linkIdx) const
Returns the conduit length recorded in the engine, or -1 if the link is not a conduit / is out of ran...
Definition swmmmodellayer.cpp:4485
bool adoptOpenEngine(SWMM_Engine engine, QList< QString > &warnings, QList< QString > &errors, qint64 openMs=-1, qint64 soaMs=0, qint64 geomMs=0)
Adopt an engine whose geometry was already built by buildFromEngine(). GUI-thread only: assigns the e...
Definition swmmmodellayer.cpp:1234
void closeEngine()
Definition swmmmodellayer.cpp:718
void setObjectVisibleAt(Category c, int row, bool visible)
Toggle visibility for a single leaf referenced by (category, row). Updates m_hiddenObjects plus the c...
Definition swmmmodellayer.cpp:2268
static constexpr quint8 kKindCatch
Definition swmmmodellayer.h:976
SWMMElementSymbol pumpSymbol() const
Definition swmmmodellayer.cpp:2528
QList< OpenSWMM::Render::LegendSymbolItem > legendSymbolItems() const
Definition swmmmodellayer.cpp:2946
static constexpr Category CatJunctions
Definition swmmmodellayer.h:156
void setLinkArrowSize(Category c, double pixels)
Definition swmmmodellayer.cpp:2773
SWMMElementSymbol outfallSymbol() const
Definition swmmmodellayer.cpp:2521
void endBulkEdit()
Definition swmmmodellayer.cpp:6102
void setLabelConfig(const OpenSWMM::Render::LabelConfig &cfg) override
Slice X.18 — full label configuration.
Definition swmmmodellayer.cpp:1426
void clearSelection()
Definition swmmmodellayer.cpp:3611
bool applyNodeAdd(const QString &name, int nodeType, double x, double y, int *outIdx=nullptr)
Add a new node: engine + cache. Engine must be OPENED.
Definition swmmmodellayer.cpp:5641
bool rollbackTailLinkAdd(const QString &name)
Definition swmmmodellayer.cpp:5811
static constexpr Category CatOutfalls
Definition swmmmodellayer.h:157
bool applyHydrographClearMonths(const QString &name)
Definition swmmmodellayer.cpp:6515
void optionsChanged(const QStringList &keys)
Emitted after any OPTIONS key has been written to the engine (via setOption() — the single entry poin...
void classifyGraduatedIfNeeded(Category c, OpenSWMM::Render::GraduatedRenderer *g)
Definition swmmmodellayer.cpp:3302
bool transformCanvasToLayer(double cx, double cy, double &lx, double &ly) const
Reverse-transform a canvas-CRS coordinate into the layer's native CRS.
Definition swmmmodellayer.cpp:9089
int linkIndex(const QString &name) const
Returns the cache index of the link with the given name, or -1 if none matches.
Definition swmmmodellayer.cpp:4221
bool applyLinkFlip(int linkIdx)
Reverse link linkIdx: the upstream node becomes the downstream node and vice versa,...
Definition swmmmodellayer.cpp:4929
SwmmElementSymbolAdapter * elementSymbolAdapter(const QString &routingId)
The layer's persistent per-kind symbol adapter for a subject routing id ("model.junctions" … "model....
Definition swmmmodellayer.cpp:2585
bool applyGageMove(int idx, double newX, double newY)
Move a rain gage: engine [SYMBOLS] coordinate + cached scene point, in lockstep (a bare swmm_spatial_...
Definition swmmmodellayer.cpp:5833
void convertLinkOffsets(bool toElevation, bool convertValues)
Apply the user's answer to legacy UpdateOffsets' "convert all link offsets?...
Definition swmmmodellayer.cpp:4709
static constexpr Category CatDividers
Definition swmmmodellayer.h:159
double linkFlow(int linkIdx) const
Definition swmmmodellayer.cpp:2878
void refreshScene(QGraphicsScene *scene, const MapExtent &canvasExtent, const SpatialReferenceSystem *canvasSRS) override
Smart scene refresh — updates existing items instead of destroying and recreating.
Definition swmmmodellayer.cpp:4168
void setVirtualJunctionSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2564
bool applyTransectRename(const QString &oldName, const QString &newName, QString *outError=nullptr)
Rename. Refuses on duplicate (case-insensitive) or empty.
Definition swmmmodellayer.cpp:7281
bool applyGageDelete(const QString &name)
Definition swmmmodellayer.cpp:6230
QsgKind
Definition swmmmodellayer.h:372
@ QsgGages
Rain gages.
Definition swmmmodellayer.h:377
@ QsgCatch
Subcatchments (polygons + outlet lines).
Definition swmmmodellayer.h:376
@ QsgLinks
Conduits / pumps / orifices / weirs / outlets.
Definition swmmmodellayer.h:375
@ QsgNodes
Junctions / outfalls / storage / dividers.
Definition swmmmodellayer.h:374
@ QsgNone
Definition swmmmodellayer.h:373
bool supportsClassEdit(OpenSWMM::Render::ClassEditKind kind) const
Definition swmmmodellayer.cpp:2968
void setLinkArrowColor(Category c, const QColor &col)
Definition swmmmodellayer.cpp:2831
bool applySetInlet(const QString &name, bool makeInlet, QString *outError=nullptr)
Set or clear a node's inlet-junction flag via swmm_node_set_inlet. Clearing leaves the node a virtual...
Definition swmmmodellayer.cpp:5424
SWMMElementSymbol conduitSymbol() const
Definition swmmmodellayer.cpp:2527
bool applyHydrographRemoveEntry(const QString &name, int month, int response)
Definition swmmmodellayer.cpp:6503
bool glRenderingEnabled() const noexcept
Definition swmmmodellayer.h:395
bool applyTransectSetComments(const QString &name, const QString &comments)
Definition swmmmodellayer.cpp:7335
double maxMarkerHalfBoundPx() const
Largest rendered marker half-bound across every SWMM element type, in PIXELS. Callers use this as a f...
Definition swmmmodellayer.cpp:1547
bool applyTransectSetStations(const QString &name, const QVector< QPair< double, double > > &stations)
Snapshot-and-rewrite the full station list.
Definition swmmmodellayer.cpp:7411
bool applyTransectSetEncroachmentStations(const QString &name, double xLeft, double xRight)
Definition swmmmodellayer.cpp:7379
QStringList subcatchmentsInPolygon(const QPolygonF &canvasPoly) const
Definition swmmmodellayer.cpp:9009
void setPumpSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2570
bool applyNodeDelete(const QString &name, QStringList *cascadeLinkNames=nullptr)
Delete a node, cascade-deleting all attached links.
Definition swmmmodellayer.cpp:6150
bool applyDeleteMany(const QStringList &nodeNames, const QStringList &linkNames, const QStringList &subcatchNames, const QStringList &gageNames, QStringList *cascadeLinkNames=nullptr)
Batch deletion (perf-plan Phase A2): one swmm_*_delete_many engine call per kind, one order-preservin...
Definition swmmmodellayer.cpp:6250
void setLinkArrowsEnabled(Category c, bool enabled)
Definition swmmmodellayer.cpp:2742
bool applyNodeMove(int idx, double newX, double newY)
Apply a new coordinate to a node: engine + cache + attached link endpoint updates....
Definition swmmmodellayer.cpp:4632
bool applyRdiiDecaySet(const QString &name, int response, double k_dep, double k_0, double k_T, double T_ref, double theta_rec, double T_freeze, bool snowOn=false, double snow_T=1.0, double snow_ddf=0.0)
Definition swmmmodellayer.cpp:6525
bool applyLinkDelete(const QString &name)
Definition swmmmodellayer.cpp:6210
bool loadModel(QList< QString > &warnings, QList< QString > &errors)
Loads (or reloads) the SWMM input file and rebuilds geometry caches.
Definition swmmmodellayer.cpp:779
void setModelFilePath(const QString &path)
Definition swmmmodellayer.cpp:707
static constexpr Category CatStorage
Definition swmmmodellayer.h:158
bool applyLinkCulvertCode(int linkIdx, int code)
Slice SC.1 — Write the FHWA culvert chart code (0 = none). Emits attributeChanged on success.
Definition swmmmodellayer.cpp:4808
void categoryOrderChanged()
QString modelFilePath
Definition swmmmodellayer.h:199
DataCategory
Slice BM.0 — non-spatial data-object categories surfaced below the spatial section in the Object Brow...
Definition swmmmodellayer.h:182
@ NumDataCategories
Definition swmmmodellayer.h:196
@ DataTimeSeries
Definition swmmmodellayer.h:184
@ DataStreets
Definition swmmmodellayer.h:194
@ DataPollutants
Definition swmmmodellayer.h:187
@ DataLIDControls
Definition swmmmodellayer.h:186
@ DataTransects
Definition swmmmodellayer.h:192
@ DataSnowpacks
Definition swmmmodellayer.h:190
@ DataHydrographs
Definition swmmmodellayer.h:193
@ DataLandUses
Definition swmmmodellayer.h:188
@ DataCurves
Definition swmmmodellayer.h:183
@ DataInlets
Definition swmmmodellayer.h:195
@ DataAquifers
Definition swmmmodellayer.h:189
@ DataPatterns
Definition swmmmodellayer.h:185
@ DataControls
Definition swmmmodellayer.h:191
void setOutfallSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2558
void onCanvasCRSChanged(const SpatialReferenceSystem *newCanvasSRS) override
Called when the user changes the canvas CRS so layers can pre-compute any CRS-dependent transform cac...
Definition swmmmodellayer.cpp:4162
SWMMElementSymbol inletConnectorSymbol() const
Definition swmmmodellayer.cpp:2526
bool applyHydrographSetGage(const QString &name, const QString &gageName)
Definition swmmmodellayer.cpp:6464
void showLabelsChanged(bool show)
void clearObjectOrder(Category cat)
Definition swmmmodellayer.cpp:2219
bool applyLinkConvert(const QString &name, int newLinkType, QStringList *outCleared=nullptr, QStringList *outWarnings=nullptr, QString *outError=nullptr)
Convert link name to newLinkType (SWMM_LinkType value) via swmm_link_convert. Endpoints,...
Definition swmmmodellayer.cpp:4883
void setSubcatchmentSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2574
qreal categoryOpacity(Category c) const
Per-kind (sub-layer) opacity in [0,1], applied on top of the layer opacity. Lets the user fade,...
Definition swmmmodellayer.cpp:2360
QColor featureColor(Category c, int idx) const
Definition swmmmodellayer.cpp:3264
void showRainGagesChanged(bool show)
void buildFromEngine(SWMM_Engine engine, qint64 *soaMsOut=nullptr, qint64 *geomMsOut=nullptr)
Populate the SoA arrays + geometry caches from engine.
Definition swmmmodellayer.cpp:1039
QObject * ensureStreetRegistry()
Lazy accessor for the project-scoped StreetRegistry.
Definition swmmmodellayer.cpp:7043
bool applyTransectSetModifiers(const QString &name, double stationMul, double elevOffset, double meander)
Definition swmmmodellayer.cpp:7394
void setCategoryOrder(const QVector< Category > &order)
Definition swmmmodellayer.cpp:2398
bool inletUsageFor(int hostKind, int hostIdx, SWMM_InletUsage *out) const
Read the inlet-usage row hosted by (hostKind, hostIdx).
Definition swmmmodellayer.cpp:5349
double featureSize(Category c, int idx) const
Definition swmmmodellayer.cpp:3272
bool applyTransectSetBankStations(const QString &name, double xLeft, double xRight)
Definition swmmmodellayer.cpp:7364
bool applySubcatchAdd(const QString &name, const QVector< QPointF > &polygon, int *outIdx=nullptr)
Definition swmmmodellayer.cpp:5927
int soaIndexAt(Category c, int row) const
SoA index at (category, row) — the index objectNameAt resolves the name from, and therefore also the ...
Definition swmmmodellayer.cpp:1635
static constexpr quint8 kKindNode
Definition swmmmodellayer.h:974
QObject * ensurePollutantRegistry()
Lazy accessor for the project-scoped PollutantRegistry.
Definition swmmmodellayer.cpp:7071
int dataObjectCount(DataCategory c) const
Slice BM.0 — number of non-spatial data objects in c. Returns 0 when the engine handle is null or whe...
Definition swmmmodellayer.cpp:1738
bool applyTransectSetRoughness(const QString &name, double nLeft, double nRight, double nChannel)
Definition swmmmodellayer.cpp:7349
bool elementPosition(const QString &name, double *x, double *y) const
Layer-CRS position of any named element (node, gage, or link midpoint) by object name.
Definition swmmmodellayer.cpp:4239
bool snapNearestPoint(double mapX, double mapY, double mapRadius, QPointF &outPt, std::optional< QPointF > excludePos=std::nullopt) const
Nearest-neighbor snap query for vertex editing.
Definition swmmmodellayer.cpp:8795
bool showSubcatchments
Definition swmmmodellayer.h:205
QStringList selectedElementNames() const
Returns the names of currently selected network elements.
Definition swmmmodellayer.cpp:3560
quint64 editRevision() const
Definition swmmmodellayer.h:768
void markEdited()
Records that the engine now holds edits not yet on disk.
Definition swmmmodellayer.h:2186
int renderLinkCount() const
Number of links the render-facing scene-coordinate arrays currently describe.
Definition swmmmodellayer.h:1286
static constexpr quint8 kKindGage
Definition swmmmodellayer.h:977
static constexpr Category CatOutlets
Definition swmmmodellayer.h:164
bool showLabels
Definition swmmmodellayer.h:209
SWMMElementSymbol orificeSymbol() const
Definition swmmmodellayer.cpp:2529
static constexpr Category NumCategories
Definition swmmmodellayer.h:167
bool transformLayerToCanvas(double lx, double ly, double &cx, double &cy) const
Forward-transform a layer-CRS coordinate into the canvas CRS.
Definition swmmmodellayer.cpp:9113
double linkArrowWidth(Category c) const
Definition swmmmodellayer.cpp:2790
bool isObjectVisible(const QString &name) const
Per-object visibility flag. Names present in m_hiddenObjects are skipped by populateScene....
Definition swmmmodellayer.cpp:1439
void depopulateScene(QGraphicsScene *scene) override
Removes all QGraphicsItems belonging to this layer from the scene.
Definition swmmmodellayer.cpp:4122
int cachedSubcatchCount() const
Number of subcatchments cached. Equivalent to categoryCount(CatSubcatchments) but provided alongside ...
Definition swmmmodellayer.cpp:4310
QVector< QPointF > cachedSubcatchVertices(int idx) const
Cached layer-CRS polygon of a subcatchment by index. Vertex order matches the .inp [Polygons] section...
Definition swmmmodellayer.cpp:4303
QStringList tableIdsOfType(int tableType) const
List the engine's table ids whose type matches tableType (Slice DA.4.3).
Definition swmmmodellayer.cpp:1954
SWMMElementSymbol storageSymbol() const
Definition swmmmodellayer.cpp:2522
QObject * ensureAquiferRegistry()
Lazy accessor for the project-scoped AquiferRegistry.
Definition swmmmodellayer.cpp:7127
static constexpr quint8 kKindLink
Definition swmmmodellayer.h:975
bool applyControlRuleRemove(const QString &name, QString *outError=nullptr)
Drop the rule with name from the engine + registry. Returns false if not found.
Definition swmmmodellayer.cpp:6962
static constexpr Category CatPumps
Definition swmmmodellayer.h:161
int cachedGageCount() const
Definition swmmmodellayer.cpp:4317
static constexpr quint8 kKindAll
Definition swmmmodellayer.h:978
bool applyControlRuleAdd(const QString &name, const QString &body, QString *outError=nullptr)
Append a new control rule. body should already include the RULE <name> header (matching the engine's ...
Definition swmmmodellayer.cpp:6833
void setConduitSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2569
bool linkArrowsEnabled(Category c) const
Definition swmmmodellayer.cpp:2730
bool kindUsesOverrides(Category c) const
Definition swmmmodellayer.cpp:3258
QVector< int > linksAttachedToNode(int nodeIdx) const
Indices of links whose from/to endpoint is the given node.
Definition swmmmodellayer.cpp:4586
void setStorageSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2559
bool rollbackTailGageAdd(const QString &name)
Definition swmmmodellayer.cpp:5906
QsgKinds qsgRenderKinds() const noexcept
Definition swmmmodellayer.h:381
HydrographDecayTableModel * hydrographDecayModel()
Definition swmmmodellayer.cpp:6570
QColor colorForClass(const QString &classKey) const
Definition swmmmodellayer.cpp:2978
void beginBulkEdit()
Definition swmmmodellayer.cpp:6091
MapCanvas * editCanvas() const
Definition swmmmodellayer.cpp:5542
QColor linkArrowColor(Category c) const
Definition swmmmodellayer.cpp:2819
bool applyHydrographSetIa(const QString &name, int month, int response, double dmax, double drecov, double dinit)
Definition swmmmodellayer.cpp:6490
QVector< OpenSWMM::Render::AttributeField > availableAttributes(OpenSWMMVis::SwmmCategory cat) const override
Definition swmmmodellayer.cpp:3102
bool applyRemoveInletUsage(int hostKind, int hostIdx, QString *outError=nullptr)
Remove the usage row hosted by (hostKind, hostIdx). A missing row is a successful no-op.
Definition swmmmodellayer.cpp:5391
std::vector< std::unique_ptr< openswmmvis::ui::ILayerStyleSubject > > styleSubjects() override
Definition swmmmodellayer.cpp:2653
HydrographGroupListModel * hydrographGroupListModel()
Definition swmmmodellayer.cpp:6552
void selectionChanged(const QStringList &selectedNames)
void setQsgRenderKinds(QsgKinds kinds)
Definition swmmmodellayer.cpp:1415
void setLinkArrowWidth(Category c, double pixels)
Definition swmmmodellayer.cpp:2802
void setSizeForClass(const QString &classKey, qreal size)
Definition swmmmodellayer.cpp:3010
bool previewNodeMove(int idx, double newX, double newY)
Definition swmmmodellayer.cpp:4437
bool nodeIsVirtual(int soaIdx) const
True when cached node soaIdx is a virtual junction.
Definition swmmmodellayer.h:1591
void dataObjectsChanged()
bool applyFuseJunctionSplit(const QString &nodeName, QString *outError=nullptr)
Inverse of applyInsertJunctionSplit — re-fuses the conduit pair and deletes the junction.
Definition swmmmodellayer.cpp:5252
bool applyFuseVirtualJunction(const QString &nodeName, QString *outError=nullptr)
Re-fuse the two conduits of virtual junction nodeName into one via swmm_virtual_junction_fuse (upstre...
Definition swmmmodellayer.cpp:5175
QStringList nodesInRect(double canvasMinX, double canvasMinY, double canvasMaxX, double canvasMaxY) const
Names of all nodes (any type) whose layer-CRS coordinates fall inside the rectangle given in canvas C...
Definition swmmmodellayer.cpp:8723
QString sourceDescription() const override
Human-readable source of this layer: a file path, a service URL, or a description for in-memory / der...
Definition swmmmodellayer.cpp:661
void attributeChanged(const QString &objectName)
void setShowSubcatchments(bool show)
Definition swmmmodellayer.cpp:1394
const QVector< SelectedElement > & selectedElements() const
Typed selection — canonical form. Each entry names WHICH kind is selected, so same-named objects of o...
Definition swmmmodellayer.h:1011
SWMMElementSymbol junctionSymbol() const
Definition swmmmodellayer.cpp:2520
void setWeirSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2572
QVector< int > objectOrder(Category cat) const
Definition swmmmodellayer.cpp:2192
SWMMElementSymbol weirSymbol() const
Definition swmmmodellayer.cpp:2530
bool bulkEditActive() const
Definition swmmmodellayer.h:1927
bool applyNodeConvert(const QString &name, int newNodeType, QStringList *outCleared=nullptr, QStringList *outWarnings=nullptr, QString *outError=nullptr)
Convert node name to newNodeType (SWMM_NodeType value) via swmm_node_convert. The engine preserves co...
Definition swmmmodellayer.cpp:4843
QStringList gagesInRect(double canvasMinX, double canvasMinY, double canvasMaxX, double canvasMaxY) const
Names of all rain gages whose coordinates fall inside the canvas-CRS rectangle. Same semantics as nod...
Definition swmmmodellayer.cpp:8760
bool applyLinkAdd(const QString &name, int linkType, const QString &fromNodeName, const QString &toNodeName, const QVector< QPointF > &interiorVertices, int *outIdx=nullptr)
Add a new link: engine + cache.
Definition swmmmodellayer.cpp:5742
bool nodeIsInlet(int soaIdx) const
True when cached node soaIdx is an inlet junction. An inlet junction is also a virtual junction,...
Definition swmmmodellayer.h:1672
static constexpr Category CatSubcatchments
Definition swmmmodellayer.h:165
bool applyHydrographSetRtk(const QString &name, int month, int response, double r, double t, double k)
Definition swmmmodellayer.cpp:6477
void setRainGageSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2575
OpenSWMM::Render::IFeatureRenderer * renderer() const override
The IFeatureRenderer for this layer.
Definition swmmmodellayer.cpp:2694
void setLinkArrowOnlyWhenFlowPos(Category c, bool onlyPos)
Definition swmmmodellayer.cpp:2861
bool findObjectLocation(const QString &name, Category *cat, int *row) const
Locate an object by name, returning true and writing cat + row on success. O(1) hash lookup against t...
Definition swmmmodellayer.cpp:2378
bool pushInletUsageEdit(const SWMM_InletUsage &usage)
Apply one inlet-usage row as a single undoable step. Pushes a SetInletUsageCommand on the edit canvas...
Definition swmmmodellayer.cpp:5544
int cachedNodeCount() const
Cached top-level object counts (all node/link kinds summed). Convenience for load-summary logging.
Definition swmmmodellayer.cpp:4315
int objectTypeFor(const QString &name) const
Classify a name into its SWMM object class via O(1) lookup against m_objectLocation.
Definition swmmmodellayer.cpp:4195
bool cachedGageCoord(int idx, double *x, double *y) const
A rain gage's coordinate AS THE ENGINE STORES IT.
Definition swmmmodellayer.cpp:4319
bool applyHydrographAddGroup(const QString &name, const QString &gageName, int initialResponse)
Definition swmmmodellayer.cpp:6382
int setOptions(const QMap< QByteArray, QString > &values)
Batch write — applies a set of key/value pairs, then emits optionsChanged(changedKeys) once....
Definition swmmmodellayer.cpp:4563
QVector< int > defaultObjectOrder(Category cat) const
Definition swmmmodellayer.cpp:2197
static constexpr Category CatRainGages
Definition swmmmodellayer.h:166
double linkArrowSize(Category c) const
Definition swmmmodellayer.cpp:2761
static QString kindKey(Category c)
Definition swmmmodellayer.cpp:2890
quint64 geomRevision() const
Definition swmmmodellayer.h:1345
void modelEdited()
QString dataObjectNameAt(DataCategory c, int row) const
Slice BM.0 — name of a non-spatial data object at (category, row), or an empty string when out of ran...
Definition swmmmodellayer.cpp:1811
bool applyInsertJunctionSplit(const QString &linkName, double t, const QString &newNodeName, const QString &newLinkName, int *outNodeIdx=nullptr, int *outLinkIdx=nullptr, QString *outError=nullptr)
Split conduit linkName at t inserting a PLAIN junction, via swmm_conduit_split with make_virtual = 0....
Definition swmmmodellayer.cpp:5211
void setSelectedElementNames(const QStringList &names)
Selects network elements by name (replaces prior selection). Legacy name-only form: each name selects...
Definition swmmmodellayer.cpp:3600
void setEditCanvas(MapCanvas *canvas)
Bind the canvas whose undo stack mediated edits push onto.
Definition swmmmodellayer.cpp:5541
QStringList subcatchmentsInRect(double canvasMinX, double canvasMinY, double canvasMaxX, double canvasMaxY) const
Names of all subcatchments whose polygon bbox overlaps the canvas-CRS rectangle. Same caching pattern...
Definition swmmmodellayer.cpp:8903
bool applyLinkXsect(int linkIdx, int shape, double g1, double g2, double g3, double g4)
Slice SC.1 — Write a cross-section to a link via swmm_link_set_xsect. Emits attributeChanged(linkName...
Definition swmmmodellayer.cpp:4787
bool applyRename(const QString &oldName, const QString &newName, quint8 kindHint=kKindAll)
Rename any network element (node, link, subcatchment, or gage).
Definition swmmmodellayer.cpp:5997
void invalidateDataObjectCache()
Definition swmmmodellayer.h:2814
bool applyHydrographRenameGroup(const QString &oldName, const QString &newName)
Definition swmmmodellayer.cpp:6421
void setRenderer(std::unique_ptr< OpenSWMM::Render::IFeatureRenderer > r) override
Replaces the current renderer.
Definition swmmmodellayer.cpp:2699
int cachedLinkCount() const
Definition swmmmodellayer.cpp:4316
bool applyGageAdd(const QString &name, double x, double y, int *outIdx=nullptr)
Definition swmmmodellayer.cpp:5869
OpenSWMM::Render::RuleList * ruleList() override
Definition swmmmodellayer.cpp:3074
bool applySetInletUsage(const SWMM_InletUsage &usage, QString *outError=nullptr)
Create or replace the usage row for usage's host via swmm_inlet_usage_set. Emits attributeChanged for...
Definition swmmmodellayer.cpp:5360
static constexpr Category CatConduits
Definition swmmmodellayer.h:160
QVariantMap identifyAt(double mapX, double mapY, const SpatialReferenceSystem *canvasSRS, double tolerance=1e-6) const
Returns attributes of the network element closest to the map point.
Definition swmmmodellayer.cpp:3868
QStringList linksInPolygon(const QPolygonF &canvasPoly) const
Definition swmmmodellayer.cpp:8987
bool applyHydrographRemoveGroup(const QString &name)
Definition swmmmodellayer.cpp:6408
void showNodesChanged(bool show)
SWMMElementSymbol subcatchmentSymbol() const
Definition swmmmodellayer.cpp:2532
QString suggestUniqueDataObjectName(DataCategory c) const
Slice DA.3 — suggest a unique default name for the next new data object of c. Scans existing names an...
Definition swmmmodellayer.cpp:1911
HydrographIaTableModel * hydrographIaModel()
Definition swmmmodellayer.cpp:6564
bool applySubcatchSetGage(int idx, const QString &gageName)
Assign a rain gage to a subcatchment: engine + change notification.
Definition swmmmodellayer.cpp:6446
QObject * ensureLandUseRegistry()
Lazy accessor for the project-scoped LandUseRegistry.
Definition swmmmodellayer.cpp:7099
void setCategoryOpacity(Category c, qreal opacity)
Definition swmmmodellayer.cpp:2367
void showSubcatchmentsChanged(bool show)
QObject * ensureLidControlRegistry()
Lazy accessor for the project-scoped LidControlRegistry.
Definition swmmmodellayer.cpp:7211
void setJunctionSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2557
void setShowNodes(bool show)
Definition swmmmodellayer.cpp:1386
void setShowLinks(bool show)
Definition swmmmodellayer.cpp:1390
bool applySubcatchVertices(int idx, const QVector< QPointF > &vertices)
Replace a subcatchment's polygon vertices: engine + cache. Recomputes the centroid as the vertex aver...
Definition swmmmodellayer.cpp:7490
bool renderLinkHidden(int idx) const
The hidden flag the renderers read for link idx — what actually decides whether the base link pass em...
Definition swmmmodellayer.h:1297
QVector< QPointF > cachedLinkPolyline(int idx) const
Cached layer-CRS polyline of a link by index, including the endpoint coordinates of its from/to nodes...
Definition swmmmodellayer.cpp:4279
void hydrographChanged(const QString &uhName)
bool createDataObject(DataCategory c, const QString &name, const QVariantMap &options, QString *outError=nullptr)
Create a new data object on the engine (DB.4b).
Definition swmmmodellayer.cpp:2011
SWMMElementSymbol rainGageSymbol() const
Definition swmmmodellayer.cpp:2533
void setDividerSymbol(const SWMMElementSymbol &s)
Definition swmmmodellayer.cpp:2560
double featureOffset(Category c, int idx) const
Definition swmmmodellayer.cpp:3288
const QVector< InletConnector > & inletConnectors() const
The connector overlay geometry, rebuilt on demand when the usage rows or the geometry changed....
Definition swmmmodellayer.cpp:5569
QVector< QPair< QString, QString > > extendedMetadata() const override
Ordered key→value pairs of TYPE-SPECIFIC metadata, rendered by the Metadata tab below the common bloc...
Definition swmmmodellayer.cpp:667
Qt::CheckState categoryCheckState(Category c) const
Aggregate check state for a category: Checked when every member is visible, Unchecked when every memb...
Definition swmmmodellayer.cpp:2258
QObject * ensureSnowpackRegistry()
Lazy accessor for the project-scoped SnowpackRegistry.
Definition swmmmodellayer.cpp:7155
bool applyRdiiDecayRemove(const QString &name, int response)
Definition swmmmodellayer.cpp:6540
SWMMElementSymbol outletSymbol() const
Definition swmmmodellayer.cpp:2531
bool rollbackTailNodeAdd(const QString &name)
Undo an add by removing the tail entry of the node cache.
Definition swmmmodellayer.cpp:5712
void transectChanged(const QString &transectName)
Represents a coordinate reference system backed by a GDAL OGRSpatialReference.
Definition spatialreferencesystem.h:28
Definition swmmelementsymboladapter.h:30
Definition userflagsmodel.h:32
DiagramType t
Definition diagramspec.cpp:20
int code
Definition heatconfigdialog.cpp:40
Layer-side seam for "what attributes can I theme by?" — Slice DM.1.
QString nodeName
Definition importplanning.cpp:95
double s
Scene px per model length unit.
Definition inletdrawingview.cpp:82
QGraphicsScene * scene
Definition inletdrawingview.cpp:78
int e
Definition inpmeshreader.cpp:41
Shared label-configuration value-type used by every layer that paints text labels.
One row in a layer's legend — label + swatch symbol + optional range.
MarkerShape shape
Definition markershape.cpp:27
Canonical 19-shape enum used by Marker Symbol Layers (Slice Z.4; extended set appended later).
std::vector< double > cx
Definition mesh2dresultsexport.cpp:103
std::vector< double > cy
area centroid per cell
Definition mesh2dresultsexport.cpp:103
std::vector< mesh::MeshTriangle > cells
Definition mesh2dresultsexport.cpp:102
int k
Definition mesh2dresultsexport.cpp:549
const char * key
Definition meshcellparams.cpp:24
double length
Definition meshpatch.cpp:64
Definition gisrasterlayer.h:40
ClassEditKind
Categories of per-class mutation that a renderer may support.
Definition ifeaturerenderer.h:64
MarkerShape
13 canonical marker shapes the Rule Model's Marker Symbol Layer supports (per RENDERING_RULE_MODEL_PL...
Definition markershape.h:53
Definition gwsourcesummary.h:21
SwmmCategory
Stable ordinal categorising every SWMM-element kind that has per-kind styling, per-kind tree rows,...
Definition swmm_category.h:28
Definition openswmmvislayer.h:43
void * SWMM_Engine
Definition objectdefaultsapplier.h:19
Abstract base class for all map layers displayed in the MapCanvas.
int path
Definition pslgminsize.cpp:234
QVector< int > parent
union-find
Definition pslgminsize.cpp:176
TokenKind kind
Definition queryparser.cpp:34
QString name
Definition sectionmodelbuilders.cpp:474
Per-layer label rendering parameters.
Definition labelconfig.h:47
Definition preferencesmanager.h:424
Definition preferencesmanager.h:504
Rendering style for a class of SWMM network elements.
Definition swmmmodellayer.h:77
QColor outlineColor
Definition swmmmodellayer.h:79
QColor fillColor
Definition swmmmodellayer.h:78
double size
Definition swmmmodellayer.h:81
double arrowSize
Definition swmmmodellayer.h:101
bool showArrows
Definition swmmmodellayer.h:100
QFont labelFont
Definition swmmmodellayer.h:88
QColor labelColor
Definition swmmmodellayer.h:89
bool arrowOnlyWhenFlowPos
Definition swmmmodellayer.h:115
bool showLabel
Definition swmmmodellayer.h:87
OpenSWMM::Render::MarkerShape markerShape
Definition swmmmodellayer.h:83
QColor arrowColor
Definition swmmmodellayer.h:109
double arrowWidth
Definition swmmmodellayer.h:108
double outlineWidth
Definition swmmmodellayer.h:80
Definition swmmmodellayer.cpp:236
Definition swmmmodellayer.h:1728
QPointF capture
capture (underdrain) node position
Definition swmmmodellayer.h:1730
QPointF host
conduit midpoint (link host) or node position
Definition swmmmodellayer.h:1729
Everything a blank untitled project needs — the in-memory replacement for the synthetic temp ....
Definition swmmmodellayer.h:296
QString name
"[TITLE]" + display name ("Untitled").
Definition swmmmodellayer.h:297
PreferencesManager::TwoDDefaults twoD
Used iff forNewEngine && sim.module2DEnabled.
Definition swmmmodellayer.h:302
QDateTime endDateTime
Definition swmmmodellayer.h:299
QDateTime startDateTime
Definition swmmmodellayer.h:298
bool forNewEngine
Gate NODE_CONTINUITY / ANDERSON_ACCEL / 2D.
Definition swmmmodellayer.h:300
PreferencesManager::SimulationDefaults sim
THREADS already maxed by caller.
Definition swmmmodellayer.h:301
Tool-facing click-pick result. valid is false when no feature was hit within tolerance of the canvas-...
Definition swmmmodellayer.h:1421
Category cat
Definition swmmmodellayer.h:1423
QString name
Definition swmmmodellayer.h:1425
int soaIndex
Definition swmmmodellayer.h:1424
bool valid
Definition swmmmodellayer.h:1422
One selected element: its name plus a bitmask of the kinds (kKind*) the selection applies to....
Definition swmmmodellayer.h:994
bool operator==(const SelectedElement &o) const
Definition swmmmodellayer.h:997
quint8 kinds
Definition swmmmodellayer.h:996
QString name
Definition swmmmodellayer.h:995
Standalone definition of the SWMM-element Category enum used by per-Category APIs across layers,...