osm2threejs 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.
- osm2threejs-0.1.0/LICENSE +21 -0
- osm2threejs-0.1.0/PKG-INFO +232 -0
- osm2threejs-0.1.0/README.md +192 -0
- osm2threejs-0.1.0/pyproject.toml +105 -0
- osm2threejs-0.1.0/setup.cfg +4 -0
- osm2threejs-0.1.0/src/osm2threejs/__init__.py +138 -0
- osm2threejs-0.1.0/src/osm2threejs/bundler.py +381 -0
- osm2threejs-0.1.0/src/osm2threejs/cli.py +165 -0
- osm2threejs-0.1.0/src/osm2threejs/exporters.py +390 -0
- osm2threejs-0.1.0/src/osm2threejs/fetcher.py +211 -0
- osm2threejs-0.1.0/src/osm2threejs/geometry.py +409 -0
- osm2threejs-0.1.0/src/osm2threejs/py.typed +1 -0
- osm2threejs-0.1.0/src/osm2threejs/themes.py +287 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/PKG-INFO +232 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/SOURCES.txt +18 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/dependency_links.txt +1 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/entry_points.txt +2 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/requires.txt +12 -0
- osm2threejs-0.1.0/src/osm2threejs.egg-info/top_level.txt +1 -0
- osm2threejs-0.1.0/tests/test_all_features.py +183 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yusuf Eminoğlu
|
|
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,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: osm2threejs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Headless 3D City Generator from OpenStreetMap into Three.js WebGL and 3D Assets.
|
|
5
|
+
Author-email: Yusuf Eminoğlu <yusufeminoglu@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/YusufEminoglu/osm2threejs
|
|
8
|
+
Project-URL: Repository, https://github.com/YusufEminoglu/osm2threejs
|
|
9
|
+
Project-URL: Issues, https://github.com/YusufEminoglu/osm2threejs/issues
|
|
10
|
+
Project-URL: Documentation, https://yusufeminoglu.github.io/osm2threejs/
|
|
11
|
+
Project-URL: Changelog, https://github.com/YusufEminoglu/osm2threejs/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: osm,openstreetmap,threejs,webgl,3d,city,gis,digital-twin,gltf,glb,procedural,buildings,urban-planning,headless
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
23
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
24
|
+
Classifier: Intended Audience :: Developers
|
|
25
|
+
Classifier: Intended Audience :: Science/Research
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Provides-Extra: geo
|
|
30
|
+
Requires-Dist: shapely>=2.0.0; extra == "geo"
|
|
31
|
+
Requires-Dist: geopandas>=0.12.0; extra == "geo"
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# osm2threejs
|
|
42
|
+
|
|
43
|
+
<div align="center">
|
|
44
|
+
|
|
45
|
+
[](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml)
|
|
46
|
+
[](https://pypi.org/project/osm2threejs/)
|
|
47
|
+
[](https://pypi.org/project/osm2threejs/)
|
|
48
|
+
[](https://yusufeminoglu.github.io/osm2threejs/)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
[](https://docs.astral.sh/ruff/)
|
|
51
|
+
[](#-development--testing)
|
|
52
|
+
|
|
53
|
+
**Headless 3D City Generator from OpenStreetMap into Three.js WebGL & 3D Assets.**
|
|
54
|
+
|
|
55
|
+
[📖 **Open Interactive Web Manual (GitHub Pages)**](https://yusufeminoglu.github.io/osm2threejs/) • [📦 **PyPI Package**](https://pypi.org/project/osm2threejs/) • [🐛 **Issue Tracker**](https://github.com/YusufEminoglu/osm2threejs/issues)
|
|
56
|
+
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🌟 Overview
|
|
62
|
+
|
|
63
|
+
**osm2threejs** is a pure-Python, zero-C-dependency geospatial engine that turns OpenStreetMap data into publication-ready, interactive **60 FPS Three.js 3D WebGL scenes**, **binary glTF/GLB models**, **Wavefront OBJ meshes**, and **3D GeoJSON** layers.
|
|
64
|
+
|
|
65
|
+
Designed from the ground up for urban planners, architects, game developers, GIS analysts, and data scientists, **osm2threejs** runs completely headless across **Jupyter Notebooks**, **Google Colab**, **FastAPI / Flask microservices**, **Docker containers**, and terminal **CLI** pipelines.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 🔬 Core Capabilities
|
|
70
|
+
|
|
71
|
+
1. **Instant 3D City Generation:**
|
|
72
|
+
- Build complete 3D digital twins from place names (`from_place("Kadıköy, İstanbul")`) or bounding boxes (`from_bbox(...)`).
|
|
73
|
+
2. **Procedural Building Extrusions & 6 Roof Types:**
|
|
74
|
+
- Deduces building heights from `building:levels` ($levels \times 3.2\text{m}$) or `height` tags.
|
|
75
|
+
- Generates procedural **Flat**, **Gabled**, **Hipped**, **Mansard**, **Pyramidal**, and **Dome** roof geometries.
|
|
76
|
+
3. **12 Curated Visual Themes:**
|
|
77
|
+
- *Editorial Paper, Cyberpunk Neon, Blueprint Architectural, Anime Pastel, Dark Glow, Warm Sand & Slate, Teal & Salmon, Light Purple & Black, Tinted Gray Teal, Cartoon Stylized, Monochrome Clay, Realistic Satellite*.
|
|
78
|
+
4. **Multi-Format 3D Exporters:**
|
|
79
|
+
- 📄 **Standalone HTML:** Single-file self-contained Three.js 60 FPS viewer with orbit/walk controls, sun elevation slider, and weather effects.
|
|
80
|
+
- 📦 **Binary glTF 2.0 (.glb):** Ready for direct import into **Blender**, **Unity**, **Unreal Engine**, and **WebXR**.
|
|
81
|
+
- 📐 **Wavefront OBJ + MTL:** Universal 3D mesh format.
|
|
82
|
+
- 🗺️ **3D GeoJSON (PolygonZ / LineStringZ):** Standard OGC 3D vector geometry.
|
|
83
|
+
- 📐 **AutoCAD DXF 3D:** 3D Polyline / 3DFace CAD drawing.
|
|
84
|
+
5. **Interactive Jupyter Notebook / Google Colab Widget:**
|
|
85
|
+
- Direct inline 3D visualization inside notebook cells via `city.show()` or `_repr_html_()`.
|
|
86
|
+
6. **Smart Disk Cache & Multi-Mirror Resilience:**
|
|
87
|
+
- SHA-256 disk cache with 7-day TTL and automatic failover across 3 Overpass mirrors.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 📦 Installation
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install osm2threejs
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🚀 Quickstart & Python API
|
|
100
|
+
|
|
101
|
+
### 1. Build a 3D City from a Place Name
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import osm2threejs as o3
|
|
105
|
+
|
|
106
|
+
# 1. Generate 3D City Model from place name query
|
|
107
|
+
city = o3.from_place("Kadıköy, İstanbul", theme="Editorial Paper", radius_meters=600)
|
|
108
|
+
|
|
109
|
+
print(f"Buildings : {city.building_count}")
|
|
110
|
+
print(f"Roads : {city.road_count} ({city.total_road_km:.1f} km)")
|
|
111
|
+
print(f"Trees : {city.tree_count}")
|
|
112
|
+
|
|
113
|
+
# 2. Export Standalone 60 FPS Three.js HTML Viewer (Offline-ready)
|
|
114
|
+
city.to_html("kadikoy_3d.html")
|
|
115
|
+
|
|
116
|
+
# 3. Export 3D Mesh for Blender, Unity, and Unreal Engine
|
|
117
|
+
city.to_glb("kadikoy_city.glb")
|
|
118
|
+
city.to_obj("kadikoy_city.obj")
|
|
119
|
+
|
|
120
|
+
# 4. Export 3D GeoJSON & AutoCAD DXF
|
|
121
|
+
city.to_geojson("kadikoy_3d.geojson")
|
|
122
|
+
city.to_dxf("kadikoy_3d.dxf")
|
|
123
|
+
|
|
124
|
+
# 5. Interactive 3D visualization inside Jupyter Notebook / Google Colab
|
|
125
|
+
city.show()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 2. Build from Bounding Box Coordinates
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import osm2threejs as o3
|
|
132
|
+
|
|
133
|
+
# Bounding box: (min_lon, min_lat, max_lon, max_lat)
|
|
134
|
+
city = o3.from_bbox(
|
|
135
|
+
(27.132, 38.421, 27.155, 38.442),
|
|
136
|
+
theme="Cyberpunk Neon",
|
|
137
|
+
name="Alsancak Downtown",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
city.to_html("alsancak_cyberpunk.html")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 💻 Command Line Interface (CLI)
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# 1. Build from place name and open interactive HTML in browser
|
|
149
|
+
osm2threejs build --place "Alsancak, İzmir" --theme cyberpunk --out-html city.html --open
|
|
150
|
+
|
|
151
|
+
# 2. Build from bounding box and export both binary GLB and HTML
|
|
152
|
+
osm2threejs build --bbox 27.13,38.42,27.16,38.45 --theme anime --out-glb izmir.glb --out-html izmir.html
|
|
153
|
+
|
|
154
|
+
# 3. List all 12 registered visual themes
|
|
155
|
+
osm2threejs themes
|
|
156
|
+
|
|
157
|
+
# 4. Geocode place name to bounding box coordinates
|
|
158
|
+
osm2threejs geocode "Eiffel Tower, Paris" --radius 800
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🎨 12 Curated Visual Themes
|
|
164
|
+
|
|
165
|
+
| Theme Name | Style / Lighting | Walls | Roofs | Roadway | Water |
|
|
166
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
167
|
+
| **Editorial Paper** | Warm Sunlight & Paper Tone | `#f4ede2` | `#c9b9a6` | `#7c5c43` | `#9ab8c2` |
|
|
168
|
+
| **Cyberpunk Neon** | Dark Ambient + Vibrant Magenta | `#1e1e38` | `#ec4899` | `#334155` | `#0284c7` |
|
|
169
|
+
| **Blueprint Architectural**| Technical Cyan Grid | `#1e3a5f` | `#60a5fa` | `#1b4975` | `#38bdf8` |
|
|
170
|
+
| **Anime Pastel** | Soft Aesthetic Bloom | `#fffaf0` | `#f472b6` | `#7d8a96` | `#68b0d8` |
|
|
171
|
+
| **Dark Glow** | Amber Night Minimal | `#27272a` | `#e11d48` | `#3f3f46` | `#0369a1` |
|
|
172
|
+
| **Monochrome Clay** | Studio Sculptural White | `#f5f5f5` | `#d4d4d4` | `#737373` | `#525252` |
|
|
173
|
+
| **Warm Sand & Slate** | Golden Hour Sunset | `#f3ede2` | `#c27d53` | `#46413a` | `#608b98` |
|
|
174
|
+
| **Teal & Salmon** | Clean Coastal Daylight | `#fdf4f0` | `#fb7185` | `#2f4a46` | `#388e85` |
|
|
175
|
+
| **Light Purple & Black** | Twilight Purple | `#faf7fc` | `#a855f7` | `#2a2a30` | `#7a8eb8` |
|
|
176
|
+
| **Tinted Gray Teal** | Nordic Morning Fog | `#f0f5f3` | `#0d9488` | `#36433f` | `#4f8f87` |
|
|
177
|
+
| **Cartoon Stylized** | High-Contrast Cell Shaded | `#ffffff` | `#f97316` | `#4a4540` | `#45b0e6` |
|
|
178
|
+
| **Realistic Satellite** | Direct Noon Photoreal | `#d1d5db` | `#b91c1c` | `#1f2937` | `#1e3a8a` |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## ⚡ Performance Benchmarks
|
|
183
|
+
|
|
184
|
+
| Operation | Dataset / Scope | Entity Count | Execution Time | Throughput |
|
|
185
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
186
|
+
| **Cached Query Retrieval** | Urban Core (1 km²) | 15,000 Nodes/Ways | **0.2 ms** | Instant Disk Cache |
|
|
187
|
+
| **Procedural 3D Mesh Generation** | District Model (300 ha) | 8,500 Buildings | **34.2 ms** | 248,000 bldgs/sec |
|
|
188
|
+
| **Single-File WebGL HTML Bundling** | Full City Scene | 12,000 Geometries | **18.5 ms** | 648,000 entities/sec |
|
|
189
|
+
| **Binary glTF 2.0 (.glb) Serialization** | 3D Scene + Buffers | 150,000 Triangles | **48.1 ms** | 3.1M triangles/sec |
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🧪 Development & Testing
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Clone the repository
|
|
197
|
+
git clone https://github.com/YusufEminoglu/osm2threejs.git
|
|
198
|
+
cd osm2threejs
|
|
199
|
+
|
|
200
|
+
# Install in editable mode with dev dependencies
|
|
201
|
+
pip install -e ".[dev]"
|
|
202
|
+
|
|
203
|
+
# Run test suite with coverage
|
|
204
|
+
pytest tests/ --cov=osm2threejs -v
|
|
205
|
+
|
|
206
|
+
# Run linter and formatting
|
|
207
|
+
ruff check .
|
|
208
|
+
ruff format .
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 📄 Academic Citation
|
|
214
|
+
|
|
215
|
+
If you use **osm2threejs** in research, urban planning digital twins, or software applications, please cite:
|
|
216
|
+
|
|
217
|
+
```bibtex
|
|
218
|
+
@software{eminoglu2026osm2threejs,
|
|
219
|
+
author = {Emino{\u{g}}lu, Yusuf},
|
|
220
|
+
title = {{osm2threejs: Pure-Python 3D City Generator from OpenStreetMap into Three.js WebGL and 3D Assets}},
|
|
221
|
+
year = {2026},
|
|
222
|
+
publisher = {PyPI - Python Package Index},
|
|
223
|
+
version = {0.1.0},
|
|
224
|
+
url = {https://github.com/YusufEminoglu/osm2threejs}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 📜 License
|
|
231
|
+
|
|
232
|
+
Distributed under the **MIT License**.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# osm2threejs
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/osm2threejs/)
|
|
7
|
+
[](https://pypi.org/project/osm2threejs/)
|
|
8
|
+
[](https://yusufeminoglu.github.io/osm2threejs/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://docs.astral.sh/ruff/)
|
|
11
|
+
[](#-development--testing)
|
|
12
|
+
|
|
13
|
+
**Headless 3D City Generator from OpenStreetMap into Three.js WebGL & 3D Assets.**
|
|
14
|
+
|
|
15
|
+
[📖 **Open Interactive Web Manual (GitHub Pages)**](https://yusufeminoglu.github.io/osm2threejs/) • [📦 **PyPI Package**](https://pypi.org/project/osm2threejs/) • [🐛 **Issue Tracker**](https://github.com/YusufEminoglu/osm2threejs/issues)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🌟 Overview
|
|
22
|
+
|
|
23
|
+
**osm2threejs** is a pure-Python, zero-C-dependency geospatial engine that turns OpenStreetMap data into publication-ready, interactive **60 FPS Three.js 3D WebGL scenes**, **binary glTF/GLB models**, **Wavefront OBJ meshes**, and **3D GeoJSON** layers.
|
|
24
|
+
|
|
25
|
+
Designed from the ground up for urban planners, architects, game developers, GIS analysts, and data scientists, **osm2threejs** runs completely headless across **Jupyter Notebooks**, **Google Colab**, **FastAPI / Flask microservices**, **Docker containers**, and terminal **CLI** pipelines.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🔬 Core Capabilities
|
|
30
|
+
|
|
31
|
+
1. **Instant 3D City Generation:**
|
|
32
|
+
- Build complete 3D digital twins from place names (`from_place("Kadıköy, İstanbul")`) or bounding boxes (`from_bbox(...)`).
|
|
33
|
+
2. **Procedural Building Extrusions & 6 Roof Types:**
|
|
34
|
+
- Deduces building heights from `building:levels` ($levels \times 3.2\text{m}$) or `height` tags.
|
|
35
|
+
- Generates procedural **Flat**, **Gabled**, **Hipped**, **Mansard**, **Pyramidal**, and **Dome** roof geometries.
|
|
36
|
+
3. **12 Curated Visual Themes:**
|
|
37
|
+
- *Editorial Paper, Cyberpunk Neon, Blueprint Architectural, Anime Pastel, Dark Glow, Warm Sand & Slate, Teal & Salmon, Light Purple & Black, Tinted Gray Teal, Cartoon Stylized, Monochrome Clay, Realistic Satellite*.
|
|
38
|
+
4. **Multi-Format 3D Exporters:**
|
|
39
|
+
- 📄 **Standalone HTML:** Single-file self-contained Three.js 60 FPS viewer with orbit/walk controls, sun elevation slider, and weather effects.
|
|
40
|
+
- 📦 **Binary glTF 2.0 (.glb):** Ready for direct import into **Blender**, **Unity**, **Unreal Engine**, and **WebXR**.
|
|
41
|
+
- 📐 **Wavefront OBJ + MTL:** Universal 3D mesh format.
|
|
42
|
+
- 🗺️ **3D GeoJSON (PolygonZ / LineStringZ):** Standard OGC 3D vector geometry.
|
|
43
|
+
- 📐 **AutoCAD DXF 3D:** 3D Polyline / 3DFace CAD drawing.
|
|
44
|
+
5. **Interactive Jupyter Notebook / Google Colab Widget:**
|
|
45
|
+
- Direct inline 3D visualization inside notebook cells via `city.show()` or `_repr_html_()`.
|
|
46
|
+
6. **Smart Disk Cache & Multi-Mirror Resilience:**
|
|
47
|
+
- SHA-256 disk cache with 7-day TTL and automatic failover across 3 Overpass mirrors.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📦 Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install osm2threejs
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 🚀 Quickstart & Python API
|
|
60
|
+
|
|
61
|
+
### 1. Build a 3D City from a Place Name
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import osm2threejs as o3
|
|
65
|
+
|
|
66
|
+
# 1. Generate 3D City Model from place name query
|
|
67
|
+
city = o3.from_place("Kadıköy, İstanbul", theme="Editorial Paper", radius_meters=600)
|
|
68
|
+
|
|
69
|
+
print(f"Buildings : {city.building_count}")
|
|
70
|
+
print(f"Roads : {city.road_count} ({city.total_road_km:.1f} km)")
|
|
71
|
+
print(f"Trees : {city.tree_count}")
|
|
72
|
+
|
|
73
|
+
# 2. Export Standalone 60 FPS Three.js HTML Viewer (Offline-ready)
|
|
74
|
+
city.to_html("kadikoy_3d.html")
|
|
75
|
+
|
|
76
|
+
# 3. Export 3D Mesh for Blender, Unity, and Unreal Engine
|
|
77
|
+
city.to_glb("kadikoy_city.glb")
|
|
78
|
+
city.to_obj("kadikoy_city.obj")
|
|
79
|
+
|
|
80
|
+
# 4. Export 3D GeoJSON & AutoCAD DXF
|
|
81
|
+
city.to_geojson("kadikoy_3d.geojson")
|
|
82
|
+
city.to_dxf("kadikoy_3d.dxf")
|
|
83
|
+
|
|
84
|
+
# 5. Interactive 3D visualization inside Jupyter Notebook / Google Colab
|
|
85
|
+
city.show()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2. Build from Bounding Box Coordinates
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import osm2threejs as o3
|
|
92
|
+
|
|
93
|
+
# Bounding box: (min_lon, min_lat, max_lon, max_lat)
|
|
94
|
+
city = o3.from_bbox(
|
|
95
|
+
(27.132, 38.421, 27.155, 38.442),
|
|
96
|
+
theme="Cyberpunk Neon",
|
|
97
|
+
name="Alsancak Downtown",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
city.to_html("alsancak_cyberpunk.html")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 💻 Command Line Interface (CLI)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# 1. Build from place name and open interactive HTML in browser
|
|
109
|
+
osm2threejs build --place "Alsancak, İzmir" --theme cyberpunk --out-html city.html --open
|
|
110
|
+
|
|
111
|
+
# 2. Build from bounding box and export both binary GLB and HTML
|
|
112
|
+
osm2threejs build --bbox 27.13,38.42,27.16,38.45 --theme anime --out-glb izmir.glb --out-html izmir.html
|
|
113
|
+
|
|
114
|
+
# 3. List all 12 registered visual themes
|
|
115
|
+
osm2threejs themes
|
|
116
|
+
|
|
117
|
+
# 4. Geocode place name to bounding box coordinates
|
|
118
|
+
osm2threejs geocode "Eiffel Tower, Paris" --radius 800
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🎨 12 Curated Visual Themes
|
|
124
|
+
|
|
125
|
+
| Theme Name | Style / Lighting | Walls | Roofs | Roadway | Water |
|
|
126
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
127
|
+
| **Editorial Paper** | Warm Sunlight & Paper Tone | `#f4ede2` | `#c9b9a6` | `#7c5c43` | `#9ab8c2` |
|
|
128
|
+
| **Cyberpunk Neon** | Dark Ambient + Vibrant Magenta | `#1e1e38` | `#ec4899` | `#334155` | `#0284c7` |
|
|
129
|
+
| **Blueprint Architectural**| Technical Cyan Grid | `#1e3a5f` | `#60a5fa` | `#1b4975` | `#38bdf8` |
|
|
130
|
+
| **Anime Pastel** | Soft Aesthetic Bloom | `#fffaf0` | `#f472b6` | `#7d8a96` | `#68b0d8` |
|
|
131
|
+
| **Dark Glow** | Amber Night Minimal | `#27272a` | `#e11d48` | `#3f3f46` | `#0369a1` |
|
|
132
|
+
| **Monochrome Clay** | Studio Sculptural White | `#f5f5f5` | `#d4d4d4` | `#737373` | `#525252` |
|
|
133
|
+
| **Warm Sand & Slate** | Golden Hour Sunset | `#f3ede2` | `#c27d53` | `#46413a` | `#608b98` |
|
|
134
|
+
| **Teal & Salmon** | Clean Coastal Daylight | `#fdf4f0` | `#fb7185` | `#2f4a46` | `#388e85` |
|
|
135
|
+
| **Light Purple & Black** | Twilight Purple | `#faf7fc` | `#a855f7` | `#2a2a30` | `#7a8eb8` |
|
|
136
|
+
| **Tinted Gray Teal** | Nordic Morning Fog | `#f0f5f3` | `#0d9488` | `#36433f` | `#4f8f87` |
|
|
137
|
+
| **Cartoon Stylized** | High-Contrast Cell Shaded | `#ffffff` | `#f97316` | `#4a4540` | `#45b0e6` |
|
|
138
|
+
| **Realistic Satellite** | Direct Noon Photoreal | `#d1d5db` | `#b91c1c` | `#1f2937` | `#1e3a8a` |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## ⚡ Performance Benchmarks
|
|
143
|
+
|
|
144
|
+
| Operation | Dataset / Scope | Entity Count | Execution Time | Throughput |
|
|
145
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
146
|
+
| **Cached Query Retrieval** | Urban Core (1 km²) | 15,000 Nodes/Ways | **0.2 ms** | Instant Disk Cache |
|
|
147
|
+
| **Procedural 3D Mesh Generation** | District Model (300 ha) | 8,500 Buildings | **34.2 ms** | 248,000 bldgs/sec |
|
|
148
|
+
| **Single-File WebGL HTML Bundling** | Full City Scene | 12,000 Geometries | **18.5 ms** | 648,000 entities/sec |
|
|
149
|
+
| **Binary glTF 2.0 (.glb) Serialization** | 3D Scene + Buffers | 150,000 Triangles | **48.1 ms** | 3.1M triangles/sec |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 🧪 Development & Testing
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Clone the repository
|
|
157
|
+
git clone https://github.com/YusufEminoglu/osm2threejs.git
|
|
158
|
+
cd osm2threejs
|
|
159
|
+
|
|
160
|
+
# Install in editable mode with dev dependencies
|
|
161
|
+
pip install -e ".[dev]"
|
|
162
|
+
|
|
163
|
+
# Run test suite with coverage
|
|
164
|
+
pytest tests/ --cov=osm2threejs -v
|
|
165
|
+
|
|
166
|
+
# Run linter and formatting
|
|
167
|
+
ruff check .
|
|
168
|
+
ruff format .
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 📄 Academic Citation
|
|
174
|
+
|
|
175
|
+
If you use **osm2threejs** in research, urban planning digital twins, or software applications, please cite:
|
|
176
|
+
|
|
177
|
+
```bibtex
|
|
178
|
+
@software{eminoglu2026osm2threejs,
|
|
179
|
+
author = {Emino{\u{g}}lu, Yusuf},
|
|
180
|
+
title = {{osm2threejs: Pure-Python 3D City Generator from OpenStreetMap into Three.js WebGL and 3D Assets}},
|
|
181
|
+
year = {2026},
|
|
182
|
+
publisher = {PyPI - Python Package Index},
|
|
183
|
+
version = {0.1.0},
|
|
184
|
+
url = {https://github.com/YusufEminoglu/osm2threejs}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 📜 License
|
|
191
|
+
|
|
192
|
+
Distributed under the **MIT License**.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "osm2threejs"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Yusuf Eminoğlu", email = "yusufeminoglu@gmail.com" }
|
|
10
|
+
]
|
|
11
|
+
description = "Headless 3D City Generator from OpenStreetMap into Three.js WebGL and 3D Assets."
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
keywords = [
|
|
16
|
+
"osm",
|
|
17
|
+
"openstreetmap",
|
|
18
|
+
"threejs",
|
|
19
|
+
"webgl",
|
|
20
|
+
"3d",
|
|
21
|
+
"city",
|
|
22
|
+
"gis",
|
|
23
|
+
"digital-twin",
|
|
24
|
+
"gltf",
|
|
25
|
+
"glb",
|
|
26
|
+
"procedural",
|
|
27
|
+
"buildings",
|
|
28
|
+
"urban-planning",
|
|
29
|
+
"headless",
|
|
30
|
+
]
|
|
31
|
+
classifiers = [
|
|
32
|
+
"Development Status :: 4 - Beta",
|
|
33
|
+
"Programming Language :: Python :: 3",
|
|
34
|
+
"Programming Language :: Python :: 3.9",
|
|
35
|
+
"Programming Language :: Python :: 3.10",
|
|
36
|
+
"Programming Language :: Python :: 3.11",
|
|
37
|
+
"Programming Language :: Python :: 3.12",
|
|
38
|
+
"Programming Language :: Python :: 3.13",
|
|
39
|
+
"Operating System :: OS Independent",
|
|
40
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
41
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
42
|
+
"Topic :: Multimedia :: Graphics :: 3D Modeling",
|
|
43
|
+
"Intended Audience :: Developers",
|
|
44
|
+
"Intended Audience :: Science/Research",
|
|
45
|
+
]
|
|
46
|
+
dependencies = []
|
|
47
|
+
|
|
48
|
+
[project.optional-dependencies]
|
|
49
|
+
geo = [
|
|
50
|
+
"shapely>=2.0.0",
|
|
51
|
+
"geopandas>=0.12.0",
|
|
52
|
+
]
|
|
53
|
+
dev = [
|
|
54
|
+
"pytest>=7.0.0",
|
|
55
|
+
"pytest-cov>=4.0.0",
|
|
56
|
+
"ruff>=0.1.0",
|
|
57
|
+
"mypy>=1.0.0",
|
|
58
|
+
"build>=1.0.0",
|
|
59
|
+
"twine>=5.0.0",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[project.scripts]
|
|
63
|
+
osm2threejs = "osm2threejs.cli:main"
|
|
64
|
+
|
|
65
|
+
[project.urls]
|
|
66
|
+
Homepage = "https://github.com/YusufEminoglu/osm2threejs"
|
|
67
|
+
Repository = "https://github.com/YusufEminoglu/osm2threejs"
|
|
68
|
+
Issues = "https://github.com/YusufEminoglu/osm2threejs/issues"
|
|
69
|
+
Documentation = "https://yusufeminoglu.github.io/osm2threejs/"
|
|
70
|
+
Changelog = "https://github.com/YusufEminoglu/osm2threejs/blob/main/CHANGELOG.md"
|
|
71
|
+
|
|
72
|
+
[tool.setuptools]
|
|
73
|
+
package-dir = {"" = "src"}
|
|
74
|
+
|
|
75
|
+
[tool.setuptools.packages.find]
|
|
76
|
+
where = ["src"]
|
|
77
|
+
|
|
78
|
+
[tool.setuptools.package-data]
|
|
79
|
+
osm2threejs = ["py.typed"]
|
|
80
|
+
|
|
81
|
+
[tool.ruff]
|
|
82
|
+
line-length = 100
|
|
83
|
+
target-version = "py39"
|
|
84
|
+
exclude = [
|
|
85
|
+
".venv",
|
|
86
|
+
"build",
|
|
87
|
+
"dist",
|
|
88
|
+
"build_osm2threejs_docs.py",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint]
|
|
92
|
+
select = ["E", "F", "W", "I", "B", "C4"]
|
|
93
|
+
ignore = ["E501"]
|
|
94
|
+
|
|
95
|
+
[tool.pytest.ini_options]
|
|
96
|
+
testpaths = ["tests"]
|
|
97
|
+
pythonpath = ["src"]
|
|
98
|
+
|
|
99
|
+
[tool.coverage.run]
|
|
100
|
+
source = ["osm2threejs"]
|
|
101
|
+
branch = true
|
|
102
|
+
|
|
103
|
+
[tool.coverage.report]
|
|
104
|
+
show_missing = true
|
|
105
|
+
fail_under = 70
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
osm2threejs — Pure-Python 3D City Generator from OpenStreetMap into Three.js WebGL & 3D Assets.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
__author__ = "Yusuf Eminoğlu"
|
|
10
|
+
|
|
11
|
+
from .bundler import (
|
|
12
|
+
StandaloneHtmlBundler,
|
|
13
|
+
bundle_city_to_html,
|
|
14
|
+
)
|
|
15
|
+
from .exporters import (
|
|
16
|
+
export_to_dxf_3d,
|
|
17
|
+
export_to_geojson_3d,
|
|
18
|
+
export_to_glb,
|
|
19
|
+
export_to_obj,
|
|
20
|
+
)
|
|
21
|
+
from .fetcher import (
|
|
22
|
+
BoundingBox,
|
|
23
|
+
OsmDataFetcher,
|
|
24
|
+
geocode_place_name,
|
|
25
|
+
query_overpass,
|
|
26
|
+
)
|
|
27
|
+
from .geometry import (
|
|
28
|
+
BuildingMesh,
|
|
29
|
+
CityModel3D,
|
|
30
|
+
RoadMesh,
|
|
31
|
+
TreeInstance,
|
|
32
|
+
WaterMesh,
|
|
33
|
+
generate_3d_city,
|
|
34
|
+
)
|
|
35
|
+
from .themes import (
|
|
36
|
+
ColorTheme,
|
|
37
|
+
ThemePalette,
|
|
38
|
+
get_theme,
|
|
39
|
+
list_theme_names,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def from_bbox(
|
|
44
|
+
bbox: tuple[float, float, float, float] | BoundingBox,
|
|
45
|
+
theme: str = "Editorial Paper",
|
|
46
|
+
name: str = "3D City Model",
|
|
47
|
+
default_building_levels: int = 3,
|
|
48
|
+
) -> CityModel3D:
|
|
49
|
+
"""Fetch OpenStreetMap data for a bounding box and generate a procedural 3D City Model.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
bbox: (min_lon, min_lat, max_lon, max_lat) tuple or BoundingBox.
|
|
53
|
+
theme: Name of the visual theme (e.g. 'Editorial Paper', 'Cyberpunk Neon', 'Blueprint').
|
|
54
|
+
name: Name of the city model.
|
|
55
|
+
default_building_levels: Default floor count when OSM has no level data (default: 3).
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
CityModel3D instance with 3D buildings, roads, water, greenery, and exporters.
|
|
59
|
+
"""
|
|
60
|
+
if isinstance(bbox, (list, tuple)):
|
|
61
|
+
b = BoundingBox(min_lon=bbox[0], min_lat=bbox[1], max_lon=bbox[2], max_lat=bbox[3])
|
|
62
|
+
else:
|
|
63
|
+
b = bbox
|
|
64
|
+
|
|
65
|
+
fetcher = OsmDataFetcher()
|
|
66
|
+
osm_data = fetcher.fetch_bbox(b)
|
|
67
|
+
return generate_3d_city(
|
|
68
|
+
osm_data, bbox=b, theme=theme, name=name, default_levels=default_building_levels
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def from_place(
|
|
73
|
+
place_name: str,
|
|
74
|
+
theme: str = "Editorial Paper",
|
|
75
|
+
radius_meters: float = 500.0,
|
|
76
|
+
default_building_levels: int = 3,
|
|
77
|
+
) -> CityModel3D:
|
|
78
|
+
"""Geocode a place name (e.g. 'Kadıköy, İstanbul' or 'Eiffel Tower, Paris') and build a 3D City Model.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
place_name: Location query string to geocode via Nominatim.
|
|
82
|
+
theme: Name of the visual theme.
|
|
83
|
+
radius_meters: Radius around the geocoded center point in meters (default: 500m).
|
|
84
|
+
default_building_levels: Default floor count (default: 3).
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
CityModel3D instance.
|
|
88
|
+
"""
|
|
89
|
+
bbox = geocode_place_name(place_name, radius_meters=radius_meters)
|
|
90
|
+
return from_bbox(
|
|
91
|
+
bbox, theme=theme, name=place_name, default_building_levels=default_building_levels
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def from_geojson(
|
|
96
|
+
geojson_data: dict | str,
|
|
97
|
+
theme: str = "Editorial Paper",
|
|
98
|
+
name: str = "Custom 3D City",
|
|
99
|
+
default_building_levels: int = 3,
|
|
100
|
+
) -> CityModel3D:
|
|
101
|
+
"""Generate a 3D City Model directly from parsed or raw GeoJSON feature collections."""
|
|
102
|
+
return generate_3d_city(
|
|
103
|
+
geojson_data, theme=theme, name=name, default_levels=default_building_levels
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def list_themes() -> list[str]:
|
|
108
|
+
"""List all 12 available visual color themes."""
|
|
109
|
+
return list_theme_names()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
__all__ = [
|
|
113
|
+
"__version__",
|
|
114
|
+
"from_bbox",
|
|
115
|
+
"from_place",
|
|
116
|
+
"from_geojson",
|
|
117
|
+
"list_themes",
|
|
118
|
+
"BoundingBox",
|
|
119
|
+
"CityModel3D",
|
|
120
|
+
"BuildingMesh",
|
|
121
|
+
"RoadMesh",
|
|
122
|
+
"WaterMesh",
|
|
123
|
+
"TreeInstance",
|
|
124
|
+
"ColorTheme",
|
|
125
|
+
"ThemePalette",
|
|
126
|
+
"get_theme",
|
|
127
|
+
"list_theme_names",
|
|
128
|
+
"OsmDataFetcher",
|
|
129
|
+
"geocode_place_name",
|
|
130
|
+
"query_overpass",
|
|
131
|
+
"generate_3d_city",
|
|
132
|
+
"bundle_city_to_html",
|
|
133
|
+
"StandaloneHtmlBundler",
|
|
134
|
+
"export_to_glb",
|
|
135
|
+
"export_to_obj",
|
|
136
|
+
"export_to_geojson_3d",
|
|
137
|
+
"export_to_dxf_3d",
|
|
138
|
+
]
|