ThreeDimensionModeller 1.0.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.
- threedimensionmodeller-1.0.0/LICENSE.md +21 -0
- threedimensionmodeller-1.0.0/PKG-INFO +386 -0
- threedimensionmodeller-1.0.0/README.md +367 -0
- threedimensionmodeller-1.0.0/pyproject.toml +33 -0
- threedimensionmodeller-1.0.0/setup.cfg +4 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/__init__.py +8 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/__main__.py +6 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/about_page.py +200 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/check_system.py +521 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/cli.py +367 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/menu_language.py +754 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/menu_model.py +276 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/menu_painter.py +487 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/menu_session.py +118 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/model.py +835 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/self_management.py +79 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/system_log.py +92 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller/tui.py +475 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/PKG-INFO +386 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/SOURCES.txt +28 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/dependency_links.txt +1 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/entry_points.txt +2 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/requires.txt +4 -0
- threedimensionmodeller-1.0.0/src/ThreeDimensionModeller.egg-info/top_level.txt +1 -0
- threedimensionmodeller-1.0.0/tests/test_about.py +1074 -0
- threedimensionmodeller-1.0.0/tests/test_dependencies.py +69 -0
- threedimensionmodeller-1.0.0/tests/test_docs.py +83 -0
- threedimensionmodeller-1.0.0/tests/test_language.py +156 -0
- threedimensionmodeller-1.0.0/tests/test_model.py +250 -0
- threedimensionmodeller-1.0.0/tests/test_tui.py +299 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wilgat Wong <wilgat.wong@gmail.com>
|
|
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,386 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ThreeDimensionModeller
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: ThreeDimensionModeller builds a glTF model and an HTML viewer from outline images.
|
|
5
|
+
Author-email: Wilgat Wong <wilgat.wong@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudgen/ThreeDimensionModeller
|
|
8
|
+
Project-URL: Repository, https://github.com/cloudgen/ThreeDimensionModeller
|
|
9
|
+
Project-URL: Issues, https://github.com/cloudgen/ThreeDimensionModeller/issues
|
|
10
|
+
Keywords: CLI,TUI,glTF,3d,outline
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE.md
|
|
14
|
+
Requires-Dist: ChronicleLogger>=1.3.1
|
|
15
|
+
Requires-Dist: numpy>=2.3.0
|
|
16
|
+
Requires-Dist: opencv-python-headless>=5.0.0.93
|
|
17
|
+
Requires-Dist: scikit-image>=0.25.0
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# ThreeDimensionModeller - A glTF model and an HTML viewer from outline images
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+

