A Civil 3D / AutoCAD plugin (.NET 8) for hydrology and basin analysis. Uses NetTopologySuite for all polygon boolean operations.
Attaches a basin ID to a closed polyline as XData under the C3DTools_Basin RegApp.
Command: TAGBASIN
Select basin polyline to tag:
Enter basin ID: B-101
Polyline tagged with basin ID: B-101
Reads and prints the basin ID and, if the polyline is a split piece, the split classification.
Command: GETBASIN
Select basin polyline to retrieve ID:
Basin ID: B-101
Split Classification: ONSITE
Parent Basin ID: B-101
For an unclassified parent polyline only Basin ID is printed.
Places a DBText entity at a user-picked point using the basin ID from a tagged polyline. Text height inherits db.Textsize; layer inherits the polyline layer.
Command: LABELBASIN
Select tagged basin polyline:
Pick point for label:
Basin label 'B-101' placed at (1234.00, 5678.00, 0.00)
Automatically finds every C3DTools_Basin-tagged closed polyline in the drawing, prompts for a site boundary, then generates onsite (intersection) and offsite (difference) result polylines. The command is idempotent — existing split results are erased before regenerating.
Workflow:
- Scans model space for all
C3DTools_Basin-tagged closed polylines. - Prompts for a site boundary polyline (must be closed).
- Erases any polylines already carrying
C3DTools_BasinSplitXData. - For each tagged basin:
- Computes
basin ∩ site→ onsite pieces placed onCALC-BASN-ONSITE(green). - Computes
basin − site→ offsite pieces placed onCALC-BASN-OFFSITE(red). - Each result polyline is tagged with both
C3DTools_Basin(parent ID) andC3DTools_BasinSplit(parent ID + classification).
- Computes
- Reports totals to the command line.
Command: SPLITBASINS
Found 4 tagged basin(s).
Select site boundary polyline:
Erased 8 existing split basin polyline(s).
SPLITBASINS complete: 4 basin(s) processed, 4 onsite piece(s) created, 3 offsite piece(s) created.
Output layers (created automatically if absent):
| Layer | Color | Contents |
|---|---|---|
CALC-BASN-ONSITE |
3 (green) | Basin area inside the site boundary |
CALC-BASN-OFFSITE |
1 (red) | Basin area outside the site boundary |
Collects tagged closed basin polylines, configured land-use hatches, basin geometry, basin areas, and basin × land-use overlap areas into the JSON contract consumed by the Python hydrology engine.
Layer names containing CN## export that value as land-use curve number metadata. Impervious-looking layer names such as IMP, PAV, or ROOF default to CN 98. Composite CN is calculated by Python, not Civil 3D.
Exports basin_model.json, runs python -m hydro_app.cli run, and writes results.json, validation_report.json, and report.xlsx to a hydrology-run folder next to the drawing when the python-engine folder and Python dependencies are available.
The Python engine can also accept NOAA Atlas 14 precipitation depth CSV output directly:
hydro run basin_model.json --out results.json --validation validation_report.json --excel report.xlsx --atlas14-depths data/PF_Depth_English_PDS.csv --atlas14-duration 24-hrBy default, this creates storm entries for every Atlas 14 ARI available from 1 through 100 years for the selected duration, then writes peak-flow rows for each basin and storm. Use --atlas14-ari 10 when you want only one return period.
Hydrographs are generated by the Python engine with local NRCS/SCS runoff and unit-hydrograph functions. Atlas 14 duration-depth tables are converted into an Atlas 14 alternating-block cumulative rainfall distribution, selected from the Basin Palette settings, and SCS hydrograph rows are generated from CN, area, and manual Tc. See docs/hydrology_methodology.md for the detailed calculation methodology.
The model supports a Hydraflow-style hydrographs table where each row produces one output hydrograph. Supported calculation rows are currently SCS, Combine, and Reservoir. Combine accepts multiple upstream hydrograph ids and creates one study-point hydrograph that can feed a reservoir, report point, or another combine. Reservoir builds a stage-storage-discharge table from pond storage and outlet rows, then routes the inflow hydrograph with the Storage Indication method. When basin_model.json does not define explicit hydrograph rows, Python automatically creates SCS rows for each basin and Combine rows where basin routing requires upstream accumulation.
results.json includes a top-level active-storm hydrographs table with peak flow, time interval, Tc, time to peak, volume, inflow hyd(s), maximum elevation/storage, reservoir outlet rating rows, description, and point arrays. It also preserves per-basin local/routed summaries for Civil 3D import and labels.
Reach and Rational rows are reserved in the contract but are not yet implemented.
Prompts for a basin polyline and a Tc value in minutes, then stores that value as hydrology input XData. The exporter writes it to tc_minutes so Python can use manual Tc values without Tc path automation.
Prompts for an upstream basin polyline and a downstream basin ID, or OUTLET. The exporter writes downstream_id and basin-route links into basin_model.json; Python validates missing downstream references and routing cycles.
The Basin Palette also supports these hydrology inputs directly. Select a tagged basin on the Basins tab to edit manual curve number, Tc, and downstream target, or use the Networks tab to review and edit downstream relationships across tagged basins.
Imports results.json and writes basin result metadata back to matching basin polylines as XData under C3DTools_HydroResults. Results are matched by exported drawing handle when available, with a basin-id fallback only when the id uniquely identifies one tagged polyline.
Creates multiline MText labels for basin polylines that have imported hydrology result XData. The command removes labels previously created by LABEL_HYDRO_RESULTS before recreating them, so it is safe to rerun after importing updated results.
Automatically collects all basin-tagged polylines from model space, prompts for a hatch selection, then computes the intersection area of each basin against each hatch layer.
Workflow:
- Scans model space for all
C3DTools_Basin-tagged polylines (parents and split pieces). - Prompts for hatch selection.
- For each invalid hatch, offers an inline fix-or-skip prompt.
- Computes intersection area per (basin, hatch layer) pair.
- Aggregates multiple geometry fragments sharing the same basin ID and classification into one row.
- Displays results in a resizable dialog. Includes a Copy to Clipboard button (tab-separated, paste directly into Excel).
Output table (Classification column appears only when split pieces are present):
id Classification C-IMPERVIOUS C-OPNSP Total
-------- -------------- ------------ ------- -------
B-101 (parent) 1.2500 0.8000 2.0500
B-101 ONSITE 0.7500 0.5000 1.2500
B-101 OFFSITE 0.5000 0.3000 0.8000
B-102 (parent) 2.1000 1.4000 3.5000
B-102 ONSITE 1.3000 0.9000 2.2000
B-102 OFFSITE 0.8000 0.5000 1.3000
(parent)— the original whole-basin polyline; unambiguously not ONSITE or OFFSITE.- Rows are grouped by basin ID with a blank line between basins.
- Basins without split pieces produce a single row (no Classification column).
| Command | Description |
|---|---|
PLUNION |
Unions two or more selected polylines. Originals are deleted; result polyline(s) are created. |
PLINT |
Intersects two or more selected polylines. Originals are preserved. |
PLDIFF |
Subtracts selected polylines from a base polyline. |
All three commands optionally prompt to delete the input polylines and report the number of result geometries created.
| Command | Description |
|---|---|
FIXHATCH |
Detects and repairs topologically invalid hatches (self-intersections, mis-wound rings, holes outside shell). Recreates the hatch using the AppendLoop / EvaluateHatch pattern. Properties preserved: layer, lineweight, pattern name/scale/angle. |
FIXPOLY |
Detects and repairs invalid polyline geometries (bowties, self-intersections, duplicate vertices). May split one polyline into multiple result polylines. |
Both RegApp names are registered automatically on first write.
Written by TAGBASIN. Also stamped on every split result by SPLITBASINS so GETBASIN works on any basin piece.
| Slot | DxfCode | Value |
|---|---|---|
| 0 | ExtendedDataRegAppName |
"C3DTools_Basin" |
| 1 | ExtendedDataAsciiString |
"<basinId>" |
Written by SPLITBASINS on generated split pieces.
| Slot | DxfCode | Value |
|---|---|---|
| 0 | ExtendedDataRegAppName |
"C3DTools_BasinSplit" |
| 1 | ExtendedDataAsciiString |
"<basinId>" |
| 2 | ExtendedDataAsciiString |
"ONSITE" or "OFFSITE" |
All geometry conversion is arc-accurate.
| Source | Arc handling |
|---|---|
Polyline (bulge segments) |
Tessellated via the bulge formula — bulge = tan(θ/4) — into 16 segments per arc |
Hatch polyline loop (BulgeVertexCollection) |
Same bulge tessellation, 16 segments |
Hatch curve loop CircularArc2d |
GetSamplePoints(17) — AutoCAD handles traversal direction |
Hatch curve loop EllipticalArc2d |
GetSamplePoints(17) |
| Spline | Silently skipped |
C3DTools/
├── Commands/
│ ├── BasinCommands.cs # TAGBASIN, GETBASIN, LABELBASIN
│ ├── SplitBasinsCommand.cs # SPLITBASINS
│ ├── BasinLanduseCommand.cs # BASINLANDUSE
│ ├── UnionCommand.cs # PLUNION
│ ├── IntersectionCommand.cs # PLINT
│ ├── DifferenceCommand.cs # PLDIFF
│ ├── FixPolylineCommand.cs # FIXPOLY
│ └── FixHatchCommand.cs # FIXHATCH
├── Helpers/
│ ├── BooleanOperationHelper.cs # Shared NTS Intersect / Difference wrappers
│ ├── GeometryConverter.cs # Polyline / Hatch -> NTS (arc-accurate)
│ ├── GeometryHelper.cs # Polyline creation from NTS results
│ ├── GeometryValidator.cs # Pre-operation geometry validation & repair
│ ├── HatchFixer.cs # Hatch repair logic
│ └── PolylineHelper.cs # Selection filter helpers
└── UI/
└── BasinLanduseResultForm.cs # Results dialog for BASINLANDUSE
- AutoCAD Civil 3D 2024 / 2025
- .NET 8
- NetTopologySuite (bundled via NuGet)
- Open
C3DTools.slnin Visual Studio 2022 or later and build. - In AutoCAD type
NETLOADand browse to the outputC3DTools.dll. - All commands listed above are immediately available for the session.
To load automatically on every session, add the NETLOAD call to your acad.lsp or the AutoCAD Startup Suite.