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 containingX
andY
fields 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
MISSING
is a special constant used to designate "no coordinate".-MISSING
is effectively negative infinity, andMISSING
is 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, Y1
will be the minimum coordinate in each dimension. X2, Y2
will 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
X
in[LL1.X, UR1.X]
is mapped into[LL2.X, UR2.X]
linearly. -
Define Local Transform Helper Functions
Xtransform(X: Extended): Extended
Ytransform(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 inTransformCoords
to store the scale factors.
- Local Helper:
AdjustExtents
insideGetCoordExtents
is used to handle degenerate bounding boxes by expanding them a bit.
Project
:
TheProject
has 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
GetCoordExtents
checks whether all coordinates might remain at default values (X1 = -MISSING
orX2 = MISSING
) if no geometry is present.- If
X1 = X2
orY1 = 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:
-
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. -
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.
No comments:
Post a Comment