Sunday, December 29, 2024

SWMM5 Delphi GUI Udxf.pas Summary

 Expanded Summary of Udxf.pas

This Delphi Pascal unit Udxf.pas is responsible for exporting the SWMM study area map to a DXF (Drawing Exchange Format) file. It uses various drawing primitives (lines, circles, polylines, text, etc.) to represent nodes, links, subcatchments, and labels from an EPA SWMM model in a DXF file that can be opened in a CAD application.


1. Purpose & Usage

  • Main Entry Point:

    procedure DXFexport(const fname: String; const Jstyle: Integer);
    

    This is the procedure that the rest of the SWMM code calls to export all visual elements of the model (e.g., subcatchments, nodes, links, labels) into a DXF file named fname. The parameter Jstyle indicates how junction nodes will be drawn (e.g., as circles, crosses, squares, etc.).

  • DXF Format:
    The code writes plain-text lines in the correct order and structure to a .dxf file. The content is broken up into:

    1. Header (map extents).
    2. Tables (line types, layers, etc.).
    3. Entities (actual geometry).

2. DXF Data Structures & Outline

  1. Header

    • The procedure AddHeader(...) writes out $EXTMIN and $EXTMAX to define the bounding box extents in the DXF file.
  2. Layer Table

    • StartTables(Nlayers) writes the starting lines of the DXF TABLES section with N layers.
    • AddLayer(LayerName, ColorIndex) is called for each separate layer (e.g., “Subcatchments,” “Links,” “Nodes,” “Arrows,” “Labels”).
    • EndTables closes the layer table and begins the SECTION ENTITIES block.
  3. Entities

    • Various geometry elements are added:
      • Circle (for nodes, if style is set to circles).
      • Polyline (for subcatchment polygons, link polylines).
      • Line or Solid (for arrowheads or node shapes).
      • Text (for labels).
  4. Ending the File

    • EndDXF writes the ENDSEC and EOF lines required at the end of the DXF.

3. Key Procedures

3.1. DXFexport(const fname: String; const Jstyle: Integer)

  • Input:

    1. fname: name of the resulting DXF file on disk.
    2. Jstyle: node-drawing style (e.g., circle, cross, etc.).
  • Actions:

    1. Open a text file for writing (DXFfile).
    2. Retrieve information from SWMM:
      • The “Map” instance (with subcatchments, nodes, etc.).
      • Various map styling options (line sizes, arrow sizes, etc.).
    3. Compute or look up color indexes for subcatchments, links, and nodes. (DXF color is integer-based, so the code finds the “closest” integer color index from a set.)
    4. Write the DXF “header” with bounding box extents.
    5. Create table data: layers for subcatchments, links, nodes, arrows, labels.
    6. Iterate over each object in the SWMM model:
      • Subcatchments: add them as polylines.
      • Links: add polylines plus optional arrowheads.
      • Nodes: add circles or squares or crosses, depending on Jstyle.
      • Labels: add text items.
    7. Finish by writing end-of-file markers.

3.2. AddHeader(xmin, ymin, xmax, ymax: Single)

  • Writes out the minimal bounding rectangle that the CAD program can use for $EXTMIN and $EXTMAX in the DXF file.

3.3. AddLayer(layer: String; color: Integer)

  • Within the “layer table,” create a new layer with the given color index.

3.4. AddCircle(x, y, radius, color, layer)

  • Writes the DXF statements for a circle entity at (x, y) with radius, assigned to some color and layer.

3.5. AddSubcatchPolyLine(aSubcatch, thickness, bulge, color, layer)

  • Polylines the subcatchment’s polygon boundary. The code writes a “POLYLINE ... VERTEX ... SEQEND” block. The subcatchment’s polygon is accessed from aSubcatch.Vlist.

3.6. AddLinkPolyLine(aLink, thickness, bulge, color, layer)

  • Similar to AddSubcatchPolyLine but for a link’s polyline (via aLink.Vlist plus the from/to node coords).

3.7. AddArrow(...)

  • Renders the arrowhead for a link, by writing two line segments forming a “V” shape. The geometry is computed from start/end angles and arrow size.

3.8. AddText(x, y, ht, rot, txt, layer)

  • Writes a text entity. Used for map labels.

4. Data & Variables

  1. Global/Module-level:

    • DXFfile: a TextFile handle for writing the DXF lines.
    • JuncStyle: integer controlling how junctions are drawn (0=circles, 1=cross, 2=filled squares).
    • SubcatchSize, LinkSize, NodeSize, LabelSize, ArrowSize: floating “scaling factors” from SWMM’s map to DXF.
    • PixPerMapExt: ratio to convert from map coordinates to screen or other dimension units, used for scaling.
    • DXFLinkColor, DXFNodeColor, DXFSubcatchColor: arrays for color indexes for different objects, matching SWMM’s color legend intervals.
  2. Units: The code transforms local map units (from the SWMM map display) into raw DXF coordinates, effectively in the same coordinate system but scaled to represent line thickness, arrow sizes, etc.


5. Flow of DXFexport

Below is a step-by-step outline of what DXFexport(...) does:

  1. Open the output file at fname.
  2. Initialize local variables with dimension and style settings from the SWMM map object.
  3. Write:
    • AddHeader(...) with bounding box.
    • StartTables(...), AddLayer(...) calls, and EndTables.
  4. Loop over subcatchments if they are shown; calls AddSubcatch(...) for each.
  5. Loop over each link type (I in [CONDUIT, PUMP, ...]), calls AddLink(...).
  6. Loop over each node type (I in [JUNCTION, OUTFALL, ...]), calls AddNode(...).
  7. AddLabels if they are shown.
  8. Close the DXF with EndDXF.
  9. Close the file handle.

That’s how the entire map is rendered into lines, polylines, circles, etc.


6. Practical Notes

  • Colors: The code looks up the SWMM color (RGB) in DXFColors = (clRed, clYellow, ...), matching it to the “closest” index. This might be a limited approach but is standard for older DXF color indexes.
  • Arrows: Only drawn if MapOptions.ArrowStyle is not asNone. The code calculates arrow geometry with SinCos(arctan2(...)) calls.
  • Units: The SWMM coordinates are used directly, no special unit conversion is done. The user’s SWMM map coordinates are in some length unit that the DXF will interpret.
  • File: The resulting .dxf is “AutoCAD Release 12 style” or older ASCII format, which is widely recognized.

7. Conclusion

Udxf.pas provides a straightforward, if somewhat “low-level,” approach to generating a standard ASCII DXF file from an EPA SWMM map. It enumerates each item of interest (subcatchments, nodes, links, labels), converts them to the necessary DXF geometry calls (POLYLINE, CIRCLE, SOLID, TEXT), and organizes them into layers. This allows the SWMM map layout to be examined or edited in any CAD application supporting DXF.

SWMM5 Delphi GUI Ucoords.pas Summary

 Extended and Expanded Summary of Ucoords.pas

This Delphi unit, Ucoords.pas, is part of the EPA SWMM project. It provides functionality to:

  1. Compute the bounding (min/max) coordinates of all geometry in the model.
  2. Transform (i.e., rescale and shift) all map object coordinates from one bounding rectangle to another.

1. Overview of Key Procedures

There are two main procedures in this unit:

  1. GetCoordExtents(var X1, Y1, X2, Y2: Extended)
    Determines the minimal bounding rectangle that encloses all map objects in the project. The bounding rectangle is described by the coordinates (X1,Y1)(X_1, Y_1) (bottom-left corner) and (X2,Y2)(X_2, Y_2) (top-right corner).

  2. TransformCoords(LL1, UR1, LL2, UR2: TExtendedPoint)
    Applies a linear coordinate transform to all map objects. The transform is from an old bounding rectangle (LL1,UR1)(LL1, UR1) to a new bounding rectangle (LL2,UR2)(LL2, UR2).

Data Types & Structures

  • Extended: A floating-point type used for coordinates.
  • TExtendedPoint: A record containing X and Y fields of type Extended.
  • Project: A global data structure containing lists of objects for all object categories (e.g., subcatchments, nodes, links, labels, etc.).
  • PVertex: A pointer to a linked list node used to store polygon or polyline coordinates of subcatchments and links.

2. The GetCoordExtents Procedure

procedure GetCoordExtents(var X1: Extended; var Y1: Extended;
                          var X2: Extended; var Y2: Extended);

Purpose:
Finds the minimum and maximum X and Y coordinates over all relevant objects in the SWMM project.

