dcel-map-generator 0.2.2__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.
- dcel_map_generator-0.2.2/.github/workflows/deploy-pages.yml +52 -0
- dcel_map_generator-0.2.2/.github/workflows/release.yml +180 -0
- dcel_map_generator-0.2.2/.github/workflows/semver-release.yml +56 -0
- dcel_map_generator-0.2.2/.gitignore +68 -0
- dcel_map_generator-0.2.2/AGENTS.md +23 -0
- dcel_map_generator-0.2.2/LICENSE +21 -0
- dcel_map_generator-0.2.2/PKG-INFO +164 -0
- dcel_map_generator-0.2.2/README.md +148 -0
- dcel_map_generator-0.2.2/conftest.py +29 -0
- dcel_map_generator-0.2.2/dcel_builder/__init__.py +130 -0
- dcel_map_generator-0.2.2/dcel_builder/__main__.py +212 -0
- dcel_map_generator-0.2.2/dcel_builder/dcel.py +174 -0
- dcel_map_generator-0.2.2/dcel_builder/frontend_bundle.py +184 -0
- dcel_map_generator-0.2.2/dcel_builder/geometry.py +20 -0
- dcel_map_generator-0.2.2/dcel_builder/hierarchy.py +553 -0
- dcel_map_generator-0.2.2/dcel_builder/noise.py +89 -0
- dcel_map_generator-0.2.2/dcel_builder/raster_dcel.py +252 -0
- dcel_map_generator-0.2.2/dcel_builder/render.py +107 -0
- dcel_map_generator-0.2.2/dcel_builder/serializer.py +99 -0
- dcel_map_generator-0.2.2/dcel_builder/tree_loader.py +146 -0
- dcel_map_generator-0.2.2/docs/atlantis-map.png +0 -0
- dcel_map_generator-0.2.2/examples/atlantis/zone_edges.json +30 -0
- dcel_map_generator-0.2.2/examples/atlantis/zone_index.json +31 -0
- dcel_map_generator-0.2.2/examples/atlantis/zone_tree_stats.json +20 -0
- dcel_map_generator-0.2.2/frontend/index.html +12 -0
- dcel_map_generator-0.2.2/frontend/package-lock.json +2599 -0
- dcel_map_generator-0.2.2/frontend/package.json +41 -0
- dcel_map_generator-0.2.2/frontend/public/.gitkeep +1 -0
- dcel_map_generator-0.2.2/frontend/public/map_bundle.json +1473 -0
- dcel_map_generator-0.2.2/frontend/src/App.tsx +41 -0
- dcel_map_generator-0.2.2/frontend/src/MapView.tsx +513 -0
- dcel_map_generator-0.2.2/frontend/src/animations.ts +9 -0
- dcel_map_generator-0.2.2/frontend/src/bundle.ts +52 -0
- dcel_map_generator-0.2.2/frontend/src/index.ts +12 -0
- dcel_map_generator-0.2.2/frontend/src/main.tsx +10 -0
- dcel_map_generator-0.2.2/frontend/src/styles.css +177 -0
- dcel_map_generator-0.2.2/frontend/src/types.ts +57 -0
- dcel_map_generator-0.2.2/frontend/src/vite-env.d.ts +1 -0
- dcel_map_generator-0.2.2/frontend/tsconfig.json +21 -0
- dcel_map_generator-0.2.2/frontend/tsconfig.lib.json +10 -0
- dcel_map_generator-0.2.2/frontend/vite.config.ts +16 -0
- dcel_map_generator-0.2.2/frontend/vite.lib.config.ts +20 -0
- dcel_map_generator-0.2.2/pyproject.toml +44 -0
- dcel_map_generator-0.2.2/scripts/semver_release.py +169 -0
- dcel_map_generator-0.2.2/tests/__init__.py +0 -0
- dcel_map_generator-0.2.2/tests/integration/__init__.py +0 -0
- dcel_map_generator-0.2.2/tests/integration/test_cli.py +322 -0
- dcel_map_generator-0.2.2/tests/integration/test_pipeline.py +85 -0
- dcel_map_generator-0.2.2/tests/unit/__init__.py +0 -0
- dcel_map_generator-0.2.2/tests/unit/test_dcel.py +137 -0
- dcel_map_generator-0.2.2/tests/unit/test_frontend_bundle.py +75 -0
- dcel_map_generator-0.2.2/tests/unit/test_hierarchy.py +101 -0
- dcel_map_generator-0.2.2/tests/unit/test_package_metadata.py +29 -0
- dcel_map_generator-0.2.2/tests/unit/test_render.py +36 -0
- dcel_map_generator-0.2.2/tests/unit/test_semver_release.py +57 -0
- dcel_map_generator-0.2.2/tests/unit/test_serializer.py +140 -0
- dcel_map_generator-0.2.2/tests/unit/test_tree_loader.py +56 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Deploy Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
environment:
|
|
21
|
+
name: github-pages
|
|
22
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Setup Node
|
|
28
|
+
uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: "22"
|
|
31
|
+
cache: npm
|
|
32
|
+
cache-dependency-path: frontend/package-lock.json
|
|
33
|
+
|
|
34
|
+
- name: Install frontend dependencies
|
|
35
|
+
working-directory: frontend
|
|
36
|
+
run: npm ci
|
|
37
|
+
|
|
38
|
+
- name: Build frontend
|
|
39
|
+
working-directory: frontend
|
|
40
|
+
run: npm run build
|
|
41
|
+
|
|
42
|
+
- name: Setup Pages
|
|
43
|
+
uses: actions/configure-pages@v5
|
|
44
|
+
|
|
45
|
+
- name: Upload artifact
|
|
46
|
+
uses: actions/upload-pages-artifact@v3
|
|
47
|
+
with:
|
|
48
|
+
path: frontend/dist
|
|
49
|
+
|
|
50
|
+
- name: Deploy to GitHub Pages
|
|
51
|
+
id: deployment
|
|
52
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Setup Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Setup uv
|
|
26
|
+
uses: astral-sh/setup-uv@v4
|
|
27
|
+
|
|
28
|
+
- name: Setup Node
|
|
29
|
+
uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: "22"
|
|
32
|
+
cache: npm
|
|
33
|
+
cache-dependency-path: frontend/package-lock.json
|
|
34
|
+
|
|
35
|
+
- name: Verify release tag matches package version
|
|
36
|
+
run: |
|
|
37
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
38
|
+
PY_VERSION="$(python - <<'PY'
|
|
39
|
+
import tomllib
|
|
40
|
+
with open("pyproject.toml", "rb") as fh:
|
|
41
|
+
print(tomllib.load(fh)["project"]["version"])
|
|
42
|
+
PY
|
|
43
|
+
)"
|
|
44
|
+
FRONTEND_VERSION="$(python - <<'PY'
|
|
45
|
+
import json
|
|
46
|
+
with open("frontend/package.json", "r", encoding="utf-8") as fh:
|
|
47
|
+
print(json.load(fh)["version"])
|
|
48
|
+
PY
|
|
49
|
+
)"
|
|
50
|
+
if [ "$TAG_VERSION" != "$PY_VERSION" ]; then
|
|
51
|
+
echo "Tag version $TAG_VERSION does not match pyproject version $PY_VERSION"
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
if [ "$TAG_VERSION" != "$FRONTEND_VERSION" ]; then
|
|
55
|
+
echo "Tag version $TAG_VERSION does not match frontend version $FRONTEND_VERSION"
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
- name: Install Python dependencies
|
|
60
|
+
run: uv sync --dev
|
|
61
|
+
|
|
62
|
+
- name: Run Python tests
|
|
63
|
+
run: uv run pytest
|
|
64
|
+
|
|
65
|
+
- name: Build Python distributions
|
|
66
|
+
run: uv build
|
|
67
|
+
|
|
68
|
+
- name: Install frontend dependencies
|
|
69
|
+
working-directory: frontend
|
|
70
|
+
run: npm ci
|
|
71
|
+
|
|
72
|
+
- name: Build frontend
|
|
73
|
+
working-directory: frontend
|
|
74
|
+
run: npm run build
|
|
75
|
+
|
|
76
|
+
- name: Prepare release artifact directory
|
|
77
|
+
run: mkdir -p release-artifacts
|
|
78
|
+
|
|
79
|
+
- name: Pack frontend npm package
|
|
80
|
+
working-directory: frontend
|
|
81
|
+
run: npm pack --pack-destination ../release-artifacts
|
|
82
|
+
|
|
83
|
+
- name: Create release archives
|
|
84
|
+
run: |
|
|
85
|
+
cp frontend/public/map_bundle.json release-artifacts/map_bundle.json
|
|
86
|
+
cp docs/atlantis-map.png release-artifacts/atlantis-map.png
|
|
87
|
+
tar -C frontend/dist -czf release-artifacts/frontend-dist.tar.gz .
|
|
88
|
+
tar -C examples -czf release-artifacts/atlantis-example-inputs.tar.gz atlantis
|
|
89
|
+
|
|
90
|
+
- name: Upload Python distributions
|
|
91
|
+
uses: actions/upload-artifact@v4
|
|
92
|
+
with:
|
|
93
|
+
name: python-dist
|
|
94
|
+
path: dist/*
|
|
95
|
+
|
|
96
|
+
- name: Upload frontend distribution
|
|
97
|
+
uses: actions/upload-artifact@v4
|
|
98
|
+
with:
|
|
99
|
+
name: frontend-dist
|
|
100
|
+
path: |
|
|
101
|
+
release-artifacts/frontend-dist.tar.gz
|
|
102
|
+
release-artifacts/*.tgz
|
|
103
|
+
|
|
104
|
+
- name: Upload example assets
|
|
105
|
+
uses: actions/upload-artifact@v4
|
|
106
|
+
with:
|
|
107
|
+
name: example-assets
|
|
108
|
+
path: |
|
|
109
|
+
release-artifacts/map_bundle.json
|
|
110
|
+
release-artifacts/atlantis-map.png
|
|
111
|
+
release-artifacts/atlantis-example-inputs.tar.gz
|
|
112
|
+
|
|
113
|
+
- name: Publish GitHub release
|
|
114
|
+
uses: softprops/action-gh-release@v2
|
|
115
|
+
with:
|
|
116
|
+
generate_release_notes: true
|
|
117
|
+
files: |
|
|
118
|
+
dist/*
|
|
119
|
+
release-artifacts/frontend-dist.tar.gz
|
|
120
|
+
release-artifacts/*.tgz
|
|
121
|
+
release-artifacts/map_bundle.json
|
|
122
|
+
release-artifacts/atlantis-map.png
|
|
123
|
+
release-artifacts/atlantis-example-inputs.tar.gz
|
|
124
|
+
|
|
125
|
+
publish-pypi:
|
|
126
|
+
name: Publish to PyPI
|
|
127
|
+
runs-on: ubuntu-latest
|
|
128
|
+
needs: release
|
|
129
|
+
environment:
|
|
130
|
+
name: pypi
|
|
131
|
+
permissions:
|
|
132
|
+
id-token: write
|
|
133
|
+
steps:
|
|
134
|
+
- name: Download Python distributions
|
|
135
|
+
uses: actions/download-artifact@v4
|
|
136
|
+
with:
|
|
137
|
+
name: python-dist
|
|
138
|
+
path: dist
|
|
139
|
+
|
|
140
|
+
- name: Publish package to PyPI
|
|
141
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
142
|
+
with:
|
|
143
|
+
packages-dir: dist
|
|
144
|
+
|
|
145
|
+
publish-npm:
|
|
146
|
+
name: Publish to npm
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
needs: release
|
|
149
|
+
environment:
|
|
150
|
+
name: npm
|
|
151
|
+
permissions:
|
|
152
|
+
contents: read
|
|
153
|
+
id-token: write
|
|
154
|
+
steps:
|
|
155
|
+
- name: Download frontend package artifact
|
|
156
|
+
uses: actions/download-artifact@v4
|
|
157
|
+
with:
|
|
158
|
+
name: frontend-dist
|
|
159
|
+
path: release-artifacts
|
|
160
|
+
|
|
161
|
+
- name: Setup Node
|
|
162
|
+
uses: actions/setup-node@v4
|
|
163
|
+
with:
|
|
164
|
+
node-version: "22"
|
|
165
|
+
registry-url: "https://registry.npmjs.org"
|
|
166
|
+
|
|
167
|
+
- name: Resolve frontend package tarball
|
|
168
|
+
id: frontend-package
|
|
169
|
+
run: |
|
|
170
|
+
shopt -s nullglob
|
|
171
|
+
tarballs=(release-artifacts/*.tgz)
|
|
172
|
+
if [ "${#tarballs[@]}" -ne 1 ]; then
|
|
173
|
+
echo "Expected exactly one frontend package tarball, found ${#tarballs[@]}"
|
|
174
|
+
ls -la release-artifacts
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
echo "path=./${tarballs[0]}" >> "$GITHUB_OUTPUT"
|
|
178
|
+
|
|
179
|
+
- name: Publish renderer package to npm
|
|
180
|
+
run: npm publish "${{ steps.frontend-package.outputs.path }}" --access public --provenance
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Semver Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: semver-release-main
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
version-and-tag:
|
|
17
|
+
if: github.actor != 'github-actions[bot]'
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
|
|
25
|
+
- name: Setup Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
|
|
30
|
+
- name: Determine next version
|
|
31
|
+
id: semver
|
|
32
|
+
run: python scripts/semver_release.py plan
|
|
33
|
+
|
|
34
|
+
- name: Stop when no release is needed
|
|
35
|
+
if: steps.semver.outputs.changed != 'true'
|
|
36
|
+
run: echo "No unreleased commits since the latest semantic version tag."
|
|
37
|
+
|
|
38
|
+
- name: Apply release version
|
|
39
|
+
if: steps.semver.outputs.changed == 'true'
|
|
40
|
+
run: python scripts/semver_release.py apply --version "${{ steps.semver.outputs.version }}"
|
|
41
|
+
|
|
42
|
+
- name: Commit and tag release
|
|
43
|
+
if: steps.semver.outputs.changed == 'true'
|
|
44
|
+
run: |
|
|
45
|
+
git config user.name "github-actions[bot]"
|
|
46
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
47
|
+
git add pyproject.toml dcel_builder/__init__.py frontend/package.json frontend/package-lock.json
|
|
48
|
+
git commit -m "Release v${{ steps.semver.outputs.version }}"
|
|
49
|
+
git tag "v${{ steps.semver.outputs.version }}"
|
|
50
|
+
git push origin main --follow-tags
|
|
51
|
+
|
|
52
|
+
- name: Trigger release workflow
|
|
53
|
+
if: steps.semver.outputs.changed == 'true'
|
|
54
|
+
env:
|
|
55
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
56
|
+
run: gh workflow run release.yml --ref "v${{ steps.semver.outputs.version }}"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.pyc
|
|
6
|
+
*.pyo
|
|
7
|
+
*.pyd
|
|
8
|
+
.Python
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
ENV/
|
|
15
|
+
|
|
16
|
+
# uv
|
|
17
|
+
.uv/
|
|
18
|
+
uv.lock
|
|
19
|
+
|
|
20
|
+
# Distribution / packaging
|
|
21
|
+
dist/
|
|
22
|
+
build/
|
|
23
|
+
node_modules/
|
|
24
|
+
frontend/dist-lib/
|
|
25
|
+
frontend/*.tgz
|
|
26
|
+
*.egg-info/
|
|
27
|
+
*.egg
|
|
28
|
+
.eggs/
|
|
29
|
+
|
|
30
|
+
# Testing
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.coverage
|
|
33
|
+
htmlcov/
|
|
34
|
+
.tox/
|
|
35
|
+
coverage.xml
|
|
36
|
+
*.cover
|
|
37
|
+
|
|
38
|
+
# Type checking
|
|
39
|
+
.mypy_cache/
|
|
40
|
+
.dmypy.json
|
|
41
|
+
*.tsbuildinfo
|
|
42
|
+
|
|
43
|
+
# Linting
|
|
44
|
+
.ruff_cache/
|
|
45
|
+
|
|
46
|
+
# IDE
|
|
47
|
+
.vscode/
|
|
48
|
+
.idea/
|
|
49
|
+
*.swp
|
|
50
|
+
*.swo
|
|
51
|
+
*.claude/
|
|
52
|
+
.claude/
|
|
53
|
+
|
|
54
|
+
# OS
|
|
55
|
+
.DS_Store
|
|
56
|
+
Thumbs.db
|
|
57
|
+
|
|
58
|
+
# Output files
|
|
59
|
+
dcel_map.json
|
|
60
|
+
dcel_map.png
|
|
61
|
+
debug_label_map.png
|
|
62
|
+
local/
|
|
63
|
+
scripts/__pycache__/
|
|
64
|
+
|
|
65
|
+
# Secrets / env
|
|
66
|
+
.env
|
|
67
|
+
.env.*
|
|
68
|
+
*.secret
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Repository Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Structure & Module Organization
|
|
4
|
+
`dcel_builder/` contains the application code and CLI entry point (`__main__.py`). The current runtime path is small: `tree_loader.py` validates the hierarchy input, `hierarchy.py` builds the recursive raster subdivision, `raster_dcel.py` converts the leaf raster into polygons/DCEL, and `render.py` produces preview PNGs. Core DCEL types and JSON I/O live in `dcel.py` and `serializer.py`. Tests are split into `tests/unit/` for module behavior and `tests/integration/` for CLI/pipeline coverage. Repository-root JSON files are the current sample inputs; generated outputs should stay untracked.
|
|
5
|
+
|
|
6
|
+
## Build, Test, and Development Commands
|
|
7
|
+
Use Python 3.11+.
|
|
8
|
+
|
|
9
|
+
- `uv sync --dev`: install runtime and development dependencies.
|
|
10
|
+
- `uv run pytest`: run the full test suite.
|
|
11
|
+
- `uv run pytest tests/unit/test_hierarchy.py`: run a focused unit test file while iterating.
|
|
12
|
+
- `uv run ruff check .`: lint imports and basic style issues.
|
|
13
|
+
- `uv run ruff format .`: apply formatting before opening a PR.
|
|
14
|
+
- `uv run python -m dcel_builder` or `uv run dcel-map`: run the CLI locally.
|
|
15
|
+
|
|
16
|
+
## Coding Style & Naming Conventions
|
|
17
|
+
Follow PEP 8 with 4-space indentation and a maximum line length of 100 characters, matching `ruff` settings in `pyproject.toml`. Use `snake_case` for modules, functions, variables, and test files; use `PascalCase` only for classes. Keep modules narrowly scoped by responsibility. Prefer explicit type-friendly function signatures and small pure helpers for geometry transforms.
|
|
18
|
+
|
|
19
|
+
## Testing Guidelines
|
|
20
|
+
Tests use `pytest` and are discovered from `tests/`. Name new files `test_<feature>.py` and new tests `test_<behavior>`. Add unit tests for deterministic logic and integration tests when CLI behavior, JSON I/O, or full pipeline assembly changes. Run `uv run pytest` before submitting changes; update or add fixture data only when behavior intentionally changes.
|
|
21
|
+
|
|
22
|
+
## Commit & Pull Request Guidelines
|
|
23
|
+
Recent history favors short, imperative commit subjects such as `Implement foundational modules`. Keep the first line concise and descriptive. Pull requests should explain the behavioral change, mention affected modules or specs, and note test coverage. Include sample command output or updated artifact references when CLI behavior or generated map outputs change.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alonso Cancino
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dcel-map-generator
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Generate a leaf-level DCEL map from a hierarchical zone tree
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: matplotlib>=3.10.8
|
|
8
|
+
Requires-Dist: networkx>=3.4
|
|
9
|
+
Requires-Dist: numpy>=1.26
|
|
10
|
+
Requires-Dist: scipy>=1.11
|
|
11
|
+
Requires-Dist: shapely>=2.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
14
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# DCEL Map Generator
|
|
18
|
+
|
|
19
|
+
Generate whimsical continent-style maps from a rooted hierarchy and export them as:
|
|
20
|
+
|
|
21
|
+
- a leaf-level DCEL
|
|
22
|
+
- a rendered preview image
|
|
23
|
+
- a frontend-ready bundle for an interactive zoomable map
|
|
24
|
+
|
|
25
|
+
This repo is the reusable core. Domain-specific map projects can keep their own hierarchy data and consume this generator/render stack.
|
|
26
|
+
|
|
27
|
+
[Live Demo](https://alonso-cancino.github.io/map-generator/)
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
## What It Does
|
|
32
|
+
|
|
33
|
+
The pipeline is tree-first:
|
|
34
|
+
|
|
35
|
+
1. load a rooted hierarchy from `examples/atlantis/zone_edges.json`
|
|
36
|
+
2. generate a continent mask
|
|
37
|
+
3. recursively partition each parent region among its children
|
|
38
|
+
4. extract leaf polygons from the raster partition
|
|
39
|
+
5. build a DCEL and optional frontend bundle
|
|
40
|
+
|
|
41
|
+
The bundled demo dataset is a small fantasy world centered on **Atlantis** so you can run the project immediately without bringing your own taxonomy first.
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
Requirements:
|
|
46
|
+
|
|
47
|
+
- Python 3.11+
|
|
48
|
+
- `uv`
|
|
49
|
+
- Node.js 20+ for the frontend demo
|
|
50
|
+
|
|
51
|
+
Install Python dependencies:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv sync --dev
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Generate the demo outputs:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv run python -m dcel_builder \
|
|
61
|
+
--zone-edges examples/atlantis/zone_edges.json \
|
|
62
|
+
--tree-stats examples/atlantis/zone_tree_stats.json \
|
|
63
|
+
--zone-index examples/atlantis/zone_index.json \
|
|
64
|
+
--output dcel_map.json \
|
|
65
|
+
--render \
|
|
66
|
+
--render-output docs/atlantis-map.png \
|
|
67
|
+
--frontend-bundle frontend/public/map_bundle.json \
|
|
68
|
+
--validate
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Run the interactive renderer locally:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd frontend
|
|
75
|
+
npm install
|
|
76
|
+
npm run dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Open `http://localhost:5173/`.
|
|
80
|
+
|
|
81
|
+
## Input Files
|
|
82
|
+
|
|
83
|
+
The generator expects three JSON files:
|
|
84
|
+
|
|
85
|
+
- `zone_edges.json`: directed `[parent, child]` pairs forming a rooted tree
|
|
86
|
+
- `zone_index.json`: `{ "id": "name" }` mapping used for labels/tooling
|
|
87
|
+
- `zone_tree_stats.json`: optional sidecar metadata; the generator currently tolerates an empty object
|
|
88
|
+
|
|
89
|
+
The bundled example describes a three-level fantasy continent:
|
|
90
|
+
|
|
91
|
+
- `Atlantis`
|
|
92
|
+
- major regions such as `Aurelia Reach`, `Tidehollow`, `Cinder Crown`, `Mistwood`
|
|
93
|
+
- smaller subregions and leaf territories beneath them
|
|
94
|
+
|
|
95
|
+
The tracked demo inputs live in [`examples/atlantis`](/home/alosc/proyectos/map/examples/atlantis). Private or domain-specific datasets can stay in ignored folders such as `local/`.
|
|
96
|
+
|
|
97
|
+
## Outputs
|
|
98
|
+
|
|
99
|
+
- `dcel_map.json`: serialized DCEL
|
|
100
|
+
- `docs/atlantis-map.png`: static render
|
|
101
|
+
- `frontend/public/map_bundle.json`: interactive bundle consumed by the frontend
|
|
102
|
+
|
|
103
|
+
## GitHub Pages Demo
|
|
104
|
+
|
|
105
|
+
The frontend is configured for GitHub Pages static hosting. A workflow in `.github/workflows/deploy-pages.yml` builds `frontend/` and publishes the interactive demo using the bundled Atlantis example.
|
|
106
|
+
|
|
107
|
+
## Versioning
|
|
108
|
+
|
|
109
|
+
This project uses Semantic Versioning and derives releases from commits on `main`.
|
|
110
|
+
|
|
111
|
+
- `BREAKING CHANGE` in a commit body, or `type!:` in the subject, increments `MAJOR`
|
|
112
|
+
- subjects starting with `feat`, `add`, or `implement` increment `MINOR`
|
|
113
|
+
- all other changes increment `PATCH`
|
|
114
|
+
|
|
115
|
+
The automation writes the chosen version into Python and frontend package metadata, commits `Release vX.Y.Z`, and creates the matching `vX.Y.Z` tag.
|
|
116
|
+
|
|
117
|
+
## Releases
|
|
118
|
+
|
|
119
|
+
Pushing to `main` triggers the semantic version workflow in `.github/workflows/semver-release.yml`. That workflow computes the next version, commits the versioned files, and pushes the matching release tag. The tag then triggers `.github/workflows/release.yml`.
|
|
120
|
+
|
|
121
|
+
Each release publishes consumable artifacts:
|
|
122
|
+
|
|
123
|
+
- Python source distribution and wheel from `dist/`
|
|
124
|
+
- a production frontend archive, `frontend-dist.tar.gz`
|
|
125
|
+
- an npm package tarball for the renderer, `alonso-cancino-dcel-map-frontend-<version>.tgz`
|
|
126
|
+
- the example frontend bundle, `map_bundle.json`
|
|
127
|
+
- the Atlantis example inputs as `atlantis-example-inputs.tar.gz`
|
|
128
|
+
- the demo screenshot, `atlantis-map.png`
|
|
129
|
+
|
|
130
|
+
You can consume the renderer package from npm by installing the published tarball, or later from the npm registry once it is published there. The library entrypoint exports `MapView`, `loadBundle`, `parseBundle`, and the bundle/type definitions.
|
|
131
|
+
|
|
132
|
+
When the repository is configured for trusted publishing, the same release workflow also publishes:
|
|
133
|
+
|
|
134
|
+
- the Python package to PyPI
|
|
135
|
+
- the renderer package to npm
|
|
136
|
+
|
|
137
|
+
### One-time registry setup
|
|
138
|
+
|
|
139
|
+
To make automated publishing work, you still need to configure each registry once:
|
|
140
|
+
|
|
141
|
+
1. PyPI:
|
|
142
|
+
Create the `dcel-map-generator` project on PyPI, then add a Trusted Publisher for this GitHub repository and the workflow file `release.yml`.
|
|
143
|
+
|
|
144
|
+
2. npm:
|
|
145
|
+
Create the `@alonso-cancino/dcel-map-frontend` package on npm, then add a Trusted Publisher for this GitHub repository and the workflow file `release.yml`.
|
|
146
|
+
|
|
147
|
+
3. GitHub:
|
|
148
|
+
If you want deployment protection, create `pypi` and `npm` environments in the repository settings to match the workflow.
|
|
149
|
+
|
|
150
|
+
After that, pushing to `main` will create the next semantic version release and publish both packages automatically.
|
|
151
|
+
|
|
152
|
+
## Development
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
uv run pytest
|
|
156
|
+
uv run ruff check .
|
|
157
|
+
cd frontend && npm run build
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Contributor conventions live in `AGENTS.md`.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT. See [LICENSE](LICENSE).
|