citygrid 0.1.0__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.
- citygrid-0.1.0/.gitignore +7 -0
- citygrid-0.1.0/LICENSE +21 -0
- citygrid-0.1.0/PKG-INFO +115 -0
- citygrid-0.1.0/README.md +92 -0
- citygrid-0.1.0/pyproject.toml +34 -0
- citygrid-0.1.0/src/citygrid/__init__.py +24 -0
- citygrid-0.1.0/src/citygrid/analytics.py +611 -0
- citygrid-0.1.0/src/citygrid/config.py +72 -0
- citygrid-0.1.0/src/citygrid/zones.py +488 -0
- citygrid-0.1.0/tests/test_analytics.py +99 -0
- citygrid-0.1.0/tests/test_zones.py +83 -0
citygrid-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joe Tan
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
citygrid-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: citygrid
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Zone classification, road generation, pathfinding, and urban analytics for a grid of buildings
|
|
5
|
+
Project-URL: Homepage, https://github.com/Joetankm/citygrid
|
|
6
|
+
Project-URL: Repository, https://github.com/Joetankm/citygrid
|
|
7
|
+
Project-URL: Issues, https://github.com/Joetankm/citygrid/issues
|
|
8
|
+
Author-email: Joe Tan <jtkmjoe@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: city-simulation,game-dev,gis,grid,pathfinding,urban-planning,walkability,zoning
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# citygrid
|
|
25
|
+
|
|
26
|
+
Zone classification, road generation, pathfinding, and urban analytics for
|
|
27
|
+
a grid of axis-aligned rectangular buildings.
|
|
28
|
+
|
|
29
|
+
Originally built for a physical LEGO-brick smart-city simulator, extracted
|
|
30
|
+
into a standalone library because the underlying logic — "given a bunch of
|
|
31
|
+
rectangles on a grid, classify zones, connect them with roads, and score
|
|
32
|
+
the layout" — is generic enough to be useful for city-builder games, urban
|
|
33
|
+
planning teaching tools, and GIS prototyping.
|
|
34
|
+
|
|
35
|
+
Zero required dependencies — pure Python, `math`/`heapq`/`dataclasses` only.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install citygrid
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## What it does
|
|
44
|
+
|
|
45
|
+
**Zoning** (`compute_zones`) — connected-component BFS groups nearby
|
|
46
|
+
buildings into blocks, then classifies each block as Residential,
|
|
47
|
+
Commercial, Industrial, or Mixed based on height/footprint mix; empty
|
|
48
|
+
areas become Green space.
|
|
49
|
+
|
|
50
|
+
**Roads** (`generate_roads`) — two-phase A* generates a closed-circuit
|
|
51
|
+
road network along zone-block faces, connecting every block without
|
|
52
|
+
cutting through building footprints.
|
|
53
|
+
|
|
54
|
+
**Pathfinding** (`pathfind`) — shortest walkable route between two
|
|
55
|
+
buildings by ID, with real-world distance in meters.
|
|
56
|
+
|
|
57
|
+
**Analytics** (`compute_all` and friends) — population & per-capita
|
|
58
|
+
resource use, walkability score (Dijkstra distance-to-amenity), zone
|
|
59
|
+
balance flags (unemployment risk, ghost town, dormitory suburb, etc.),
|
|
60
|
+
crucial-service coverage (hospitals/schools/fire/police), an SDG
|
|
61
|
+
green-space score, a carbon-neutrality timeline, and rooftop solar
|
|
62
|
+
potential.
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from citygrid import compute_zones, generate_roads, compute_all, GridConfig
|
|
68
|
+
|
|
69
|
+
# buildings: list of {id, grid_x, grid_y, width_studs, depth_studs,
|
|
70
|
+
# height_bricks, building_type (optional)}
|
|
71
|
+
buildings = [
|
|
72
|
+
{"id": 1, "grid_x": 0, "grid_y": 0, "width_studs": 2, "depth_studs": 2, "height_bricks": 6},
|
|
73
|
+
{"id": 2, "grid_x": 3, "grid_y": 0, "width_studs": 2, "depth_studs": 2, "height_bricks": 6},
|
|
74
|
+
{"id": 3, "grid_x": 0, "grid_y": 3, "width_studs": 2, "depth_studs": 2, "height_bricks": 1},
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
zones = compute_zones(buildings)
|
|
78
|
+
roads = generate_roads(buildings)
|
|
79
|
+
stats = compute_all(buildings, zones)
|
|
80
|
+
|
|
81
|
+
print(stats["population"]) # {'total_pop': ..., 'density': ..., 'energy': ..., ...}
|
|
82
|
+
print(stats["walkability"]) # {'score': ..., 'avg_dist': ..., 'unreachable': ...}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Custom grid size / thresholds
|
|
86
|
+
|
|
87
|
+
Every constant — grid dimensions, per-capita resource use, zone-balance
|
|
88
|
+
thresholds, walkability distance cap, and more — lives in one overridable
|
|
89
|
+
`GridConfig`:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from citygrid import GridConfig, compute_all
|
|
93
|
+
|
|
94
|
+
config = GridConfig(
|
|
95
|
+
grid_width=32, grid_height=32, # smaller board
|
|
96
|
+
stud_meters=5.0, # different real-world scale
|
|
97
|
+
walk_max_meters=800, # stricter walkability target
|
|
98
|
+
)
|
|
99
|
+
stats = compute_all(buildings, zones, config)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If you don't pass a `config`, every function uses `GridConfig()`'s
|
|
103
|
+
defaults (a 64x64 grid at 10 real-world meters per cell — the values this
|
|
104
|
+
library was originally tuned against).
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install -e ".[dev]"
|
|
110
|
+
pytest
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT
|
citygrid-0.1.0/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# citygrid
|
|
2
|
+
|
|
3
|
+
Zone classification, road generation, pathfinding, and urban analytics for
|
|
4
|
+
a grid of axis-aligned rectangular buildings.
|
|
5
|
+
|
|
6
|
+
Originally built for a physical LEGO-brick smart-city simulator, extracted
|
|
7
|
+
into a standalone library because the underlying logic — "given a bunch of
|
|
8
|
+
rectangles on a grid, classify zones, connect them with roads, and score
|
|
9
|
+
the layout" — is generic enough to be useful for city-builder games, urban
|
|
10
|
+
planning teaching tools, and GIS prototyping.
|
|
11
|
+
|
|
12
|
+
Zero required dependencies — pure Python, `math`/`heapq`/`dataclasses` only.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install citygrid
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What it does
|
|
21
|
+
|
|
22
|
+
**Zoning** (`compute_zones`) — connected-component BFS groups nearby
|
|
23
|
+
buildings into blocks, then classifies each block as Residential,
|
|
24
|
+
Commercial, Industrial, or Mixed based on height/footprint mix; empty
|
|
25
|
+
areas become Green space.
|
|
26
|
+
|
|
27
|
+
**Roads** (`generate_roads`) — two-phase A* generates a closed-circuit
|
|
28
|
+
road network along zone-block faces, connecting every block without
|
|
29
|
+
cutting through building footprints.
|
|
30
|
+
|
|
31
|
+
**Pathfinding** (`pathfind`) — shortest walkable route between two
|
|
32
|
+
buildings by ID, with real-world distance in meters.
|
|
33
|
+
|
|
34
|
+
**Analytics** (`compute_all` and friends) — population & per-capita
|
|
35
|
+
resource use, walkability score (Dijkstra distance-to-amenity), zone
|
|
36
|
+
balance flags (unemployment risk, ghost town, dormitory suburb, etc.),
|
|
37
|
+
crucial-service coverage (hospitals/schools/fire/police), an SDG
|
|
38
|
+
green-space score, a carbon-neutrality timeline, and rooftop solar
|
|
39
|
+
potential.
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from citygrid import compute_zones, generate_roads, compute_all, GridConfig
|
|
45
|
+
|
|
46
|
+
# buildings: list of {id, grid_x, grid_y, width_studs, depth_studs,
|
|
47
|
+
# height_bricks, building_type (optional)}
|
|
48
|
+
buildings = [
|
|
49
|
+
{"id": 1, "grid_x": 0, "grid_y": 0, "width_studs": 2, "depth_studs": 2, "height_bricks": 6},
|
|
50
|
+
{"id": 2, "grid_x": 3, "grid_y": 0, "width_studs": 2, "depth_studs": 2, "height_bricks": 6},
|
|
51
|
+
{"id": 3, "grid_x": 0, "grid_y": 3, "width_studs": 2, "depth_studs": 2, "height_bricks": 1},
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
zones = compute_zones(buildings)
|
|
55
|
+
roads = generate_roads(buildings)
|
|
56
|
+
stats = compute_all(buildings, zones)
|
|
57
|
+
|
|
58
|
+
print(stats["population"]) # {'total_pop': ..., 'density': ..., 'energy': ..., ...}
|
|
59
|
+
print(stats["walkability"]) # {'score': ..., 'avg_dist': ..., 'unreachable': ...}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Custom grid size / thresholds
|
|
63
|
+
|
|
64
|
+
Every constant — grid dimensions, per-capita resource use, zone-balance
|
|
65
|
+
thresholds, walkability distance cap, and more — lives in one overridable
|
|
66
|
+
`GridConfig`:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from citygrid import GridConfig, compute_all
|
|
70
|
+
|
|
71
|
+
config = GridConfig(
|
|
72
|
+
grid_width=32, grid_height=32, # smaller board
|
|
73
|
+
stud_meters=5.0, # different real-world scale
|
|
74
|
+
walk_max_meters=800, # stricter walkability target
|
|
75
|
+
)
|
|
76
|
+
stats = compute_all(buildings, zones, config)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If you don't pass a `config`, every function uses `GridConfig()`'s
|
|
80
|
+
defaults (a 64x64 grid at 10 real-world meters per cell — the values this
|
|
81
|
+
library was originally tuned against).
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install -e ".[dev]"
|
|
87
|
+
pytest
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "citygrid"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Zone classification, road generation, pathfinding, and urban analytics for a grid of buildings"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{ name = "Joe Tan", email = "jtkmjoe@gmail.com" }]
|
|
13
|
+
keywords = ["urban-planning", "city-simulation", "zoning", "pathfinding", "walkability", "grid", "game-dev", "gis"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
21
|
+
"Topic :: Software Development :: Libraries",
|
|
22
|
+
]
|
|
23
|
+
dependencies = []
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = ["pytest>=7.0"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/Joetankm/citygrid"
|
|
30
|
+
Repository = "https://github.com/Joetankm/citygrid"
|
|
31
|
+
Issues = "https://github.com/Joetankm/citygrid/issues"
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/citygrid"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from .config import GridConfig
|
|
2
|
+
from .zones import compute_zones, generate_roads, pathfind
|
|
3
|
+
from .analytics import (
|
|
4
|
+
compute_population_stats,
|
|
5
|
+
compute_walkability,
|
|
6
|
+
compute_zone_balance,
|
|
7
|
+
zone_balance_score,
|
|
8
|
+
compute_crucial_metrics,
|
|
9
|
+
compute_sdg_score,
|
|
10
|
+
compute_carbon_timeline,
|
|
11
|
+
compute_solar_potential,
|
|
12
|
+
compute_all,
|
|
13
|
+
CRUCIAL_TYPES,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"GridConfig",
|
|
18
|
+
"compute_zones", "generate_roads", "pathfind",
|
|
19
|
+
"compute_population_stats", "compute_walkability", "compute_zone_balance",
|
|
20
|
+
"zone_balance_score", "compute_crucial_metrics", "compute_sdg_score",
|
|
21
|
+
"compute_carbon_timeline", "compute_solar_potential", "compute_all",
|
|
22
|
+
"CRUCIAL_TYPES",
|
|
23
|
+
]
|
|
24
|
+
__version__ = "0.1.0"
|