Key Steps:

  1. Initialize bounding values

    • X1 := -MISSING; X2 := MISSING;
    • Y1 := -MISSING; Y2 := MISSING;

    Note that MISSING is a special constant used to designate "no coordinate". -MISSING is effectively negative infinity, and MISSING is positive infinity for the logic.

  2. Loop Over Object Categories (I from 0 to MAXCLASS)

    • For each category, the procedure checks if it is a "visual" object type that stores coordinates (e.g., subcatchments, nodes, rain gages, etc.).
    • If so, gather X and Y values into the bounding extents.

    Specifically:

    • Rain gages (I = RAINGAGE): Each gage has a single (X, Y) location.
    • Nodes (Project.IsNode(I)): Each node also has a single (X, Y).
    • Subcatchments (Project.IsSubcatch(I)): Each subcatch can have a polygon of vertices. The code loops through these vertex lists to find min and max X, Y.
  3. Expand Extents Slightly
    If final bounding box is degenerate in X or Y (same min and max), it adjusts it by some small fraction so that the bounding area is non-zero. Specifically, it expands the bounding box by 5% of the range in each dimension.

  4. Returning:

    • On exit, X1, Y1 will be the minimum coordinate in each dimension.
    • X2, Y2 will be the maximum coordinate in each dimension.

In summary, you get a bounding rectangle that encloses all geometry with a small margin added.


3. The TransformCoords Procedure

procedure TransformCoords(LL1, UR1, LL2, UR2: TExtendedPoint);

Purpose:
Transforms all map coordinates from bounding box (LL1, UR1) to box (LL2, UR2).

Where:

  • LL1, UR1 = old lower-left & upper-right corners
  • LL2, UR2 = new lower-left & upper-right corners

Key Steps:

  1. Compute the Scale Factors

    • Xscale := (UR2.X - LL2.X) / (UR1.X - LL1.X)
    • Yscale := (UR2.Y - LL2.Y) / (UR1.Y - LL1.Y)

    This effectively means that any coordinate X in [LL1.X, UR1.X] is mapped into [LL2.X, UR2.X] linearly.

  2. Define Local Transform Helper Functions

    • Xtransform(X: Extended): Extended
    • Ytransform(Y: Extended): Extended

    If X or Y is MISSING, it remains MISSING; otherwise it’s a direct linear scaling from the old domain to the new domain.

  3. Loop Over All SWMM Objects

    • Rain gage => transform (X, Y)
    • Subcatchment => transform (X, Y) centroid and each vertex in its polygon.
    • Node => transform (X, Y) for each node.
    • Link => transform each vertex in the link’s polyline Vlist.
    • Map label => transform (X, Y) location.

All geometry is thus re-scaled and shifted so that the old bounding box is effectively mapped onto the new bounding box.


4. Implementation Details

  1. Global Variables:
    • Xscale, Yscale: Computed once in TransformCoords to store the scale factors.
  2. Local Helper:
    • AdjustExtents inside GetCoordExtents is used to handle degenerate bounding boxes by expanding them a bit.
  3. Project:
    The Project has lists of different object types—some are in memory as TNode, TLink, TSubcatch, TRainGage, TMapLabel, etc.
  4. MISSING:
    A sentinel constant used to represent nonexistent or undefined coordinates.
  5. Map:
    • Rain gages store a single (X, Y) coordinate.
    • Subcatchments store a centroid plus a polygon (Vlist).
    • Nodes store a single (X, Y).
    • Links store a set of polyline vertices.
    • Labels store a single (X, Y).

5. Error Handling & Edge Cases

  • GetCoordExtents checks whether all coordinates might remain at default values (X1 = -MISSING or X2 = MISSING) if no geometry is present.
  • If X1 = X2 or Y1 = Y2 after reading geometry, they get expanded by 5% or by ±5 units if the bounding coordinate is 0.
  • TransformCoords does nothing if old bounding box (UR1.X - LL1.X) or (UR1.Y - LL1.Y) is zero (to avoid division by zero).

6. Summary

In short, the unit Ucoords.pas provides two main functionalities for managing geometry in an EPA SWMM project:

  1. GetCoordExtents collects the min and max X,Y coordinates from all map objects (rain gages, subcatchments, nodes, links, map labels), returning a bounding rectangle that encloses all geometry.

  2. TransformCoords linearly rescales every coordinate from an old bounding rectangle to a new one. This is especially useful when you want to reposition or re-scale the entire model map (e.g., after reading a background image or changing projection units).

These routines are typically called by the main user interface or other geometry-handling routines whenever a bounding view is required or map coordinates need re-scaling.

SWMM5 Delphi GUI Ucombine.pas Summary

 Extended and Expanded Summary of Ucombine.pas

This Delphi unit, Ucombine.pas, contains a single public function, CombineFiles, which merges two SWMM interface files into a third file. In SWMM, these interface files (often called routing interface or intermediate data files) store flow and water quality data at specific time steps for multiple locations. The combined file merges data from two such interface files into one, effectively combining hydrographs and pollutographs in terms of flow and mass.


1. Purpose and Context

  • Interface Files are text-based data files produced by or read by SWMM at the boundary between different model components (e.g., used when splitting a large model into two stages or combining separate upstream routing results).
  • This unit aims to read two interface files (F1 and F2) and produce a single combined interface file (F3) where flow and mass-based water quality parameters from F1 and F2 are added at each location and time.
    • For flow variables, the new file's flow is the sum of flows from the two input files.
    • For water quality variables, the new file's pollutant concentration is derived by combining mass flow (flow * concentration) from each file and then dividing by the resulting flow to get a new concentration.

The procedure ensures that all dates, times, node names, and parameter names from both input files are consolidated properly.


2. Key Data Structures

  1. F: An array of TextFile, containing:

    • F[1]: The first input file.
    • F[2]: The second input file.
    • F[3]: The temporary output file (which eventually becomes F3).
  2. Nparams[i], Nnodes[i]: The number of parameters and the number of nodes found in file i.

  3. Tstep[i]: The time step (in seconds) for file i.

  4. Params[i], ParamUnits[i]: TStringList that store the parameter names and units for file i.

  5. Nodes[i]: TStringList holding all node (location) names for file i.

  6. ParamIndex2[]: An integer array mapping each parameter in file 2 to its position (index) in the merged set of parameters.

  7. NodeIndex2[]: Similar mapping for node names from file 2 to the merged node list.

  8. Time-based arrays:

    • V1 (primary file’s data at the current time).
    • V2, V2before, V2after (secondary file’s data, for interpolation).
    • V3 (the merged data to write to the new file).
  9. Dates:

    • BeforeDate[1..2] / AfterDate[1..2]: The times from the primary or secondary file that bracket the current date used in combining.
    • CurrentDate: The date/time for which the code merges data from both files.
    • Ndates: The number of time records ultimately written to the new file.

3. CombineFiles Function Logic

function CombineFiles(const F1, F2, F3, Title: String): Boolean;

Takes four arguments:

  • F1: Name of interface file #1.
  • F2: Name of interface file #2.
  • F3: Name of the resulting combined file.
  • Title: A string stored in the combined file’s header.

Returns True if combining is successful, otherwise False.

