trenchfoot 0.1.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of trenchfoot might be problematic. Click here for more details.
- trenchfoot-0.2.3/.env +1 -0
- trenchfoot-0.2.3/CHANGELOG.md +52 -0
- trenchfoot-0.2.3/CLAUDE.md +68 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/PKG-INFO +16 -18
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/README.md +15 -17
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/docs/scenario_gallery.md +1 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/generate_scenarios.py +104 -27
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/gmsh_sloped_trench_mesher.py +125 -25
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/metrics.json +4 -4
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/scene.json +2 -2
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S01_straight_vwalls/trench_scene.obj +49 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S01_straight_vwalls/volumetric/trench_volume.msh +755 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/metrics.json +10 -10
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/scene.json +3 -3
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S02_straight_slope_pipe/trench_scene.obj +14407 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S02_straight_slope_pipe/volumetric/trench_volume.msh +2114 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/metrics.json +42 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/scene.json +4 -4
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/trench_scene.obj +10547 -10540
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/volumetric/trench_volume.msh +3797 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/metrics.json +46 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/scene.json +8 -7
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/trench_scene.obj +17999 -17988
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/volumetric/trench_volume.msh +6095 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/metrics.json +42 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S05_wide_slope_pair/scene.json +6 -6
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/trench_scene.obj +28810 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S05_wide_slope_pair/volumetric/trench_volume.msh +5081 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/metrics.json +43 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_top.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/scene.json +6 -6
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/trench_scene.obj +12812 -12793
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/volumetric/trench_volume.msh +10402 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/metrics.json +48 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/preview_oblique.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/preview_side.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/preview_top.png +0 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/scene.json +203 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/trench_scene.obj +64401 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/S07_circular_well/volumetric/trench_volume.msh +22370 -0
- trenchfoot-0.2.3/packages/trenchfoot/scenarios/SUMMARY.json +470 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/trench_scene_generator_v3.py +311 -46
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/pyproject.toml +1 -1
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/tests/test_trenchfoot_generation.py +203 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/uv.lock +1 -1
- trenchfoot-0.1.1/.env +0 -1
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S01_straight_vwalls/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S01_straight_vwalls/trench_scene.obj +0 -46
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S01_straight_vwalls/volumetric/trench_volume.msh +0 -1017
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S02_straight_slope_pipe/trench_scene.obj +0 -14404
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S02_straight_slope_pipe/volumetric/trench_volume.msh +0 -2389
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/metrics.json +0 -42
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/volumetric/trench_volume.msh +0 -4463
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/metrics.json +0 -46
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/volumetric/trench_volume.msh +0 -7610
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S05_wide_slope_pair/metrics.json +0 -42
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S05_wide_slope_pair/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S05_wide_slope_pair/trench_scene.obj +0 -28803
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/metrics.json +0 -43
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_oblique.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_side.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/S06_bumpy_wide_loop/preview_top.png +0 -0
- trenchfoot-0.1.1/packages/trenchfoot/scenarios/SUMMARY.json +0 -159
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/.github/workflows/ci.yml +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/.github_token.env +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/LICENSE +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/STATUS.md +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/__init__.py +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/Dockerfile +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/README.md +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/__init__.py +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/plot_mesh.py +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/render_colors.py +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/meshes/trench_scene_culled.obj +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/point_clouds/culled/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/point_clouds/full/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S01_straight_vwalls/preview.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/meshes/trench_scene_culled.obj +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/point_clouds/culled/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/point_clouds/full/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S02_straight_slope_pipe/preview.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/meshes/trench_scene_culled.obj +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/point_clouds/culled/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/point_clouds/full/resolution0p050.pth +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S03_L_slope_two_pipes_box/preview.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/meshes/trench_scene_culled.obj +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scenarios/S04_U_slope_multi_noise/preview.png +0 -0
- {trenchfoot-0.1.1 → trenchfoot-0.2.3}/packages/trenchfoot/scene_spec_example.json +0 -0
trenchfoot-0.2.3/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
PYPI_API_TOKEN=pypi-AgEIcHlwaS5vcmcCJGZjZTM1MzQwLTFiZGQtNGQ5MS1hNzIyLTc1MmU1YTJhYzE1NQACGFsxLFsicHl0ZXN0LWNocm9uaWNsZSJdXQACLFsyLFsiMzg4ZTYxZTMtMDk2NC00ZjNiLWE5ODItYzc4NTMxNDlhM2FjIl1dAAAGID45Pzb1Xm05EgS5M8C2_5BbgSEULSUwP3GpDCia6vTP
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.3] - 2025-12-20
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Closed path offset direction bug**: `_offset_closed_polyline` was using CCW rotation for normals, causing positive offsets to go inward instead of outward. Fixed to use CW rotation for correct outward-pointing normals on CCW polygons.
|
|
7
|
+
- **Circular well ground surface**: Removed incorrect center island from closed path ground surfaces. For circular wells, only the outer ground ring exists, leaving the trench opening completely open.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **Open-topped trench tests**: New tests to verify trenches are truly open (no geometry covering the trench opening):
|
|
11
|
+
- `test_trench_opening_is_open_for_straight_trench`
|
|
12
|
+
- `test_circular_well_trench_opening_is_open`
|
|
13
|
+
- `test_ground_surface_annular_structure`
|
|
14
|
+
|
|
15
|
+
## [0.2.2] - 2025-12-20
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Closed path handling for S07 circular well**: Explicitly close the circular path by repeating the first point. The previous heuristic was incorrectly detecting L-shaped and U-shaped paths as closed.
|
|
19
|
+
- **Volumetric meshing for closed paths**: Added proper annular geometry support to the gmsh mesher for closed circular paths with outer and inner walls.
|
|
20
|
+
|
|
21
|
+
## [0.2.1] - 2025-12-20
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- **Annular triangulation bug**: Ground plane was incorrectly filling in the trench opening with triangles instead of leaving it as a hole. Replaced bridge+ear-clipping algorithm with proper annular triangulation that "zips" around both polygon boundaries.
|
|
25
|
+
|
|
26
|
+
## [0.2.0] - 2025-12-19
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- **S07 circular well scenario**: Deep cylindrical well with 4 criss-crossing pipes at different elevations and diameters
|
|
30
|
+
- **Offset polygon ground plane**: Ground surface now follows trench outline instead of axis-aligned bounding box, reducing wasted space for L-shaped, U-shaped, and curved trenches
|
|
31
|
+
- **Open-topped trenches**: Trench cap (`trench_cap_for_volume`) is kept internally for metrics calculations but excluded from OBJ export and preview renders
|
|
32
|
+
- New tests for cap exclusion, offset ground, and circular well scenario
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- **Shallower trench depths**: All scenarios adjusted to be less extreme (S01: 0.6m, S02: 0.9m, S03: 1.1m, S04: 1.2m, S05: 0.7m, S06: 0.85m)
|
|
36
|
+
- Reduced ground `size_margin` values to work better with offset polygon ground
|
|
37
|
+
- Pipe z-positions adjusted proportionally to fit within shallower trenches
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
- Ground plane no longer wastes space on flat areas away from the trench path
|
|
41
|
+
|
|
42
|
+
## [0.1.1] - 2025-10-30
|
|
43
|
+
|
|
44
|
+
- CI hardening for PyPI token handling
|
|
45
|
+
- Initial PyPI release
|
|
46
|
+
|
|
47
|
+
## [0.1.0] - 2025-10-30
|
|
48
|
+
|
|
49
|
+
- Initial release with surface and volumetric mesh generation
|
|
50
|
+
- Scenarios S01-S06 with increasing complexity
|
|
51
|
+
- Plotly HTML viewer support
|
|
52
|
+
- Python SDK with `generate_surface_mesh()` and `generate_trench_volume()`
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Trenchfoot is a synthetic trench mesh generator that produces surface meshes (OBJ) and volumetric meshes (via Gmsh). It generates semi-realistic trench scenes with embedded pipes, boxes, and spheres, useful for creating synthetic datasets.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Install with uv (development)
|
|
13
|
+
uv pip install -e ".[dev,preview,mesher,viz]"
|
|
14
|
+
|
|
15
|
+
# Run tests
|
|
16
|
+
uv run pytest -rs
|
|
17
|
+
|
|
18
|
+
# Run a single test
|
|
19
|
+
uv run pytest tests/test_trenchfoot_generation.py::test_build_scene_produces_surface -v
|
|
20
|
+
|
|
21
|
+
# Generate scenario previews (writes to TRENCHFOOT_SCENARIO_OUT_ROOT or packages/trenchfoot/scenarios/)
|
|
22
|
+
uv run python -m trenchfoot.generate_scenarios --preview --skip-volumetric
|
|
23
|
+
|
|
24
|
+
# Generate with volumetric meshes (requires gmsh)
|
|
25
|
+
uv run python -m trenchfoot.generate_scenarios --volumetric --lc 0.4
|
|
26
|
+
|
|
27
|
+
# Generate gallery markdown
|
|
28
|
+
uv run python -m trenchfoot.generate_scenarios --preview --skip-volumetric --gallery docs/scenario_gallery.md
|
|
29
|
+
|
|
30
|
+
# Interactive Plotly mesh viewer (requires viz extra)
|
|
31
|
+
trenchfoot-plot path/to/trench_scene.obj --open
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Set `TRENCHFOOT_SCENARIO_OUT_ROOT=/tmp/trench-previews` to keep generated assets out of the repository.
|
|
35
|
+
|
|
36
|
+
## Architecture
|
|
37
|
+
|
|
38
|
+
The package lives in `packages/trenchfoot/` with these core modules:
|
|
39
|
+
|
|
40
|
+
- **`trench_scene_generator_v3.py`**: Surface mesh generator. Produces OBJ files with polyline trenches, sloped walls, ground planes, and embedded geometry (pipes/boxes/spheres). Handles noise application and preview rendering. Key types: `SceneSpec`, `SurfaceMeshResult`.
|
|
41
|
+
|
|
42
|
+
- **`gmsh_sloped_trench_mesher.py`**: Volumetric mesher using Gmsh. Creates tetrahedral meshes with physical groups (`TrenchAir`, `Pipe0`, etc.). Has adaptive clearance logic that scales guard bands based on pipe radius and wall slope. Key types: `VolumeMeshResult`.
|
|
43
|
+
|
|
44
|
+
- **`generate_scenarios.py`**: CLI and scenario runner. Defines preset scenarios (S01-S06) and orchestrates both surface and volumetric generation. Handles gallery markdown output and SUMMARY.json diagnostics.
|
|
45
|
+
|
|
46
|
+
- **`__init__.py`**: Public API exports. Gracefully handles missing gmsh dependency.
|
|
47
|
+
|
|
48
|
+
## Scene Specification
|
|
49
|
+
|
|
50
|
+
Trenches are defined by JSON specs with:
|
|
51
|
+
- `path_xy`: 2D polyline defining trench centerline
|
|
52
|
+
- `width`, `depth`, `wall_slope`: Cross-section parameters
|
|
53
|
+
- `ground`: Elevation, slope, and margin for ground plane
|
|
54
|
+
- `pipes`, `boxes`, `spheres`: Embedded objects positioned along the trench
|
|
55
|
+
- `noise`: Perlin-style surface perturbation settings
|
|
56
|
+
|
|
57
|
+
Objects use `s` or `s_center` (0-1 arc-length parameter) to position along the trench path.
|
|
58
|
+
|
|
59
|
+
## Optional Dependencies
|
|
60
|
+
|
|
61
|
+
- `[preview]` - matplotlib for PNG previews
|
|
62
|
+
- `[mesher]` - gmsh for volumetric mesh generation
|
|
63
|
+
- `[viz]` - plotly for interactive HTML viewers
|
|
64
|
+
- `[dev]` - pytest
|
|
65
|
+
|
|
66
|
+
## Testing Notes
|
|
67
|
+
|
|
68
|
+
Tests skip volumetric tests if gmsh runtime prerequisites (e.g., libGLU) are unavailable. The `_require_gmsh_runtime()` helper handles this gracefully.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trenchfoot
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Synthetic trench scenario generator bundle (surfaces + volumetrics).
|
|
5
5
|
Author: Liam Moore
|
|
6
6
|
License-File: LICENSE
|
|
@@ -43,29 +43,27 @@ Color key: trench surfaces use warm soil tones; embedded geometry is colour-code
|
|
|
43
43
|
| S04_U_slope_multi_noise |  |  |  |
|
|
44
44
|
| S05_wide_slope_pair |  |  |  |
|
|
45
45
|
| S06_bumpy_wide_loop |  |  |  |
|
|
46
|
+
| S07_circular_well |  |  |  |
|
|
46
47
|
|
|
47
|
-
###
|
|
48
|
+
### S07 circular well preset
|
|
49
|
+
|
|
50
|
+
A deep cylindrical well with criss-crossing pipes at different elevations:
|
|
48
51
|
|
|
49
52
|
```json
|
|
50
53
|
{
|
|
51
|
-
"path_xy":
|
|
52
|
-
"width": 2.
|
|
53
|
-
"depth":
|
|
54
|
-
"wall_slope": 0.
|
|
55
|
-
"ground": {"z0": 0.
|
|
54
|
+
"path_xy": "<<32-vertex circle approximation, radius=1.5>>",
|
|
55
|
+
"width": 2.0,
|
|
56
|
+
"depth": 2.5,
|
|
57
|
+
"wall_slope": 0.05,
|
|
58
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 2.0},
|
|
56
59
|
"pipes": [
|
|
57
|
-
{"radius": 0.
|
|
58
|
-
{"radius": 0.
|
|
60
|
+
{"radius": 0.20, "length": 4.0, "angle_deg": 0, "s_center": 0.25, "z": -0.5},
|
|
61
|
+
{"radius": 0.15, "length": 3.5, "angle_deg": 45, "s_center": 0.5, "z": -1.2},
|
|
62
|
+
{"radius": 0.10, "length": 3.0, "angle_deg": -60, "s_center": 0.75, "z": -1.8},
|
|
63
|
+
{"radius": 0.12, "length": 3.2, "angle_deg": 90, "s_center": 0.0, "z": -2.2}
|
|
59
64
|
],
|
|
60
|
-
"spheres": [{"radius": 0.
|
|
61
|
-
"noise": {
|
|
62
|
-
"enable": true,
|
|
63
|
-
"amplitude": 0.035,
|
|
64
|
-
"corr_length": 0.5,
|
|
65
|
-
"octaves": 4,
|
|
66
|
-
"gain": 0.55,
|
|
67
|
-
"apply_to": ["trench_walls", "trench_bottom", "pipe*_pipe_side"]
|
|
68
|
-
}
|
|
65
|
+
"spheres": [{"radius": 0.25, "s": 0.4, "z": -1.5}],
|
|
66
|
+
"noise": {"enable": true, "amplitude": 0.02, "corr_length": 0.4, "octaves": 2, "gain": 0.5}
|
|
69
67
|
}
|
|
70
68
|
```
|
|
71
69
|
|
|
@@ -25,29 +25,27 @@ Color key: trench surfaces use warm soil tones; embedded geometry is colour-code
|
|
|
25
25
|
| S04_U_slope_multi_noise |  |  |  |
|
|
26
26
|
| S05_wide_slope_pair |  |  |  |
|
|
27
27
|
| S06_bumpy_wide_loop |  |  |  |
|
|
28
|
+
| S07_circular_well |  |  |  |
|
|
28
29
|
|
|
29
|
-
###
|
|
30
|
+
### S07 circular well preset
|
|
31
|
+
|
|
32
|
+
A deep cylindrical well with criss-crossing pipes at different elevations:
|
|
30
33
|
|
|
31
34
|
```json
|
|
32
35
|
{
|
|
33
|
-
"path_xy":
|
|
34
|
-
"width": 2.
|
|
35
|
-
"depth":
|
|
36
|
-
"wall_slope": 0.
|
|
37
|
-
"ground": {"z0": 0.
|
|
36
|
+
"path_xy": "<<32-vertex circle approximation, radius=1.5>>",
|
|
37
|
+
"width": 2.0,
|
|
38
|
+
"depth": 2.5,
|
|
39
|
+
"wall_slope": 0.05,
|
|
40
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 2.0},
|
|
38
41
|
"pipes": [
|
|
39
|
-
{"radius": 0.
|
|
40
|
-
{"radius": 0.
|
|
42
|
+
{"radius": 0.20, "length": 4.0, "angle_deg": 0, "s_center": 0.25, "z": -0.5},
|
|
43
|
+
{"radius": 0.15, "length": 3.5, "angle_deg": 45, "s_center": 0.5, "z": -1.2},
|
|
44
|
+
{"radius": 0.10, "length": 3.0, "angle_deg": -60, "s_center": 0.75, "z": -1.8},
|
|
45
|
+
{"radius": 0.12, "length": 3.2, "angle_deg": 90, "s_center": 0.0, "z": -2.2}
|
|
41
46
|
],
|
|
42
|
-
"spheres": [{"radius": 0.
|
|
43
|
-
"noise": {
|
|
44
|
-
"enable": true,
|
|
45
|
-
"amplitude": 0.035,
|
|
46
|
-
"corr_length": 0.5,
|
|
47
|
-
"octaves": 4,
|
|
48
|
-
"gain": 0.55,
|
|
49
|
-
"apply_to": ["trench_walls", "trench_bottom", "pipe*_pipe_side"]
|
|
50
|
-
}
|
|
47
|
+
"spheres": [{"radius": 0.25, "s": 0.4, "z": -1.5}],
|
|
48
|
+
"noise": {"enable": true, "amplitude": 0.02, "corr_length": 0.4, "octaves": 2, "gain": 0.5}
|
|
51
49
|
}
|
|
52
50
|
```
|
|
53
51
|
|
|
@@ -6,3 +6,4 @@
|
|
|
6
6
|
| S04_U_slope_multi_noise |  |  |  |
|
|
7
7
|
| S05_wide_slope_pair |  |  |  |
|
|
8
8
|
| S06_bumpy_wide_loop |  |  |  |
|
|
9
|
+
| S07_circular_well |  |  |  |
|
|
@@ -135,18 +135,35 @@ def gmsh_available() -> bool:
|
|
|
135
135
|
return _gmsh_mesher is not None
|
|
136
136
|
|
|
137
137
|
|
|
138
|
+
def _generate_circular_path(
|
|
139
|
+
center: tuple[float, float], radius: float, n_vertices: int = 32
|
|
140
|
+
) -> List[List[float]]:
|
|
141
|
+
"""Generate vertices for a closed circular polyline.
|
|
142
|
+
|
|
143
|
+
The path is explicitly closed by repeating the first point at the end.
|
|
144
|
+
This ensures proper handling as a closed loop in mesh generation.
|
|
145
|
+
"""
|
|
146
|
+
import math
|
|
147
|
+
cx, cy = center
|
|
148
|
+
angles = [2 * math.pi * i / n_vertices for i in range(n_vertices)]
|
|
149
|
+
points = [[cx + radius * math.cos(a), cy + radius * math.sin(a)] for a in angles]
|
|
150
|
+
# Close the path by repeating the first point
|
|
151
|
+
points.append(points[0].copy())
|
|
152
|
+
return points
|
|
153
|
+
|
|
154
|
+
|
|
138
155
|
def default_scenarios() -> List[ScenarioDefinition]:
|
|
139
|
-
"""Built-in scenario presets."""
|
|
156
|
+
"""Built-in scenario presets with shallower depths and offset polygon ground."""
|
|
140
157
|
return [
|
|
141
158
|
ScenarioDefinition(
|
|
142
159
|
"S01_straight_vwalls",
|
|
143
160
|
{
|
|
144
161
|
"path_xy": [[0, 0], [5, 0]],
|
|
145
162
|
"width": 1.0,
|
|
146
|
-
"depth":
|
|
163
|
+
"depth": 0.6,
|
|
147
164
|
"wall_slope": 0.0,
|
|
148
165
|
"ground_margin": 0.5,
|
|
149
|
-
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin":
|
|
166
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 1.0},
|
|
150
167
|
"pipes": [],
|
|
151
168
|
"boxes": [],
|
|
152
169
|
"spheres": [],
|
|
@@ -158,17 +175,17 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
158
175
|
{
|
|
159
176
|
"path_xy": [[0, 0], [6, 0]],
|
|
160
177
|
"width": 1.2,
|
|
161
|
-
"depth":
|
|
178
|
+
"depth": 0.9,
|
|
162
179
|
"wall_slope": 0.2,
|
|
163
180
|
"ground_margin": 0.5,
|
|
164
|
-
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin":
|
|
181
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 1.0},
|
|
165
182
|
"pipes": [
|
|
166
183
|
{
|
|
167
184
|
"radius": 0.15,
|
|
168
185
|
"length": 7.0,
|
|
169
186
|
"angle_deg": 0,
|
|
170
187
|
"s_center": 0.5,
|
|
171
|
-
"z": -0.
|
|
188
|
+
"z": -0.45,
|
|
172
189
|
"offset_u": 0.0,
|
|
173
190
|
}
|
|
174
191
|
],
|
|
@@ -182,17 +199,17 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
182
199
|
{
|
|
183
200
|
"path_xy": [[0, 0], [6, 0], [6, 4]],
|
|
184
201
|
"width": 1.2,
|
|
185
|
-
"depth": 1.
|
|
202
|
+
"depth": 1.1,
|
|
186
203
|
"wall_slope": 0.15,
|
|
187
204
|
"ground_margin": 1.0,
|
|
188
|
-
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin":
|
|
205
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 1.2},
|
|
189
206
|
"pipes": [
|
|
190
207
|
{
|
|
191
208
|
"radius": 0.15,
|
|
192
209
|
"length": 8.0,
|
|
193
210
|
"angle_deg": 0,
|
|
194
211
|
"s_center": 0.35,
|
|
195
|
-
"z": -
|
|
212
|
+
"z": -0.6,
|
|
196
213
|
"offset_u": 0.0,
|
|
197
214
|
},
|
|
198
215
|
{
|
|
@@ -200,7 +217,7 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
200
217
|
"length": 5.0,
|
|
201
218
|
"angle_deg": 90,
|
|
202
219
|
"s_center": 0.75,
|
|
203
|
-
"z": -0.
|
|
220
|
+
"z": -0.55,
|
|
204
221
|
"offset_u": 0.2,
|
|
205
222
|
},
|
|
206
223
|
],
|
|
@@ -230,17 +247,17 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
230
247
|
{
|
|
231
248
|
"path_xy": [[0, 0], [6, 0], [6, 4], [0, 4]],
|
|
232
249
|
"width": 1.4,
|
|
233
|
-
"depth": 2
|
|
250
|
+
"depth": 1.2,
|
|
234
251
|
"wall_slope": 0.25,
|
|
235
252
|
"ground_margin": 1.2,
|
|
236
|
-
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 5
|
|
253
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 1.5},
|
|
237
254
|
"pipes": [
|
|
238
255
|
{
|
|
239
256
|
"radius": 0.18,
|
|
240
257
|
"length": 9.0,
|
|
241
258
|
"angle_deg": 0,
|
|
242
259
|
"s_center": 0.25,
|
|
243
|
-
"z": -
|
|
260
|
+
"z": -0.6,
|
|
244
261
|
"offset_u": 0.0,
|
|
245
262
|
},
|
|
246
263
|
{
|
|
@@ -248,7 +265,7 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
248
265
|
"length": 5.0,
|
|
249
266
|
"angle_deg": 45,
|
|
250
267
|
"s_center": 0.55,
|
|
251
|
-
"z": -
|
|
268
|
+
"z": -0.65,
|
|
252
269
|
"offset_u": -0.2,
|
|
253
270
|
},
|
|
254
271
|
{
|
|
@@ -256,12 +273,12 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
256
273
|
"length": 3.5,
|
|
257
274
|
"angle_deg": -60,
|
|
258
275
|
"s_center": 0.75,
|
|
259
|
-
"z": -
|
|
276
|
+
"z": -0.8,
|
|
260
277
|
"offset_u": 0.25,
|
|
261
278
|
},
|
|
262
279
|
],
|
|
263
280
|
"boxes": [],
|
|
264
|
-
"spheres": [{"radius": 0.
|
|
281
|
+
"spheres": [{"radius": 0.25, "s": 0.85, "offset_u": -0.2, "z": -0.7}],
|
|
265
282
|
"noise": {
|
|
266
283
|
"enable": True,
|
|
267
284
|
"amplitude": 0.02,
|
|
@@ -278,17 +295,17 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
278
295
|
{
|
|
279
296
|
"path_xy": [[0, 0], [9, 0], [9, 3]],
|
|
280
297
|
"width": 2.4,
|
|
281
|
-
"depth":
|
|
298
|
+
"depth": 0.7,
|
|
282
299
|
"wall_slope": 0.08,
|
|
283
300
|
"ground_margin": 1.5,
|
|
284
|
-
"ground": {"z0": 0.0, "slope": [0.02, -0.015], "size_margin":
|
|
301
|
+
"ground": {"z0": 0.0, "slope": [0.02, -0.015], "size_margin": 1.5},
|
|
285
302
|
"pipes": [
|
|
286
303
|
{
|
|
287
304
|
"radius": 0.2,
|
|
288
305
|
"length": 5.5,
|
|
289
306
|
"angle_deg": 10,
|
|
290
307
|
"s_center": 0.35,
|
|
291
|
-
"z": -0.
|
|
308
|
+
"z": -0.4,
|
|
292
309
|
"offset_u": 0.3,
|
|
293
310
|
"clearance_scale": 0.9,
|
|
294
311
|
},
|
|
@@ -297,7 +314,7 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
297
314
|
"length": 4.2,
|
|
298
315
|
"angle_deg": -15,
|
|
299
316
|
"s_center": 0.7,
|
|
300
|
-
"z": -0.
|
|
317
|
+
"z": -0.45,
|
|
301
318
|
"offset_u": -0.4,
|
|
302
319
|
"clearance_scale": 1.1,
|
|
303
320
|
},
|
|
@@ -306,10 +323,10 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
306
323
|
{
|
|
307
324
|
"along": 1.2,
|
|
308
325
|
"across": 0.9,
|
|
309
|
-
"height": 0.
|
|
326
|
+
"height": 0.35,
|
|
310
327
|
"s": 0.55,
|
|
311
328
|
"offset_u": -0.25,
|
|
312
|
-
"z": -0.
|
|
329
|
+
"z": -0.35,
|
|
313
330
|
}
|
|
314
331
|
],
|
|
315
332
|
"spheres": [],
|
|
@@ -329,17 +346,17 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
329
346
|
{
|
|
330
347
|
"path_xy": [[0, 0], [4, -1], [8, 0], [8, 5], [2, 5], [-1, 2]],
|
|
331
348
|
"width": 2.6,
|
|
332
|
-
"depth":
|
|
349
|
+
"depth": 0.85,
|
|
333
350
|
"wall_slope": 0.12,
|
|
334
351
|
"ground_margin": 2.0,
|
|
335
|
-
"ground": {"z0": 0.2, "slope": [0.015, 0.03], "size_margin":
|
|
352
|
+
"ground": {"z0": 0.2, "slope": [0.015, 0.03], "size_margin": 1.8},
|
|
336
353
|
"pipes": [
|
|
337
354
|
{
|
|
338
355
|
"radius": 0.18,
|
|
339
356
|
"length": 6.0,
|
|
340
357
|
"angle_deg": 35,
|
|
341
358
|
"s_center": 0.3,
|
|
342
|
-
"z": -0.
|
|
359
|
+
"z": -0.55,
|
|
343
360
|
"offset_u": 0.35,
|
|
344
361
|
"clearance_scale": 1.0,
|
|
345
362
|
},
|
|
@@ -348,14 +365,14 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
348
365
|
"length": 4.8,
|
|
349
366
|
"angle_deg": -40,
|
|
350
367
|
"s_center": 0.6,
|
|
351
|
-
"z": -0.
|
|
368
|
+
"z": -0.6,
|
|
352
369
|
"offset_u": -0.45,
|
|
353
370
|
"clearance_scale": 0.85,
|
|
354
371
|
},
|
|
355
372
|
],
|
|
356
373
|
"boxes": [],
|
|
357
374
|
"spheres": [
|
|
358
|
-
{"radius": 0.
|
|
375
|
+
{"radius": 0.3, "s": 0.82, "offset_u": 0.3, "z": -0.4}
|
|
359
376
|
],
|
|
360
377
|
"noise": {
|
|
361
378
|
"enable": True,
|
|
@@ -368,6 +385,66 @@ def default_scenarios() -> List[ScenarioDefinition]:
|
|
|
368
385
|
},
|
|
369
386
|
},
|
|
370
387
|
),
|
|
388
|
+
ScenarioDefinition(
|
|
389
|
+
"S07_circular_well",
|
|
390
|
+
{
|
|
391
|
+
"path_xy": _generate_circular_path((0.0, 0.0), radius=1.5, n_vertices=32),
|
|
392
|
+
"width": 2.0,
|
|
393
|
+
"depth": 2.5,
|
|
394
|
+
"wall_slope": 0.05,
|
|
395
|
+
"ground_margin": 1.0,
|
|
396
|
+
"ground": {"z0": 0.0, "slope": [0.0, 0.0], "size_margin": 2.0},
|
|
397
|
+
"pipes": [
|
|
398
|
+
# Upper pipe - large diameter, horizontal
|
|
399
|
+
{
|
|
400
|
+
"radius": 0.20,
|
|
401
|
+
"length": 4.0,
|
|
402
|
+
"angle_deg": 0,
|
|
403
|
+
"s_center": 0.25,
|
|
404
|
+
"z": -0.5,
|
|
405
|
+
"offset_u": 0.0,
|
|
406
|
+
},
|
|
407
|
+
# Middle pipe - medium, angled
|
|
408
|
+
{
|
|
409
|
+
"radius": 0.15,
|
|
410
|
+
"length": 3.5,
|
|
411
|
+
"angle_deg": 45,
|
|
412
|
+
"s_center": 0.5,
|
|
413
|
+
"z": -1.2,
|
|
414
|
+
"offset_u": 0.1,
|
|
415
|
+
},
|
|
416
|
+
# Lower pipe - small, opposite angle
|
|
417
|
+
{
|
|
418
|
+
"radius": 0.10,
|
|
419
|
+
"length": 3.0,
|
|
420
|
+
"angle_deg": -60,
|
|
421
|
+
"s_center": 0.75,
|
|
422
|
+
"z": -1.8,
|
|
423
|
+
"offset_u": -0.15,
|
|
424
|
+
},
|
|
425
|
+
# Deep pipe - crossing at bottom
|
|
426
|
+
{
|
|
427
|
+
"radius": 0.12,
|
|
428
|
+
"length": 3.2,
|
|
429
|
+
"angle_deg": 90,
|
|
430
|
+
"s_center": 0.0,
|
|
431
|
+
"z": -2.2,
|
|
432
|
+
"offset_u": 0.0,
|
|
433
|
+
},
|
|
434
|
+
],
|
|
435
|
+
"boxes": [],
|
|
436
|
+
"spheres": [{"radius": 0.25, "s": 0.4, "offset_u": 0.0, "z": -1.5}],
|
|
437
|
+
"noise": {
|
|
438
|
+
"enable": True,
|
|
439
|
+
"amplitude": 0.02,
|
|
440
|
+
"corr_length": 0.4,
|
|
441
|
+
"octaves": 2,
|
|
442
|
+
"gain": 0.5,
|
|
443
|
+
"seed": 37,
|
|
444
|
+
"apply_to": ["trench_walls", "trench_bottom"],
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
),
|
|
371
448
|
]
|
|
372
449
|
|
|
373
450
|
|