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.
@@ -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
+ [![CI](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml/badge.svg)](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml)
46
+ [![PyPI version](https://img.shields.io/pypi/v/osm2threejs.svg?color=38bdf8)](https://pypi.org/project/osm2threejs/)
47
+ [![Python version support](https://img.shields.io/pypi/pyversions/osm2threejs.svg?color=10b981)](https://pypi.org/project/osm2threejs/)
48
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-818cf8.svg)](https://yusufeminoglu.github.io/osm2threejs/)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
50
+ [![Code style: Ruff](https://img.shields.io/badge/code%20style-ruff-D7FF64.svg)](https://docs.astral.sh/ruff/)
51
+ [![Test Coverage](https://img.shields.io/badge/coverage-70%25%2B-brightgreen.svg)](#-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
+ [![CI](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml/badge.svg)](https://github.com/YusufEminoglu/osm2threejs/actions/workflows/ci.yml)
6
+ [![PyPI version](https://img.shields.io/pypi/v/osm2threejs.svg?color=38bdf8)](https://pypi.org/project/osm2threejs/)
7
+ [![Python version support](https://img.shields.io/pypi/pyversions/osm2threejs.svg?color=10b981)](https://pypi.org/project/osm2threejs/)
8
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-818cf8.svg)](https://yusufeminoglu.github.io/osm2threejs/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+ [![Code style: Ruff](https://img.shields.io/badge/code%20style-ruff-D7FF64.svg)](https://docs.astral.sh/ruff/)
11
+ [![Test Coverage](https://img.shields.io/badge/coverage-70%25%2B-brightgreen.svg)](#-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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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
+ ]