Steps in the Combining Process

  1. File Name Checks:

    • Ensures F1 and F2 exist and are distinct from each other and from F3.
  2. Open Files:

    • Opens F1 and F2 for reading (Reset)
    • Opens a temporary file for combined output, because if an error occurs, we discard it.
  3. Parse Header:

    • Each interface file has a specified header with:
      1. A line containing 'SWMM5'
      2. A project-specific title line
      3. A time step integer
      4. A count of parameters + each parameter’s name/units
      5. A count of nodes + each node’s name
    • The code checks each file for correct formatting and extracts these elements into arrays/lists:
      • Nparams[], Params[], ParamUnits[], Nnodes[], Nodes[]
    • If not properly formatted, raises an error.
  4. Merge Parameter & Node Lists:

    • Some parameters might be present in both files. For instance, each file must have "FLOW" as its first parameter.
    • If a parameter is new to the second file, it is appended to the combined parameter list.
    • The code also merges the node (location) lists from both files, so the result includes every node from both input files.
    • The arrays ParamIndex2[] and NodeIndex2[] record the mapping from file #2’s param/node to the merged list.
  5. Allocate Data Arrays:

    • The code sets up the V1, V2, V2before, V2after, and V3 arrays with row dimension = number of nodes, column dimension = number of parameters.
    • The “primary file” is the one with the smaller time step.
  6. Write Combined File Header:

    • SWMM5 Interface File
    • The Title argument
    • The time step for the combined file (the smaller of the two input file steps)
    • The total count of parameters, their names & units
    • The total count of merged nodes, plus their names
    • A final heading line for data columns
  7. Initial Data Reading:

    • The routine loads the first data record from each file (the code calls ReadValues) which extracts date/time and an array of parameter values for each node.
  8. Iterative Combine:

    • The function keeps a CurrentDate that increments in steps of the primary file’s time step.
    • For each iteration:
      • (a) If the secondary file times haven’t yet started for the CurrentDate, the code uses repeated increments, or if it’s started but not caught up, the code reads from the secondary file.
      • (b) Interpolation might be used if the primary file’s CurrentDate is between two date/times in the secondary file.
        • V2before and V2after bracket the times around CurrentDate.
        • The code linearly interpolates the parameter values into V2.
      • (c) Summation is done by “flow” plus “mass.” The code:
        1. Clears V3.
        2. Merges the primary flow V1 + secondary flow V2.
        3. Merges pollutant loads (mass flow = flow * concentration).
        4. Then “convert” to concentration by dividing total mass by total flow.
      • (d) Writes out a line to the combined file for each node.
    • The loop continues until both input files are exhausted.
  9. Cleanup:

    • Closes all files.
    • If no errors, renames the temporary output to user’s requested name F3.
    • If errors, notifies the user and returns False.

4. Interpolation Explanation

When the primary file’s CurrentDate is between BeforeDate[2] and AfterDate[2] from the secondary file:

  1. BeforeDate[2] is the last known date/time from file #2 that is <= CurrentDate.
  2. AfterDate[2] is the next date/time from file #2 that is >= CurrentDate.
  3. V2before and V2after store the node parameter arrays from those two bounding times.
  4. The code uses linear interpolation fraction F = (CurrentDate - BeforeDate[2]) / (AfterDate[2] - BeforeDate[2]).
  5. Then sets V2[j,k] = V2before[j,k] + F*( V2after[j,k] - V2before[j,k] ).

5. Error Handling

  • Various checks are made: e.g., verifying file existence, format correctness, matching parameter units for parameters with same name, date/time expansions, etc.
  • A global string ErrorTxt is used to store error messages. If it’s non-empty, the routine stops and returns False.
  • If an error occurs or the user-supplied output file can't be created, the code deletes the temporary file and displays a message.

6. Summary of Output

  • The combined file is a valid SWMM interface file with:
    • Time steps at the smaller interval of the two input files.
    • Parameter set that includes all unique parameters from both input files.
    • Node set that includes all unique node/location IDs from both input files.
    • Merged flow & concentration values at each time step for each node.

Hence, the function CombineFiles is the entry point used by a higher-level user interface form (FileCombineForm) to merge two routing interface files, producing one that sums flows and merges water quality data.

SWMM5 Delphi GUI Uclipbrd.pas Summary

 Extended and Expanded Summary of Uclipbrd.pas

This Delphi unit, Uclipbrd.pas, manages the copy and paste operations involving objects in an EPA SWMM project (the project’s internal data structures) to and from an internal clipboard. It is not the same as the Windows system clipboard (although it parallels that usage), but rather a custom data container stored in Project.Clipboard.

The code provides procedures to:

  1. Copy the data of a particular object type (e.g. subcatchment, node, link, label, rain gage) from the project's database into the internal clipboard.
  2. Paste the data from the internal clipboard back onto a target object (replacing the target’s properties).

1. Objects and Their Data

SWMM organizes objects by type (e.g., Subcatch, Node, Link, Gage, Label). Each object type has a set of string fields or properties stored in arrays or lists:

  • For subcatchments: infiltration parameters, land uses, etc.
  • For nodes: invert elevation, inflows, etc.
  • For links: geometry parameters, cross-section, etc.
  • For rain gages: data format, time-series name, etc.
  • For map labels: font name, size, style, etc.

These fields are typically stored in the Data[] arrays of the objects (e.g., TSubcatch.Data[i], TNode.Data[i], etc.).


2. Internal Clipboard: Project.Clipboard

There is a single Project.Clipboard object with these main properties:

  • ObjType: an integer storing the SWMM object type code (like SUBCATCH, JUNCTION, etc.).
  • Data: a string list. Each line holds one property value for the object that was copied.
  • List1, List2: optional additional string lists for objects with more complex data (like infiltration data, or inflows).
  • Font: used only for label objects, storing the TFont attributes.

When a user chooses "Copy" from the GUI for a subcatchment, the code collects the subcatchment data (like indexes [SUBCATCH_RAINGAGE_INDEX .. SUBCATCH_CURBLENGTH_INDEX]) into the Data list, infiltration data into List1, and land uses into List2. The code then marks ObjType := SUBCATCH.

When "Paste" is requested, the code reads these lists from Project.Clipboard and applies them to a given subcatchment’s data arrays.


3. Procedures Overview

A. Copy Routines

  1. CopyGage(Index)
    Copies a rain gage object’s relevant data (e.g. Data[GAGE_DATA_FORMAT..GAGE_RAIN_UNITS]) into Project.Clipboard.

    • ObjType := RAINGAGE;
  2. CopySubcatch(Index)
    Copies a subcatchment object’s data from Data[SUBCATCH_RAINGAGE_INDEX..SUBCATCH_CURBLENGTH_INDEX], infiltration data, and land uses into the clipboard’s Data, List1, and List2.

    • ObjType := SUBCATCH;
  3. CopyNode(Ntype, Index)
    For a node object (junction, outfall, divider, storage), it determines which data indexes to copy (using GetDataIndexes). Then it copies those fields plus any inflow lists.

    • ObjType := Ntype;
      Node inflows appear in DWInflow or DXInflow lists, which get placed in List1 and List2.
  4. CopyLink(Ltype, Index)
    For a link (conduit, pump, orifice, weir, outlet), uses GetDataIndexes to know which data fields to copy, then places them into the Data list.

    • ObjType := Ltype;
  5. CopyLabel(Index)
    Copies a map label object’s font properties (font name, size, bold, italic) into the clipboard’s Font object.

    • ObjType := MAPLABEL;

B. Paste Routines

  1. PasteGage(Index)
    Pastes the data from the Clipboard.Data[] fields back into a rain gage’s data array [GAGE_DATA_FORMAT..GAGE_RAIN_UNITS].

  2. PasteSubcatch(Index)
    Pastes subcatchment properties, infiltration data (List1), and land uses (List2). If the subcatchment’s OutletID changes, the code calls Uupdate.UpdateSubcatchOutlet.

  3. PasteNode(Ntype, Index)
    Pastes the node’s data from the Data array plus any dry-weather and pattern-based inflows from the List1 and List2.
    Then calls Uedit.UpdateEditor(...) to refresh the property editor and color updates if needed.

  4. PasteLink(Ltype, Index)
    Pastes link data. E.g. for a conduit, it might copy shape, offsets, etc. from Data.

  5. PasteLabel(Index)
    Pastes the label’s stored TFont info. Then re-draws it on the map.


4. Shared Helper Routines

GetDataIndexes(ObjType, var First, Last) -> Boolean

  • Each node or link object type uses a certain range of integer indexes to store relevant data.
  • For example, a junction might store data from NODE_INVERT_INDEX up to JUNCTION_PONDED_AREA_INDEX.
  • This routine maps the object type (like JUNCTION, OUTFALL, CONDUIT, etc.) to the correct First and Last indexes in the Data array.
  • Returns False if not recognized.

Copy/Paste Mechanism

When the user calls Copy on an object:

  1. Determine the range of indexes (GetDataIndexes for some types).
  2. Place each string-based property into Clipboard.Data[...].
  3. For more complex objects, place infiltration/inflow arrays in Clipboard.List1, .List2.
  4. Set Clipboard.ObjType to that object’s type.

When the user calls Paste onto an object:

  1. Confirm that Clipboard.ObjType matches the target object type.
  2. Copy the strings from Clipboard.Data, .List1, .List2 into the object’s data arrays or infiltration/inflow lists.
  3. Possibly call Uupdate.Update... to handle post-processing changes (like subcatch outlets, node color, or link geometry).