|
|
24
|
+
[-purple.svg)](https://github.com/cloudgen/ciao)
|
|
25
|
+
[](https://github.com/cloudgen/ThreeDimensionModeller)
|
|
26
|
+
[]()
|
|
27
|
+
[](https://pypi.org/project/ThreeDimensionModeller/)
|
|
28
|
+
|
|
29
|
+
ThreeDimensionModeller builds one glTF model and one HTML viewer from outline images in a folder. The files are `model.glb` and `viewer.html`. Supported inputs are webp, png, jpg, and jpeg.
|
|
30
|
+
|
|
31
|
+
On a terminal, starting it with no arguments opens a text menu. The menu does not convert images by itself, and it does not call pip.
|
|
32
|
+
|
|
33
|
+
The sample conversion is [`sample-images/model/viewer.html`](https://cloudgen.github.io/ThreeDimensionModeller/sample-images/model/viewer.html). The picture is that page. The picture address is absolute, so the package index and GitHub both show it.
|
|
34
|
+
|
|
35
|
+
[](https://cloudgen.github.io/ThreeDimensionModeller/sample-images/model/viewer.html)
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- Text menu on a terminal: **model**, **system-log**, **language**, **self-management**, and **Exit**
|
|
40
|
+
- The first row shows the current folder and a local clock (`HH:MM:SS`) when the row has room
|
|
41
|
+
- Numbered rows line up. A rounded input box sits along the bottom, as wide as the terminal, with the name and version on the status line under the box
|
|
42
|
+
- **model** (1) lists **1** current folder, each subfolder, and **0** back. The chosen folder becomes one 3D model
|
|
43
|
+
- The typed verb `model` builds that model in the terminal and does not draw the menu. With no folder, it uses the current directory
|
|
44
|
+
- **system-log** (3) opens view-log, clear-log, and log-folder. **language** (4) picks the menu language. **self-management** (8) opens version, about, and the pip lifecycle rows
|
|
45
|
+
- Console script `three-dimension-modeller` and module entry `python -m ThreeDimensionModeller`
|
|
46
|
+
- Typed verbs: `help`, `version`, `about`, `model`, `self-install`, `version-check`, `self-update`, `self-uninstall`
|
|
47
|
+
- Checkout script `./convert.py` runs the same conversion
|
|
48
|
+
|
|
49
|
+
## Advantages
|
|
50
|
+
|
|
51
|
+
1. **A folder of outlines in, one model out.** `three-dimension-modeller model` builds a model from outline images in the current directory and does not draw the menu. On the menu, row **1 model** asks for the current folder or a subfolder, then writes `model.glb` and `viewer.html` in that folder's `model` directory. With no arguments on a terminal, the text menu opens and waits. With no terminal and no verb, the program prints help and returns 0. There is no `--json`.
|
|
52
|
+
2. **Built-in languages.** Row **4** lists thirteen languages: English, Simplified Chinese, Traditional Chinese, Spanish, Arabic, French, Portuguese, Russian, German, Japanese, Korean, Dutch, and Greek. The choice is saved for the next run. The note on row 1 follows the menu language.
|
|
53
|
+
3. **Lifecycle and diagnostics.** `version-check`, `self-update`, `self-install`, and `self-uninstall` are menu rows **84**–**87** and typed verbs. `self-uninstall` on the command line needs `--force`. They call pip and do not use root. **system-log** (**3**) views a log, clears a log, and shows the log folder. **about** (**83**) stays in English.
|
|
54
|
+
|
|
55
|
+
## Quick Installation
|
|
56
|
+
|
|
57
|
+
**Python dependencies:** `ChronicleLogger>=1.3.1`, `numpy>=2.3.0`, `opencv-python-headless>=5.0.0.93`, and `scikit-image>=0.25.0` (required). Pip installs them with ThreeDimensionModeller. The inputs are outline images already drawn. No model download and no external media tool are required.
|
|
58
|
+
|
|
59
|
+
### PyPI (registry)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install ThreeDimensionModeller
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This installs the console entry **`three-dimension-modeller`** and the package **`ThreeDimensionModeller`**. Packaging name SSOT is `pyproject.toml` `[project].name` = `ThreeDimensionModeller`. This tree is **1.0.0**. The PyPI badge above shows the live index.
|
|
66
|
+
|
|
67
|
+
### Local install (checkout)
|
|
68
|
+
|
|
69
|
+
From a checkout (editable / unreleased work):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/cloudgen/ThreeDimensionModeller.git
|
|
73
|
+
cd ThreeDimensionModeller
|
|
74
|
+
python3 -m venv venv
|
|
75
|
+
source venv/bin/activate # Windows: venv\Scripts\activate
|
|
76
|
+
pip install -e .
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Main menu
|
|
80
|
+
|
|
81
|
+
After install, on a terminal, `three-dimension-modeller` with no arguments prints this screen. The verb is bold and the note after the colon is italic. `9` leaves. `0` on a submenu goes back. After a command finishes, the main menu is shown again. A number that is not on the list prints an error and lets you choose again.
|
|
82
|
+
|
|
83
|
+
Picture of the English menu. Current directory `/tmp/clips`. The rows are the text the menu paints. The frame is the 80-column box.
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
$ three-dimension-modeller
|
|
87
|
+
Path: /tmp/clips 12:06:45
|
|
88
|
+
|
|
89
|
+
1. **model** : *build a 3D model from outline images in a chosen folder*
|
|
90
|
+
3. **system-log** : *view, clear, and the log folder*
|
|
91
|
+
4. **language** : *display language for this menu*
|
|
92
|
+
8. **self-management**: *version, about, and pip lifecycle*
|
|
93
|
+
9. **Exit** : *leave*
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
99
|
+
│ > │
|
|
100
|
+
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
101
|
+
ThreeDimensionModeller 1.0.0 │ main menu │ Up/Down • Enter
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**system-log** (3):
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
Path: /tmp/clips 12:06:45
|
|
108
|
+
|
|
109
|
+
31. **view-log** : *list a log file and show it*
|
|
110
|
+
32. **clear-log** : *empty one log file*
|
|
111
|
+
33. **log-folder**: *show the log folder*
|
|
112
|
+
0. **Back** : *return to the main menu*
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
118
|
+
│ > │
|
|
119
|
+
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
120
|
+
ThreeDimensionModeller 1.0.0 │ system-log │ Up/Down • Enter
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**language** (4). The short on each language row is that language’s own name. Numbers 40 and 54–59 are not printed. `0` goes back and does not save.
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
Path: /tmp/clips 12:06:46
|
|
127
|
+
|
|
128
|
+
41. **English** : *use English for this menu*
|
|
129
|
+
42. **简体中文** : *use 简体中文 for this menu*
|
|
130
|
+
43. **繁體中文** : *use 繁體中文 for this menu*
|
|
131
|
+
44. **Español** : *use Español for this menu*
|
|
132
|
+
45. **العربية** : *use العربية for this menu*
|
|
133
|
+
46. **Français** : *use Français for this menu*
|
|
134
|
+
47. **Português** : *use Português for this menu*
|
|
135
|
+
48. **Русский** : *use Русский for this menu*
|
|
136
|
+
49. **Deutsch** : *use Deutsch for this menu*
|
|
137
|
+
50. **日本語** : *use 日本語 for this menu*
|
|
138
|
+
51. **한국어** : *use 한국어 for this menu*
|
|
139
|
+
52. **Nederlands**: *use Nederlands for this menu*
|
|
140
|
+
53. **Ελληνικά** : *use Ελληνικά for this menu*
|
|
141
|
+
0. **Back** : *return to the main menu*
|
|
142
|
+
|
|
143
|
+
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
144
|
+
│ > │
|
|
145
|
+
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
146
|
+
ThreeDimensionModeller 1.0.0 │ language │ Up/Down • Enter
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**self-management** (8):
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
Path: /tmp/clips 14:05:09
|
|
153
|
+
|
|
154
|
+
82. **version** : *show the installed version*
|
|
155
|
+
83. **about** : *version and this computer*
|
|
156
|
+
84. **version-check** : *compare this install with pip*
|
|
157
|
+
85. **self-update** : *upgrade this package with pip*
|
|
158
|
+
86. **self-uninstall**: *remove this package with pip*
|
|
159
|
+
87. **self-install** : *install this package with pip*
|
|
160
|
+
0. **Back** : *return to the main menu*
|
|
161
|
+
|
|
162
|
+
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
163
|
+
│ > │
|
|
164
|
+
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
165
|
+
ThreeDimensionModeller 1.0.0 │ self-management │ Up/Down • Enter
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Choose a number, or type the command name in the box. The block caret appears in that box while it is focused.
|
|
169
|
+
|
|
170
|
+
## Usage
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
three-dimension-modeller
|
|
174
|
+
# or
|
|
175
|
+
python -m ThreeDimensionModeller
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
On a terminal, that opens the main menu above. It does not build a model yet, and it does not call pip. With no terminal, the same command prints help and returns 0.
|
|
179
|
+
|
|
180
|
+
**model** (1) opens a folder list: **1** current folder, then each subfolder, and **0** back. The chosen folder is built into `model.glb` and `viewer.html`. By default those files go in that folder's `model` directory. A `views.json` in the folder, or `--views`, names each outline with azimuth and elevation in degrees. `--grid` sets the voxel count on each axis (16 to 160, default 96). Any key on the result page returns to the main menu. The typed verb builds the model in the terminal and does not draw the menu:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
three-dimension-modeller model
|
|
184
|
+
three-dimension-modeller model photos --views views.json --grid 96
|
|
185
|
+
three-dimension-modeller model --output photos/built
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
three-dimension-modeller help
|
|
190
|
+
three-dimension-modeller version
|
|
191
|
+
three-dimension-modeller about
|
|
192
|
+
three-dimension-modeller model
|
|
193
|
+
three-dimension-modeller version-check
|
|
194
|
+
three-dimension-modeller self-update
|
|
195
|
+
three-dimension-modeller self-install
|
|
196
|
+
three-dimension-modeller self-uninstall --force
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`version` prints `ThreeDimensionModeller 1.0.0` and does not call pip. `about` shows one English page: the product identity, a host check of this computer, and a star box. It does not call pip. `model` uses the current directory when no folder is given and does not draw the menu. `help` prints usage.
|
|
200
|
+
|
|
201
|
+
`version-check` runs `python -m pip index versions ThreeDimensionModeller`. `self-update` runs `python -m pip install --upgrade ThreeDimensionModeller`. `self-install` runs `python -m pip install ThreeDimensionModeller`. `self-uninstall` runs `python -m pip uninstall -y ThreeDimensionModeller` and needs `--force` on the command line. Those pip verbs do not use sudo. Empty arguments do not install or update.
|
|
202
|
+
|
|
203
|
+
Exit codes: non-zero for an unknown verb, a missing folder, a bad views file, an empty visual hull, a pip failure, or a menu that cannot open. Menu **Exit** (9) returns 0. `model` returns 0 when the folder exists and the model is written. An empty folder returns 0 and does not load the vision stack.
|
|
204
|
+
|
|
205
|
+
Import for scripts (thin entry):
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from ThreeDimensionModeller import main
|
|
209
|
+
# interactive session; a terminal opens the text menu
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Screenshots
|
|
213
|
+
|
|
214
|
+
Each heading is the file name. The paragraph is what that picture shows: the words on the screen, the characters in the input box, or the scene. Package **1.0.0**. These pictures are captures of ThreeDimensionModeller. Row 1 is **model**. The folder board is `model-folder.png`. `model-viewer.png` is the converted model in `sample-images/model/viewer.html`, and that picture links to the viewer. The package index can fetch a picture only after that file is on the public `main` branch. Every picture address is an absolute `https` URL.
|
|
215
|
+
|
|
216
|
+
### `language-menu.png`
|
|
217
|
+
|
|
218
|
+
Row **4** has opened the language list. **41 English** is highlighted, with the note "use English for this menu." The other rows are **42 简体中文**, **43 繁體中文**, **44 Español**, **45 العربية**, **46 Français**, **47 Português**, **48 Русский**, **49 Deutsch**, **50 日本語**, **51 한국어**, **52 Nederlands**, and **53 Ελληνικά**. Each note says to use that language for this menu. **0 Back** says "return to the main menu." The path label is `Path`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `language`.
|
|
219
|
+
|
|
220
|
+

|
|
221
|
+
|
|
222
|
+
### `main-menu-en.png`
|
|
223
|
+
|
|
224
|
+
English main menu. There is no saved-language line above the box. The path label is `Path`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted: "build a 3D model from outline images in a chosen folder." Then **3 system-log** "view, clear, and the log folder," **4 language** "display language for this menu," **8 self-management** "version, about, and pip lifecycle," and **9 Exit** "leave." The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `main menu`.
|
|
225
|
+
|
|
226
|
+

|
|
227
|
+
|
|
228
|
+
### `main-menu-zh-hans.png`
|
|
229
|
+
|
|
230
|
+
Simplified Chinese main menu. The line above the box says `菜单语言是简体中文`. The path label is `路径`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted: "把所选文件夹中的轮廓图做成三维模型." **3** is `系统日志`, **4** is `语言`, **8** is `自我管理`, and **9** is `离开`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `主菜单`.
|
|
231
|
+
|
|
232
|
+

|
|
233
|
+
|
|
234
|
+
### `main-menu-zh-hant.png`
|
|
235
|
+
|
|
236
|
+
Traditional Chinese main menu. The line above the box says `選單語言是繁體中文`. The path label is `路徑`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted: "把所選資料夾中的輪廓圖做成三維模型." **3** is `系統日誌`, **4** is `語言`, **8** is `自我管理`, and **9** is `離開`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `主選單`.
|
|
237
|
+
|
|
238
|
+

|
|
239
|
+
|
|
240
|
+
### `main-menu-es.png`
|
|
241
|
+
|
|
242
|
+
Spanish main menu. The line above the box says `El idioma del menú es español`. The path label is `Ruta`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted: "construye un modelo 3D con los contornos de una carpeta elegida." **3** is `registro`, **4** is `idioma`, **8** is `autogestión`, and **9** is `Salir`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `menú principal`.
|
|
243
|
+
|
|
244
|
+

|
|
245
|
+
|
|
246
|
+
### `main-menu-ar.png`
|
|
247
|
+
|
|
248
|
+
Arabic main menu. The line above the box says `لغة القائمة هي العربية`. The path label is `المسار`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. The numbers stay on the left. Arabic words on each row are shaped and read right to left. **1 model** is highlighted and stays `model`: "يبني نموذجا ثلاثي الأبعاد من حدود المجلد المختار." **3** is `سجل النظام`, **4** is `لغة`, **8** is `إدارة ذاتية`, and **9** is `خروج`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `القائمة الرئيسية`.
|
|
249
|
+
|
|
250
|
+

|
|
251
|
+
|
|
252
|
+
### `main-menu-fr.png`
|
|
253
|
+
|
|
254
|
+
French main menu. The line above the box says `La langue du menu est le français`. The path label is `Chemin`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "construit un modèle 3D à partir des contours d'un dossier choisi." **3** is `journal`, **4** is `langue`, **8** is `autogestion`, and **9** is `Quitter`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `menu principal`.
|
|
255
|
+
|
|
256
|
+

|
|
257
|
+
|
|
258
|
+
### `main-menu-pt.png`
|
|
259
|
+
|
|
260
|
+
Portuguese main menu. The line above the box says `O idioma do menu é português`. The path label is `Caminho`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "constrói um modelo 3D a partir dos contornos de uma pasta escolhida." **3** is `registo`, **4** is `idioma`, **8** is `autogestão`, and **9** is `Sair`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `menu principal`.
|
|
261
|
+
|
|
262
|
+

|
|
263
|
+
|
|
264
|
+
### `main-menu-ru.png`
|
|
265
|
+
|
|
266
|
+
Russian main menu. The line above the box says `Язык меню — русский`. The path label is `Путь`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "собрать трёхмерную модель из контуров выбранной папки." **3** is `системный журнал`, **4** is `язык`, **8** is `самоуправление`, and **9** is `Выход`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `главное меню`.
|
|
267
|
+
|
|
268
|
+

|
|
269
|
+
|
|
270
|
+
### `main-menu-de.png`
|
|
271
|
+
|
|
272
|
+
German main menu. The line above the box says `Die Menüsprache ist Deutsch`. The path label is `Pfad`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "aus Umrissen eines gewählten Ordners ein 3D-Modell bauen." **3** is `Systemprotokoll`, **4** is `Sprache`, **8** is `Selbstverwaltung`, and **9** is `Beenden`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `Hauptmenü`.
|
|
273
|
+
|
|
274
|
+

|
|
275
|
+
|
|
276
|
+
### `main-menu-ja.png`
|
|
277
|
+
|
|
278
|
+
Japanese main menu. The line above the box says `メニューの言語は日本語`. The path label is `パス`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "選んだフォルダの輪郭画像から3Dモデルを作る." **3** is `システムログ`, **4** is `言語`, **8** is `自己管理`, and **9** is `終了`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `メインメニュー`.
|
|
279
|
+
|
|
280
|
+

|
|
281
|
+
|
|
282
|
+
### `main-menu-ko.png`
|
|
283
|
+
|
|
284
|
+
Korean main menu. The line above the box says `메뉴 언어는 한국어`. The path label is `경로`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "고른 폴더의 윤곽 이미지로 3D 모델을 만듭니다." **3** is `시스템 로그`, **4** is `언어`, **8** is `자기관리`, and **9** is `종료`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `주 메뉴`.
|
|
285
|
+
|
|
286
|
+

|
|
287
|
+
|
|
288
|
+
### `main-menu-nl.png`
|
|
289
|
+
|
|
290
|
+
Dutch main menu. The line above the box says `De menutaal is Nederlands`. The path label is `Pad`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "maak een 3D-model van contouren in een gekozen map." **3** is `systeemlog`, **4** is `taal`, **8** is `zelfbeheer`, and **9** is `Afsluiten`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `hoofdmenu`.
|
|
291
|
+
|
|
292
|
+

|
|
293
|
+
|
|
294
|
+
### `main-menu-el.png`
|
|
295
|
+
|
|
296
|
+
Greek main menu. The line above the box says `Η γλώσσα του μενού είναι ελληνικά`. The path label is `Διαδρομή`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 model** is highlighted and stays `model`: "φτιάχνει ένα τρισδιάστατο μοντέλο από τα περιγράμματα ενός φακέλου." **3** is `αρχείο καταγραφής`, **4** is `γλώσσα`, **8** is `αυτοδιαχείριση`, and **9** is `Έξοδος`. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `κύριο μενού`.
|
|
297
|
+
|
|
298
|
+

|
|
299
|
+
|
|
300
|
+
### `model-folder.png`
|
|
301
|
+
|
|
302
|
+
The folder board for row **1**. The path label is `Path`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. **1 current** is highlighted: "build a 3D model from outline images in this folder." **2 photos** says "build a 3D model from outline images in this subfolder." **0 Back** says "return to the main menu." The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `model`.
|
|
303
|
+
|
|
304
|
+

|
|
305
|
+
|
|
306
|
+
### `self-management.png`
|
|
307
|
+
|
|
308
|
+
Row **8** has opened self-management. **82 version** is highlighted: "show the installed version." Then **83 about** "version and this computer", **84 version-check** "compare this install with pip", **85 self-update** "upgrade this package with pip", **86 self-uninstall** "remove this package with pip", **87 self-install** "install this package with pip", and **0 Back** "return to the main menu." The path label is `Path`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `self-management`.
|
|
309
|
+
|
|
310
|
+

|
|
311
|
+
|
|
312
|
+
### `tui-about.png`
|
|
313
|
+
|
|
314
|
+
**about** (83) on the result page. The title is `ThreeDimensionModeller (1.0.0) — result`. The page prints `ThreeDimensionModeller 1.0.0`, `Domain: Build a glTF model and an HTML viewer from outline images in a folder`, `Runtime tools: none`, and `Entry points: three-dimension-modeller, python -m ThreeDimensionModeller`. The host check is stamped `2026-10-05 17:48:52.787448` and headed `[CHECK SYSTEM]:`. Visible lines include Python 3.12.11, C Library GCC 13.3.0, Ubuntu 24.04.5 LTS, amd64, the current user, the shell `/bin/bash`, the Python executable `python3`, python2 location, python3 location, an empty conda location, pyenv location, `Inside docker container: False`, and `Cython String: cpython-312-x86_64-linux-gnu`. The footer says `Up/Down scrolls this page.` and `Press a key to return to the main menu.` There is no input box and no clock. The page stays in English.
|
|
315
|
+
|
|
316
|
+

|
|
317
|
+
|
|
318
|
+
### `system-log.png`
|
|
319
|
+
|
|
320
|
+
Row **3** has opened system-log. **31 view-log** is highlighted: "list a log file and show it." Then **32 clear-log** "empty one log file", **33 log-folder** "show the log folder", and **0 Back** "return to the main menu." The path label is `Path`. The path is `/tmp/clips`. The clock is `17:48:52` on the right of that row. The input box shows `>` and no typed text. The status line says `ThreeDimensionModeller 1.0.0` and `system-log`.
|
|
321
|
+
|
|
322
|
+

|
|
323
|
+
|
|
324
|
+
### `model-viewer.png`
|
|
325
|
+
|
|
326
|
+
A capture of the converted model in `sample-images/model/viewer.html`. The page background is near black. The mesh is light gray and built from stacked outline slices: a wide upper mass, an opening through the middle, and a lower mass with a flat slab. The line at the bottom left reads "ThreeDimensionModeller — drag to orbit, wheel to zoom. model.glb is the glTF file." This is not a text-menu capture. The picture links to that viewer.
|
|
327
|
+
|
|
328
|
+
[](https://cloudgen.github.io/ThreeDimensionModeller/sample-images/model/viewer.html)
|
|
329
|
+
|
|
330
|
+
## Examples
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
cd /path/to/folder/with/outline-images
|
|
334
|
+
three-dimension-modeller
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
three-dimension-modeller version
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`version` prints `ThreeDimensionModeller 1.0.0` and does not call pip. A run that is not the text menu can also print ChronicleLogger status lines above that. The text menu keeps those lines off the screen.
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
three-dimension-modeller model --views views.json --grid 96
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
That builds `model/model.glb` and `model/viewer.html` from outline images in the current directory and does not draw the menu. On a terminal, row **1** asks for the current folder or a subfolder, then does the same build. `./convert.py` is the same build from a checkout. A views file lists each outline basename with azimuth and elevation in degrees. Without one, the outlines are spaced evenly around the object at elevation 0.
|
|
348
|
+
|
|
349
|
+
## Platform Compatibility
|
|
350
|
+
|
|
351
|
+
| Platform | Status |
|
|
352
|
+
|----------|--------|
|
|
353
|
+
| Linux | Primary; tested development path |
|
|
354
|
+
| macOS | Supported when CPython is on PATH |
|
|
355
|
+
| Windows | Supported when CPython is on PATH (venv activate differs) |
|
|
356
|
+
| Architectures | Any with CPython |
|
|
357
|
+
|
|
358
|
+
The text menu needs a terminal. With no terminal and no verb, the program prints help and returns 0. It does not wait.
|
|
359
|
+
|
|
360
|
+
## Related Projects
|
|
361
|
+
|
|
362
|
+
- [ThreeDimensionModeller on GitHub](https://github.com/cloudgen/ThreeDimensionModeller) — this program’s source
|
|
363
|
+
- [ThreeDimensionModeller on PyPI](https://pypi.org/project/ThreeDimensionModeller/) — this program on PyPI
|
|
364
|
+
- [OutlineImage on GitHub](https://github.com/cloudgen/OutlineImage) — writes a detailed outline image for each picture in a folder, and this program reads those images
|
|
365
|
+
- [OutlineImage on PyPI](https://pypi.org/project/OutlineImage/) — that program on PyPI
|
|
366
|
+
- [AnimeDlp](https://github.com/Wilgat/AnimeDlp) — command-line downloader for anime video sites
|
|
367
|
+
- [ChronicleLogger](https://github.com/Wilgat/ChronicleLogger) — status logger this program depends on (`ChronicleLogger>=1.3.1`)
|
|
368
|
+
- [VideoSpeed](https://github.com/Wilgat/VideoSpeed) — cuts, changes speed, and boomerangs a clip. That program is not this one
|
|
369
|
+
- [CIAO](https://github.com/cloudgen/ciao) — Caution, Intentional, Anti-fragile, Over-engineered
|
|
370
|
+
- [CIAO-Lite](https://github.com/cloudgen/ciao-lite) — short agent contract
|
|
371
|
+
- [safe-rm](https://github.com/cloudgen/safe-rm) — guarded `rm`
|
|
372
|
+
|
|
373
|
+
## Contributing
|
|
374
|
+
|
|
375
|
+
1. Keep product law under `docs/requirements/` in sync when behavior changes.
|
|
376
|
+
2. Prefer small, CIAO-safe changes. The model build lives in `src/ThreeDimensionModeller/model.py`. `./convert.py` calls that module.
|
|
377
|
+
3. Version dual SSOT: bump **`pyproject.toml`** and **`src/ThreeDimensionModeller/__init__.py`** `__version__` together.
|
|
378
|
+
4. Open issues and pull requests on GitHub.
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
MIT — see [`LICENSE.md`](./LICENSE.md). Also declared in `pyproject.toml`.
|
|
383
|
+
|
|
384
|
+
## Last Update
|
|
385
|
+
|
|
386
|
+
2026-10-05 — **1.0.0** working tree: the package name is **ThreeDimensionModeller** and the console script is `three-dimension-modeller`. The public source is `https://github.com/cloudgen/ThreeDimensionModeller`. `model` builds `model.glb` and `viewer.html` from outline images in a folder. The default directory is that folder's `model`. Menu row 1 lists **1** current folder, each subfolder, and **0** back, then runs that build. `screenshots/model-viewer.png` is a capture of `sample-images/model/viewer.html`, and that picture links to the viewer. Picture addresses are absolute `https` URLs. Menu pictures are captures of this product, including the folder board. Version badge matches `pyproject.toml` and `__version__`. `ChronicleLogger>=1.3.1`, `numpy>=2.3.0`, `opencv-python-headless>=5.0.0.93`, and `scikit-image>=0.25.0` are required.
|