Extended and Expanded Summary of Ucoords.pas
This Delphi unit, Ucoords.pas, is part of the EPA SWMM project. It provides functionality to:
- Compute the bounding (min/max) coordinates of all geometry in the model.
- 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:
-
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 (bottom-left corner) and (top-right corner). -
TransformCoords(LL1, UR1, LL2, UR2: TExtendedPoint)
Applies a linear coordinate transform to all map objects. The transform is from an old bounding rectangle to a new bounding rectangle .
Data Types & Structures
Extended: A floating-point type used for coordinates.TExtendedPoint: A record containingXandYfields of typeExtended.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:
-
Initialize bounding values
X1 := -MISSING; X2 := MISSING;Y1 := -MISSING; Y2 := MISSING;
Note that
MISSINGis a special constant used to designate "no coordinate".-MISSINGis effectively negative infinity, andMISSINGis positive infinity for the logic. -
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.
-
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. -
Returning:
- On exit,
X1, Y1will be the minimum coordinate in each dimension. X2, Y2will be the maximum coordinate in each dimension.
- On exit,
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 cornersLL2,UR2= new lower-left & upper-right corners
Key Steps:
-
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
Xin[LL1.X, UR1.X]is mapped into[LL2.X, UR2.X]linearly. -
Define Local Transform Helper Functions
Xtransform(X: Extended): ExtendedYtransform(Y: Extended): Extended
If X or Y is
MISSING, it remainsMISSING; otherwise it’s a direct linear scaling from the old domain to the new domain. -
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.
- Rain gage => transform
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
- Global Variables:
Xscale,Yscale: Computed once inTransformCoordsto store the scale factors.
- Local Helper:
AdjustExtentsinsideGetCoordExtentsis used to handle degenerate bounding boxes by expanding them a bit.
Project:
TheProjecthas lists of different object types—some are in memory as TNode, TLink, TSubcatch, TRainGage, TMapLabel, etc.- MISSING:
A sentinel constant used to represent nonexistent or undefined coordinates. - 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).
- Rain gages store a single
5. Error Handling & Edge Cases
GetCoordExtentschecks whether all coordinates might remain at default values (X1 = -MISSINGorX2 = MISSING) if no geometry is present.- If
X1 = X2orY1 = Y2after reading geometry, they get expanded by 5% or by ±5 units if the bounding coordinate is 0. TransformCoordsdoes 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:
-
GetCoordExtentscollects 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. -
TransformCoordslinearly 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.
No comments:
Post a Comment