5. Uutils and Uupdate Interaction

  • Uutils.CopyStringList(...) is used to clone lists from objects to the clipboard and vice versa.
  • Uupdate.UpdateSubcatchOutlet(...) is used if a subcatchment’s outlet changes.
  • Uedit.UpdateEditor(...) is used to refresh the property editor form if the object is currently open for editing.
  • MapForm.EraseLabel(...) and MapForm.DrawObject(...) are used to handle re-drawing the map label after a paste.

6. Key Points

  1. The unit deals only with internal in-application copy/paste, not the OS clipboard.
  2. Each object type has a distinct structure for how many data fields exist and how they’re stored.
  3. For node or link objects, we rely on a helper function GetDataIndexes to identify the relevant data fields (like from “CONDUIT_SHAPE_INDEX” to “CONDUIT_TSECT_INDEX”).
  4. Subcatchments, nodes, and links often carry extra list-based data: infiltration data, land uses, or inflows. These require special handling in Clipboard.List1 and Clipboard.List2.
  5. Labels store only font name, size, bold, italic in the TFont of Clipboard.Font.
  6. After the paste, changes are flagged as “modified” so that the application can track unsaved changes and re-run the model if needed.

Hence, Uclipbrd.pas is an internal utility for copying/pasting SWMM’s object data to the program’s ephemeral data structure, letting the user replicate or reassign the properties from one object to another quickly.

SWMM5 Delphi GUI Ucalib.pas Summary

 Extended and Expanded Summary of Ucalib.pas

This Delphi unit, named Ucalib.pas, is part of the EPA SWMM GUI codebase. It provides routines for retrieving and plotting observed calibration data that match SWMM's simulation data. More specifically, it fetches time-series observations (e.g., measured runoff, flow, groundwater elevations, water quality) from an external calibration file and then plots them (as points) on a TeeChart series in a graph.


1. Primary Purpose

  • Read measured data from a set of calibration files (each file dedicated to a specific kind of data, such as runoff, node depth, link flow, etc.).
  • Parse these calibration files for a particular location (like a subcatchment ID or node ID) and for a particular variable.
  • Plot the data onto a TChartSeries object for visual comparison with the model’s computed time-series on the same plot.

2. Key Constants and Structures

  1. Link between "view variable indexes" and "calibration file indexes":

    A comment block explains which calibration file index corresponds to a certain SWMM variable. For instance:

    • Subcatchment RUNOFF -> calibration file index #1
    • Node NODEDEPTH -> calibration file index #3
    • Link FLOW -> calibration file index #4
    • etc.
  2. CalibData array:
    An external global array (declared somewhere else, presumably Uglobals.pas) that records the file name and location list for each calibration file index.
    For example, CalibData[1].FileName might be the file containing subcatchment runoff measurements. And CalibData[1].Locations might be a string listing which subcatchment IDs have data there.

  3. Toklist: TStringList:
    Used to store tokenized strings read from the calibration file lines.

  4. StartDate, EndDate, TimeFactor, DateTimeDisplay, SimStartDate:
    Shared module-level variables set by the main procedure, used in reading/processing times from the calibration file so that they line up with the time displayed on the TChart.


3. Main Procedure: GetCalibData(...)

This is the central routine that:

  1. Identifies which calibration file to use by calling GetCalibFileIndex().
  2. Checks if that file has measurement data for the user-specified location (like a subcatchment or node ID).
  3. Opens the calibration file and tokenizes each line.
  4. Processes lines belonging to the location of interest.
  5. Extracts the measurement time and data value from tokens.
  6. Adds a point to the chart if it passes checks (within time range, is valid numeric value, etc.).

Parameters:

  • VarIndex: Index identifying the SWMM result variable (like RUNOFF, FLOW, etc.).
  • ObjType: Whether it’s subcatchment, node, or link variable.
  • LocID: The name (ID) of the specific object (like "Node10" or "Subcatch5") to find in the calibration file.
  • aStartDate, aEndDate: Date range that we want to plot.
  • aTimeFactor: If we’re not plotting date/time, this factor is used to convert from days to hours or something similar.
  • aDateTimeDisplay: True if chart uses real date/time for the X-axis. Otherwise, it’s using an elapsed time scale.
  • ChartSeries: A TChartSeries object (for instance a TPointSeries) to which calibration data points are added.

Steps:

  1. GetCalibFileIndex(...): Figures out which calibration file index (1..12, etc.) applies to the variable. Some variables have an additional offset if it’s a pollutant.
  2. If FileIndex = 0, we know there’s no relevant calibration file for that variable.
  3. If the LocID is not present in that file’s Locations string, we skip.
  4. Calculate a “simulation start date” that is slightly earlier than the actual start (one reporting step earlier).
  5. Open the file:
    • For each line, strip comments, parse tokens, detect if a single token indicates new location header.
    • If it matches LocID, we turn on UseData := True; if not, turn it off.
    • Otherwise, if line has enough tokens, parse the measurement time from token[0,1] and the measurement value from token[ DataTok ].
    • Check if the date/time is within [StartDate..EndDate]. If so, add it to the chart.
  6. Close the file & free resources.

AddCalibDataPoint(...) is a helper function that tries to parse the first two tokens as date/time or as an “elapsed day/hour,” then parse the measurement value from a third token. If successful and in range, it calls ChartSeries.AddXY(...).


4. GetCalibFileIndex(VarIndex, ObjType, var FileIndex, var VarOffset)

This helper function looks at:

  • Which object type (Subcatch, Node, or Link).
  • Which variable index (RUNOFF, FLOW, etc.).

It sets:

  • FileIndex: which calibration file index to use (1 for runoff, 2 for subcatchment water quality, 3 for node depth, etc.).
  • VarOffset: a zero-based offset used when a variable might be a pollutant. That means the base index for the calibration file is 2 or 5, but if we have multiple pollutants, we add an offset to know which pollutant is being measured.

5. File Format / Data Reading

Calibration file structure is presumably:

; Comments
Subcatch5
6/1/2019  7:00  0.25
6/1/2019  7:15  0.28
... etc ...
SomeOtherLocation
...
  • A single token line indicates a new location ID.
  • Next lines with multiple tokens: [Date/Time] [Value(s)...].

AddCalibDataPoint tries to parse the date/time. If it fails, it tries to interpret the tokens as “Elapsed days and hours.” Either way, it forms a TDateTime or a float X-value for the chart.


6. Summary

  1. Ucalib.pas provides a way to read measured calibration data from external text files (the CalibData array).
  2. The function GetCalibData does the main work: deciding which file to open, searching for the location ID, parsing lines, building time-value data points, and adding them to a chart series.
  3. The calibration file can have multiple location blocks. Only lines after the “LocID” line are used until a new location name is encountered.
  4. The measured times can be in actual date/time or in elapsed time. The code tries one method, catches exceptions, and then tries the other method.
  5. Points are only included if within [StartDate..EndDate].
  6. The final effect is that the chart can overlay these measured points on top of the model’s simulated time-series for that location and variable, enabling visual calibration or error checking.

Thus, Ucalib.pas is a straightforward but crucial component for importing and plotting observed calibration data in the SWMM interface. It ensures the user can compare computed vs. observed results directly within the GUI’s time series graphs.

SWMM5 Delphi GUI Ubrowser.pas Summary

 Extended and Expanded Summary of Ubrowser.pas

The unit Ubrowser.pas is part of the EPA SWMM (Storm Water Management Model) Delphi-based GUI. It contains functions and procedures that drive the Browser panel within the MainForm of the SWMM application. The Browser panel has two parts:

  1. A Data Page that lists categories (nodes) of SWMM data (e.g., raingages, subcatchments, nodes, links, etc.) in a TreeView, and displays specific items from a selected category in a ListBox.
  2. A Map Page that hosts combo boxes for selecting map display variables and controls for time/date selection.

This unit organizes, updates, and manipulates the data items that appear in the Browser, including the addition, deletion, sorting, and editing of objects, plus controlling output display on the map for different variables and time periods.

Below is a detailed outline:


1. Main Purpose

  • It manages the content and behavior of the Browser panel on the MainForm.
  • It supports object addition, deletion, sorting, renaming, editing, and selection in the Data Page.
  • It also controls time and variable selection for map display in the Map Page (subcatchment, node, link data, date/time, etc.).

2. Key Global Variables and Utilities

Global Variables:

  • CurrentDateIndex, CurrentTimeIndex: track the user-selected date/time indexes from the Date and Time listboxes.
  • OldSubcatchVar, OldNodeVar, OldLinkVar: store the previously selected map display variables for subcatchments, nodes, and links so that we can restore or update them after a new analysis.

Stringlist Sorting:

  • CompareIDStrings: a specialized comparison function that tries to compare numeric IDs numerically, and falls back to normal string comparison otherwise. Helpful for sorting object IDs like 1, 2, 10, 20.
  • SortStringlist: a QuickSort-based routine to sort TStringList items using a user-supplied comparison function (here, CompareIDStrings).

3. Initial Setup Routines

  1. InitBrowser

    • Called at application start or upon creating a new project.
    • Clears the map display variables, resets them to NOVIEW, and calls InitMapViewBoxes.
  2. InitDataPage

    • Called when a new project begins.
    • Clears the “data” side of the Browser (the TreeView's selection, the ItemListBox, and associated states).
  3. InitMapPage

    • Called before running an analysis.
    • Resets stored OldSubcatchVar, OldNodeVar, OldLinkVar.
    • Clears the map theme combo boxes and date/time controls, then calls InitMapViewBoxes to populate them.
    • Disables date/time controls (will enable once a simulation is completed).
    • Assigns units to potential output variables (e.g., flow units, pollution units).
  4. InitMapViewBoxes

    • Fills the Subcatch, Node, and Link combo boxes with input variables only. After the simulation, it calls UpdateMapViewBoxes to add output variables.

4. Browser Data Page Manipulation

The Data Page has a TreeView listing categories (like “Subcatchments,” “Nodes,” “Hydrographs,” etc.), and an ItemListBox showing items within a selected category. The procedures relevant here:

  • BrowserAddItem(ObjType, Index)
    Adds a new object of a given type to the browser’s list box (and optionally refreshes the display if it matches the current list). Updates HasItems for that object type.

  • BrowserDeleteObject
    Prompts the user for confirmation (if Uglobals.ConfirmDelete is true) and then deletes the currently selected object in the list box and database. Calls DeleteItem internally.

  • BrowserEditObject
    Invokes the universal object editing system (e.g., Uedit.EditObject). This can bring up specialized dialogs or the property editor for a selected object.

  • BrowserNewObject
    Creates a new non-visual object by calling Uedit.AddNonvisualObject(Uglobals.CurrentList). For visual objects, the user typically uses the map-based “Add” toolbar buttons.

  • BrowserSortObjects
    Sorts the current object’s items by ID using SortStringList(..., CompareIDStrings). The user sees these sorted in the ItemListBox.

  • DeleteItem
    Called by BrowserDeleteObject or other routines to remove an item from the project’s database. If the object is visual, it calls MapForm.EraseObject(...).

  • BrowserUpdate(ObjType, Index)
    The core routine that sets the current object type, selects the item in the list box, updates the property editor if necessary, highlights the item on the map, and sets the browser’s speed button states.


5. Browser Map Page: Time and Variable Control

  • UpdateMapPage
    Called after a new successful simulation run. It populates the date list box and time list box, sets up the scroll bars, and re-enables those controls. Also sets the current map display to time period 0.

  • EnableDateTimeControls(Boolean)
    Disables/enables the date/time controls in the interface.

  • RefreshTimeListBox(Backwards)
    Rebuilds the items in the TimeOfDay list box for the selected date, either enumerating the day’s steps forward or backward.

  • ChangeDate(I)
    Moves to date index I, calls RefreshTimeListBox with a direction, and thus changes the map’s date portion of the time.

  • ChangeTimePeriod(I)
    Moves to time index I, sets Uglobals.CurrentPeriod, calls RefreshTimeLegend, and triggers RefreshMap plus UpdateProfilePlots.

  • GetCurrentPeriod
    Returns the absolute reporting period from the sum of CurrentDateIndex + CurrentTimeIndex or just direct if DeltaDateTime >= 1.

  • RefreshTimeLegend
    Adjusts the text in the map’s Time Legend panel (i.e., shows the date/time of current period). Also updates ElapsedTimePanel in the main status bar.

  • IncreaseElapsedTime / DecreaseElapsedTime
    Let the user step forward/backward one time step (or day).

  • RefreshMap
    Recomputes color themes if results exist, gets flow directions, updates subcatch/node/link color indexes, and redraws the map.

  • RefreshMapColors
    If the user changes from old variable to new, reapply color sets for subcatchments, nodes, or links.

  • UpdateMapViewBoxes
    After a run, it appends output variables (e.g., rainfall, infiltration, flow, or user pollutant names) to the Subcatch/Node/Link combo boxes.


6. Converting Object Types

Two specialized routines:

  • ConvertNode(oldType, oldIndex, newType)

    • Creates a new node object of newType, copies property data from the old node, updates references in subcatchments and links, etc.
    • Returns the new node’s index.
  • ConvertLink(oldType, oldIndex, newType)

    • Similarly, creates a new link object of newType, copies old link data, updates references, and returns the new link’s index.

These are used, for example, if the user changes a Node from “Junction” to “Storage” or a Link from “Conduit” to “Weir.”


7. Utility Functions

  1. GetIndexOfVar(ObjType, S)
    Finds map variable index by name S in the theme combo box for ObjType.

  2. GetIndexFromObject(ObjType) and GetObjectFromIndex(Index)
    Map from the object types to TreeView node indexes (and vice versa).

  3. AssignOutputUnits
    Assigns measurement units to analysis output variables (flow units, volume, etc.) for subcatchments, nodes, and links.

  4. SetBrowserButtons(ObjType, Index)
    Controls the enabling/disabling of the “New,” “Delete,” “Edit,” “Sort,” “Up,” “Down” buttons on the Data Page, depending on whether objects exist and what type they are.

  5. RefreshObjectImage(ObjType, ImageIndex)
    Potentially updates the image next to an object in the TreeView (not currently used).

  6. UpdateHasItems(ObjType)
    Tracks if the project database has at least one item of a given type or not.


8. Typical Flow of Calls

  • Initialization: InitBrowser, InitDataPage, InitMapPage set up the empty project or new run.
  • Adding/Deleting Objects: BrowserAddItem, BrowserDeleteObject, DeleteItem.
  • Editing: BrowserEditObject calls Uedit.<method>.
  • Sorting: BrowserSortObjects uses SortStringList.
  • Switching: BrowserUpdate moves to a new object type or item, updating displays in list boxes, property editor, and map.
  • Map: UpdateMapPage, EnableDateTimeControls, RefreshTimeListBox, ChangeTimePeriod, RefreshMap handle date/time changes and re-draw of color-coded objects.
  • Convert: ConvertNode and ConvertLink handle advanced usage.

9. Conclusion

Ubrowser.pas plays a vital role in orchestrating the Browser panel’s data structure and interface interactions in the SWMM GUI. It ensures consistency between the project database (Project.Lists[ObjType]), the main form’s TreeView/ListBox, the property editor, and the study area map. Through a well-defined set of routines, it supports editing, sorting, timing, and theming operations that allow users to effectively manage SWMM model data within the application.

SWMM5 Delphi GUI swmm5.pas Summary

 Extended and Expanded Summary of swmm5.pas

This Delphi unit, swmm5.pas, provides import declarations for functions residing in the EPA-SWMM (Storm Water Management Model) engine library. The library in question is swmm5.dll, a compiled binary that executes the core SWMM hydraulic and water quality computations. By linking these external functions, a Delphi application can invoke SWMM’s simulation routines directly.

Below is a more detailed breakdown of each part of swmm5.pas:


1. Purpose and Role of the Unit

  • This file imports (i.e., declares) a set of functions from an external DLL (swmm5.dll).
  • It allows Delphi-based code to call the SWMM engine’s procedures for setting up, running, and finalizing a SWMM simulation, as well as retrieving errors, warnings, and mass balance data.

2. Function Declarations

All these functions have an external SWMM5_DLL directive, indicating they are linked from the SWMM5 DLL:

  1. swmm_run(F1: PAnsiChar; F2: PAnsiChar; F3: PAnsiChar): Integer; stdcall;

    • A convenience procedure to run an entire SWMM simulation from start to finish by specifying paths to:
      • F1: Input file
      • F2: Report file
      • F3: Binary output file
    • Returns an integer status code (0 = success; non-zero = error).
  2. swmm_open(F1: PAnsiChar; F2: PAnsiChar; F3: PAnsiChar): Integer; stdcall;

    • Opens and parses the SWMM input file, typically the first step in a more granular approach (as opposed to the single-call swmm_run).
    • Also initializes internal structures for subsequent calls.
  3. swmm_start(SaveFlag: Integer): Integer; stdcall;

    • Prepares the simulation engine after swmm_open.
    • SaveFlag indicates whether a simulation state is saved at each step (for hotstart usage).
  4. swmm_step(var ElapsedTime: Double): Integer; stdcall;

    • Executes a single time-step of the SWMM simulation.
    • The ElapsedTime parameter, passed by reference, is updated with the simulation’s current elapsed time in the chosen units (days).
  5. swmm_end: Integer; stdcall;

    • Ends the simulation after all time steps finish or have been iterated through.
    • Frees memory used by the simulation engine but leaves some data structures for generating a report.
  6. swmm_report: Integer; stdcall;

    • Generates a detailed status/report file based on simulation results (such as continuity, node/link summaries).
    • This is typically called after swmm_end.
  7. swmm_getMassBalErr(var Erunoff: Single; var Eflow: Single; var Equal: Single): Integer; stdcall;

    • Retrieves mass balance errors for:
      • Erunoff: Runoff continuity error (surface hydrology)
      • Eflow: Flow continuity error (hydraulic routing)
      • Equal: Quality continuity error (water quality)
    • These values help ensure the simulation’s numeric stability and correctness.
  8. swmm_close: Integer; stdcall;

    • Closes the SWMM project and releases all resources allocated in swmm_open.
    • Typically the final call in the simulation lifecycle.
  9. swmm_getVersion: Integer; stdcall;

    • Returns an integer representing the SWMM engine version (multiplied by 100, e.g., version 5.2.1 might be 521).
  10. swmm_getError(ErrMsg: PAnsiChar; MsgLen: Integer): Integer; stdcall;

    • Retrieves a text-based error message from the SWMM engine for any most-recent or pending error.
    • ErrMsg is a buffer that will receive the error string (null-terminated).
    • MsgLen is the buffer size.
  11. swmm_getWarnings: Integer; stdcall;

    • Returns the number of warning messages produced during the simulation run.

3. Notable Details

  • Calling Convention: stdcall
    This means parameters are passed using the standard call method, typical for Windows libraries.

  • Data Types:

    • The function arguments mostly use PAnsiChar for string paths (input/report/output files) or for retrieving error messages.
    • Some procedures exchange Double or Single float types for numeric data, e.g., ElapsedTime, continuity errors.
  • Constant: SWMM5_DLL = 'swmm5.dll';

    • This denotes the library name. Each function is declared external SWMM5_DLL, meaning they are loaded from swmm5.dll.

4. Typical Simulation Workflow

A typical usage pattern within a Delphi application referencing swmm5 might be:

  1. swmm_open(inputFile, reportFile, outputFile) to load project data.
  2. swmm_start(saveFlag) to initialize.
  3. Loop over swmm_step(...) until ElapsedTime returns 0 or a termination condition is found.
  4. swmm_end to finalize.
  5. Optional: swmm_report to produce text-based report data.
  6. swmm_getMassBalErr(...) for continuity checks or swmm_getError(...) / swmm_getWarnings to handle issues.
  7. swmm_close to fully release resources.

Alternatively, swmm_run(inputFile, reportFile, outputFile) can do all steps (open, run, close) in one shot, but with less fine-grained control.


5. Integration Considerations

  • The end user (Delphi developer) includes swmm5.pas in the uses clause.
  • The developer ensures the actual swmm5.dll is accessible (e.g., in the same folder or in the system’s PATH).
  • On building, Delphi dynamically links calls to these declared entry points in the DLL.
  • Error/warning codes are typically interpreted by surrounding code to manage simulation logic.

6. Conclusion

swmm5.pas is a bridge between a Delphi application and the SWMM computational engine. By declaring external methods with stdcall, it allows the developer to open, run, report, and close a SWMM simulation session. It also provides an interface for error retrieval, mass balance stats, and version queries. This encapsulation fosters seamless integration of the SWMM engine’s robust stormwater and hydraulics modeling into Delphi-based applications.

SWMM5 Delphi GUI GridEdit.pas Summary

 Extended & Expanded Summary of GridEdit.pas

The GridEdit.pas unit defines a TGridEditFrame, a custom frame that provides a StringGrid enhanced with in-place numeric editing and a popup menu for quick data manipulations. Below is an in-depth look at its design, components, and functionality.


1. Purpose & Context

  • Objective: Provide a specialized grid for editing numeric data.
  • Key Feature: A TNumEdit control is placed over the selected cell, enabling direct numeric entry (instead of the standard text-based in-place editor).
  • Additional Tools: A PopupMenu offers editing shortcuts—Cut, Copy, Paste, Insert, and Delete—enabling quick table data manipulations.

2. Core Components & Their Roles

  1. TGridEditFrame (Frame):

    • The main container that holds:
      • A TStringGrid (Grid) for data display.
      • A TPanel (EditPanel) housing a TNumEdit control (EditBox) for numeric editing.
      • A TPopupMenu with menu items for cut/copy/paste/insert/delete functions.
    • Publishes a few key properties:
      • AllowInsert: Whether new rows can be added.
      • CenterHeaders: Whether header cells are centered.
      • Modified: Tracks if data changed.
  2. Grid: TStringGrid:

    • Displays rows/columns of textual data (cells).
    • Some columns or rows may represent numeric data that can be edited in numeric form.
    • Integrates event handlers to open the numeric editor, handle key presses, and manage copy/paste operations.
  3. EditPanel: TPanel & EditBox: TNumEdit:

    • The numeric edit box (a TNumEdit from NumEdit.pas) is placed on top of a panel, which is then located to overlap the selected grid cell when editing is triggered.
    • Hidden by default; becomes visible only during cell editing.
    • Accepts only numeric input (supports decimal, negative or positive, depending on configuration).
  4. PopupMenu with items:

    • Cut / Copy / Paste: Standard text-based operations for selected cells.
    • Insert / Delete: Insert or remove data or rows in the grid.

3. Editing Mechanics

  1. Initiating Edit:

    • When user presses Enter or starts typing in a cell, the ShowEditor method:
      1. Decides if the user wants to override the cell’s old text or append new input.
      2. Moves the EditPanel (with EditBox) over that cell.
      3. Sets visibility to true and passes the initial keystroke onward to EditBox.
  2. Handling Key Presses in EditBox:

    • Enter Key (#13):
      • Finishes edit → EditBoxExit is called → commits changes to the grid.
      • Optionally moves the active cell to the right if AutoMove is true.
    • Escape Key (#27):
      • Cancels the edit (reverts to old cell text).
      • Hides the panel.
    • Arrow Keys (VK_UP/VK_DOWN):
      • Moves the selection up/down in the grid, ending current edit session.
  3. EditBoxExit:

    • Occurs when user leaves the editing control (either by key action or clicking away).
    • The typed value in EditBox is assigned to the cell. If changed, Modified is set true.
    • The edit panel is hidden.
  4. GoAutoMove:

    • If AutoMove is enabled and the user pressed Enter, the focus moves to the next cell (right column or next row if at row’s end).
    • This simulates how spreadsheet applications often behave.

4. Popup Menu Operations

Popup provides typical data manipulations:

  1. Cut:
    • Calls CopyCells, then ClearCells on the selected range.
  2. Copy:
    • Extracts selected cells into a string list separated by tabs, places them on the Clipboard.
  3. Paste:
    • Reads text from the Clipboard, splits it by rows/tabs, and places it into the grid starting at the current selection.
    • If the text extends beyond current row capacity, the grid can grow row count as needed.
  4. Insert:
    • Similar to Paste, but first calculates how many lines to insert, calls InsertRows, then does a normal PasteCells operation.
  5. Insert Row:
    • Adds a single row below the currently selected row.
  6. Delete Row:
    • Removes the current row from the grid, shifting subsequent rows up.

5. Implementation Highlights

  1. Grid Row & Col:
    • The component sets FixedCols (often 1) if row indexing is used.
    • The user’s selected region is known through Grid.Selection.
  2. Clipboard Format:
    • All data is stored as text. For multiple rows, each row ends with a CRLF, and columns within a row are separated by a TAB.
  3. Row Counting (CountRows):
    • For Insert operation, code counts how many line breaks occur in the copied text to decide how many new rows to insert.

6. Key Methods & Their Responsibilities

  1. ShowEditor(Key: Char):

    • Activates numeric EditBox, re-initializes the text (blank if user typed a char, or old cell contents if the user pressed Enter).
    • Positions the panel over the cell.
  2. SetEditBounds:

    • Calculates the exact cell rectangle in the Grid and sets EditPanel and EditBox to overlay that cell.
  3. EditBoxKeyPress:

    • Interprets Enter (finish edit → commit) or Escape (cancel edit → revert).
  4. MenuItemClick(Sender: TObject):

    • The central handler for popup actions. Distinguishes Cut, Copy, Paste, Insert, etc., by the menu item’s Tag.
  5. PasteCells:

    • Splits the multiline string from Clipboard by row (CR or CRLF) and by column (TAB).
    • Fills the cells sequentially, extending row count if needed.
  6. InsertRows(Nrows: Integer):

    • Makes space by shifting existing row data downward, leaving blank rows for new content at the top.
  7. DeleteOneRow:

    • Removes the user’s current row from the grid.

7. Public Properties

  • AllowInsert: Toggles whether Insert/Paste adds new rows or not.
  • CenterHeaders: If true, the top row cells get centered text.
  • Modified: Read-only boolean that indicates changes since creation/last set.

8. Typical Usage Scenario

  1. Drop a TGridEditFrame onto a form, set AllowInsert to true if you want row insertion.
  2. Populate the Grid with data or set row/column counts.
  3. Run your app. The user can:
    • Click or start typing in a numeric cell → an in-place numeric edit box appears.
    • Use arrow keys or Enter to move around cells.
    • Right-click to open the popup menu → cut/copy/paste/insert/delete.
    • Data changes set Modified = true.

9. Summary

GridEdit.pas extends the standard TStringGrid with numeric editing (through a TNumEdit) and a context menu for data manipulation. This design is particularly handy for editing numeric arrays or parameter sets, providing row insertion/deletion logic, a consistent numeric input interface, and an Excel-like cut/copy/paste user experience.

SWMM5 Delphi GUI TPropEdit.pas Summary

Below is an extended and expanded summary of the PropEdit.pas code. It gives a high-level description of how the TPropEdit component operates, the sub-components it creates, and how it manages the display and editing of property values.


1. Purpose and Overview

  • PropEdit.pas defines a Delphi component named TPropEdit, which visually displays a set of properties in a two-column layout—property names on the left, and corresponding values on the right.
  • The component manages reading, displaying, and editing property values via specialized in-place editors (an TEdit for text or numeric input and a TComboBox for list-based selections).
  • Each individual “property” is described by a TPropRecord structure, which specifies how the property is labeled and how it can be edited.

2. Relationship to Delphi UI

  • TPropEdit derives from TCustomPanel and includes:
    • A header panel with two sub-panels for column headings,
    • A splitter that allows resizing of the two column headers,
    • A string grid (named FGrid) that contains rows for each property and two columns (property name / property value),
    • Two ephemeral editor controls: a normal edit control (FEdit) and a combo box (FCombo)—both appear temporarily, placed over a cell to allow user input.

3. The TPropRecord Structure

Each property is defined by a record named TPropRecord:

  • Name: The user-facing name of the property (appears in the left column).
  • Style: One of the following edit styles:
    1. esHeading: Not editable; used as a descriptive heading.
    2. esReadOnly: The property displays a value that cannot be edited.
    3. esEdit: User can type text or numbers in an TEdit control.
    4. esComboList: A drop-down list (fixed choices, no user text input).
    5. esComboEdit: A drop-down list (but users can also edit or type new text).
    6. esButton: Special style that displays a “button” (drawn within the cell) which triggers an external event.
  • Mask: An edit mask that further restricts esEdit entry (e.g., numeric only, positive numeric, no spaces, or none).
  • Length: Maximum text length allowed in the esEdit style.
  • List: For combo box styles, a string containing the possible choices (separated by #13).

4. TPropEdit Sub-Components

When TPropEdit is first created:

  1. FGrid (a TStringGrid)
    • Two columns: property name (col 0) and property value (col 1).
    • Allows for custom drawing of cells (OnDrawCell) so that headings, read-only cells, and button cells can be visually distinct.
    • Manages row selection, key navigation, etc.
  2. Header Panel / Sub-panels
    • A top panel FPanel1 that holds:
      • FHeader1 (the left header label, i.e., property name heading),
      • FSplitter (the movable splitter),
      • FHeader2 (the right header label, i.e., property value heading).
    • The user can drag FSplitter to adjust how much width is given to each column.
  3. FEdit (TEdit)
    • Invisible by default.
    • Placed over a grid cell for in-place editing of textual/numeric properties.
    • Restricts user input according to the property’s Mask (e.g., numeric only).
  4. FCombo (TComboBox)
    • Invisible by default.
    • Used instead of FEdit when the property’s style requires a drop-down list of choices (esComboList/esComboEdit).
    • The user can pick from a set of items or, in esComboEdit, can also type a custom value.

5. Property Editor Lifecycle

  1. Loading Properties
    • The SetProps method is called with two parameters:
      • An array of TPropRecord (defining each property’s name, edit style, etc.),
      • A matching stringlist of initial values for these properties.
    • TPropEdit sets up the FGrid row count to match the number of properties, placing each property’s name in col 0 and each initial value in col 1.
  2. Display and Interaction
    • The user sees each property name in the left column and the current value in the right column.
    • If the property style is:
      • esHeading: Shows only a label, merges with the left column cells, not editable.
      • esReadOnly: The user cannot edit the value.
      • esEdit: The user can click or press a key to invoke the FEdit control.
      • esComboList/esComboEdit: The user sees or can invoke a FCombo drop-down for selecting or typing a value.
      • esButton: The property row shows a small “button” on the right. When clicked, it fires the OnButtonClick event.
  3. Editing
    • On a keystroke or double-click in a cell, TPropEdit:
      • Positions and displays either FEdit or FCombo exactly over that cell.
      • The user modifies the text or picks from the list.
      • On pressing Enter, or leaving the cell, TPropEdit hides the edit control.
    • The OnValidate event (if assigned) is called to check the new value. If valid, TPropEdit updates FGrid and its internal stringlist. Otherwise, it can revert or show an error message.
  4. Finishing Edits
    • The “modified” flag is set if the user changes a property.
    • The user or code calls EndEditing or sets focus away from the editor to finalize changes.

6. Event Handling

  • Row selection is tracked, and OnRowSelect can be triggered whenever a new row is chosen.
  • OnValidate is where code can confirm or reject new values.
  • OnButtonClick is triggered for an esButton style property row if a user clicks that property’s “button.”

7. Key Implementation Details

  1. GoValidate
    • Utility method that checks if a user’s new value is valid via an OnValidate callback. If it is valid, it updates the grid and the underlying stringlist.
    • If not valid, raises an exception or discards changes.
  2. StringGrid Drawing
    • The component customizes the grid appearance for headings, read-only cells, etc.
    • For an esButton property, the right column draws a small button-like rectangle.
  3. FHeaderSplit
    • A user-defined percentage controlling the relative widths of property vs. value columns. The user can drag a splitter at runtime to change these columns’ widths.
    • SplitterMoved updates the grid column widths accordingly.
  4. FReadOnlyColor, FValueColor, FHeadBackColor, FHeadForeColor
    • Control the background/foreground colors of read-only property cells, value cells, and heading cells.

8. Typical Usage

  1. Create a TPropEdit component on a form.
  2. Call SetProps(PropertyArray, Values) to populate the editor with property definitions and initial values.
  3. Display the form, letting the user interact with the property table.
  4. Validation of changed values occurs through the OnValidate event.
  5. Button property rows use the OnButtonClick event for specialized actions.
  6. At the end, retrieve updates (if any) from the property editor via the underlying stringlist or by calling GetProp for each property.

9. Summary

  • TPropEdit is a self-contained property editing panel. It organizes properties (described by TPropRecord) in a grid.
  • It seamlessly offers different editing styles: read-only, heading, direct text input, combo box selection, or custom “button event.”
  • By hooking up OnValidate and OnButtonClick handlers, one can create a robust, small-scale “property inspector” tailored to Delphi applications.
  • It features column headings, color customizations, automatic resizing with a splitter, and row-based event callbacks.

In short, TPropEdit gives a developer the means to present a property table to end-users with minimal overhead, while also allowing easy customization for validation and specialized event handling.

SWMM5 Delphi GUI Ftable.pas Summary

 Below is a high-level summary of Ftable.pas, a Delphi unit within the EPA SWMM 5 application. This unit implements TTableForm, an MDI child form that displays tabular time series results of a SWMM simulation using a TDrawGrid component.


1. Purpose of Ftable.pas

The Ftable.pas unit defines a form (TTableForm) that provides a time series data table for SWMM's simulation results. Depending on the user’s selection (described by a TReportSelection record), the table can display:

  1. Table by Variable: Time series for a single variable (e.g., flow, depth, or subcatchment runoff) across multiple objects.
  2. Table by Object: Time series for one object (a single node, link, subcatchment, or the system) across several variables.

The table is populated with results from SWMM’s binary output file. When a new simulation is completed, calling RefreshTable re-queries the output file for the selected data and redraws the table.


2. Key Elements of TTableForm

  1. TTableForm class:

    • Inherits from TForm and acts as an MDI child window inside SWMM.
  2. Grid1: TDrawGrid:

    • The main grid where data is displayed (time along rows; variables/objects along columns).
    • Each cell is rendered in the Grid1DrawCell event.
  3. Edit1: TEdit (invisible at runtime):

    • Provides a reference for consistent row/column heights.
  4. Table: TReportSelection:

    • Stores the user’s selection parameters (object type, variable indices, date/time display mode, etc.).
  5. ColLabel[]: array:

    • Holds the string labels (headers) for each column.
  6. Methods:

    • CreateTable(aReportSelection):
      Receives a TReportSelection describing what data to display, sets up column headers, and calls RefreshTable.
    • RefreshTable:
      Retrieves data from SWMM’s output results, populates the column headings, and sets the row count. Updates Grid1 display.
    • Grid1DrawCell:
      Custom drawing of each table cell (including date/time in columns 0-1, and fetched simulation data in columns 2+).
    • CopyTo:
      Launches the "Copy To" dialog (in Dcopy.pas) and calls CopyToString to copy the current selection to file or clipboard.
    • Print:
      Prints the grid across multiple pages if necessary (using Xprinter.pas).

3. Work Flow

  1. Creation: When a user requests a Table by Object or Table by Variable, SWMM builds a TReportSelection and calls TableForm.CreateTable(ReportSelection).
  2. Setup: The form uses the TReportSelection to configure:
    • The number of columns,
    • Column headers (object IDs or variable names + units),
    • Row count (matches number of time steps).
  3. Population: Each time step is placed in row 1..N, and each item (object/variable) in columns 2..M. Rows 0 or columns 0-1 are for headings.
  4. Interaction:
    • Sorting is limited (only partial).
    • Copying is done by selecting a block of cells or the entire table, then calling CopyTo.
    • Printing goes column by column to fit across multiple pages.

4. Integration with SWMM

  • The table obtains results from Uoutput.Get*ValStr functions which read from SWMM’s binary results file.
  • Date/time and simulation indexing come from Uglobals fields like StartDateTime, DeltaDateTime, ReportStep, etc.

5. Summary

In Ftable.pas, TTableForm is the MDI child window that displays time series data in tabular form, fetches SWMM output results for each time step and item, renders them in a TDrawGrid, and provides copying/printing functionalities. This is part of SWMM’s user interface for analyzing and exporting simulation results in tabular format.

SWMM5 Delphi GUI Fstatus.pas Summary

 Below is a high-level summary of Fstatus.pas, the Delphi unit that implements the TStatusForm in SWMM. This form is used to display the Status Report (a text-based summary of the SWMM simulation run).


1. Purpose

Fstatus.pas defines the TStatusForm, an MDI child form that:

  1. Loads and displays the text content of a temporary Status Report file produced by the SWMM engine.
  2. Offers functionality to copy the text to the clipboard or to an external file.
  3. Supports printing the text contents to the printer or a preview window.

2. Key Components

  1. Memo1 (TMemo):

    • Displays the text lines of the Status Report.
    • Can be scrolled to see the entire report.
  2. Methods:

    • RefreshStatusReport:
      Opens the temporary report file (TempReportFile) in text mode.
      Reads all lines and loads them into Memo1.Lines.
    • ClearReport:
      Clears the Memo so the text is empty.
    • CopyTo:
      Launches the CopyTo dialog to let the user copy the report to the Windows clipboard or to a file.
    • Print:
      Prints the textual content of the Status Report through the main form’s printer object.

3. Overall Flow

When SWMM completes a simulation, it writes a Status Report to a file. The TStatusForm:

  1. Refresh: Reads that file and populates Memo1.
  2. The user can copy the textual contents or print them from the form’s UI.
  3. Once the user closes the form, it frees itself (in typical MDI child fashion).

In summary, Fstatus.pas provides a simple text viewer form (TStatusForm) for SWMM’s Status Report, with basic capabilities to display, copy, and print the simulation’s textual run results.

SWMM5 Delphi GUI Fstats.pas Summary

 Below is a high-level summary of Fstats.pas, the Delphi unit that implements the TStatsReportForm in SWMM. This form is used to produce a statistical analysis report of user-specified events (e.g., peaks, totals, durations) taken from simulation results.


1. Purpose

Fstats.pas defines TStatsReportForm, an MDI child form that:

  1. Takes a TStatsSelection record (from Dstats.pas) describing which object, variable, and analysis type (peak, mean, etc.) to study.
  2. Uses Ustats.GetStats to compute the event-based statistics (peak values, durations, volumes, etc.), returning:
    • A list of individual events (EventList).
    • Summary results in a TStatsResults record.
  3. Displays the results in a PageControl with these pages:
    • StatsPage: textual summary of overall event stats (mean, min, max, etc.).
    • TablePage: rank-ordered table of events.
    • HistogramPage: histogram plot of event values.
    • FrequencyPlotPage: exceedance frequency plot of event values.

2. Components and Displays

  1. StatsPage (StatsMemo):

    • Lists key summary information:
      • Object name, Variable name, Units
      • Number of events, min/max/mean values, standard deviation, skewness
      • Period of record and event threshold criteria
    • This text is built from templates in StatsText.
  2. TablePage (EventTable):

    • A rank-ordered list of all events, each with date/time, value, duration, frequency, etc.
    • Includes sortable columns (headers that user can click).
    • Event data come from the EventList.
  3. HistogramPage (HistoChart):

    • A bar chart (TBarSeries) of event values, grouped into bins.
    • Code calculates bin widths, min & max event values, etc.
  4. FrequencyPlotPage (FreqChart):

    • An exceedance frequency chart (TAreaSeries), showing event value on x-axis vs. log-based exceedance freq. on y-axis.

3. Key Methods

  1. CreateReport(StatsSelection):

    • Stores the selected statistical options in a local variable (Stats).
    • Sets up object & variable names, units, and the display caption.
    • (Later, RefreshReport actually runs the analysis.)
  2. RefreshReport:

    • Clears any existing events from EventList.
    • Calls Ustats.GetStats to compute new event data & summary results.
    • Fills in StatsPage (text), TablePage (grid), HistogramPage (bar chart), FrequencyPlotPage (exceedance chart).
  3. RefreshStatsPage / RefreshTablePage / RefreshHistoPage / RefreshFreqPage:

    • Each routine populates one of the 4 pages with the newly computed data.
  4. CopyTo / Print:

    • Allows user to copy or print the currently visible page.
    • For the histogram & frequency pages, uses graph copy/print logic (see Ugraph).
    • For the summary page, copies the text from StatsMemo.
    • For the table page, copies or prints the rank-ordered event table.
  5. SelectAll:

    • Selects all rows/columns in the event table (for e.g. copying to clipboard).

4. Overall Flow

A TStatsSelection describing the event-based analysis is passed to CreateReport, which sets up references to the object/variable and calls RefreshReport. That method invokes Ustats to compute statistics and fill EventList & Results. The results then populate four pages (text summary, event table, histogram, frequency plot). The form supports copying/printing either the text/table pages or the chart pages, and provides “select all” for the event table.


In summary, Fstats.pas manages the creation and display of a statistics report on events (like storm events or flow events) in SWMM, showing both textual summaries and graphical charts of the event data.

InfoSWMM: A 2030 AI-Assisted Study Guide

  InfoSWMM: A 2030 AI-Assisted Study Guide delete   InfoSWMM: A 2030 AI-Assisted Study Guide A comprehensive study guide for someone in 2030...