phg-vis 1.3.2__tar.gz → 1.4.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.
- {phg_vis-1.3.2 → phg_vis-1.4.0}/PKG-INFO +56 -1
- phg_vis-1.3.2/phg_vis.egg-info/PKG-INFO → phg_vis-1.4.0/README.md +63 -28
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/__init__.py +113 -42
- phg_vis-1.4.0/phg/ai_bridge.py +174 -0
- phg_vis-1.4.0/phg/gcu_api.py +709 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/pipe_string_phg.py +144 -116
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/shader_render.py +26 -12
- phg_vis-1.4.0/phg/visphg.py +79 -0
- phg_vis-1.4.0/phg/web_three.py +164 -0
- phg_vis-1.3.2/README.md → phg_vis-1.4.0/phg_vis.egg-info/PKG-INFO +70 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg_vis.egg-info/SOURCES.txt +4 -0
- phg_vis-1.4.0/phg_vis.egg-info/requires.txt +6 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/setup.py +8 -3
- phg_vis-1.3.2/phg/visphg.py +0 -55
- {phg_vis-1.3.2 → phg_vis-1.4.0}/LICENSE +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/MANIFEST.in +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/phg_to_shader.py +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/GCU.dll +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/dragpad.exe +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/dragpad_config.ini +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/freeglut.dll +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/imgui/main.lua +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/lua.dll +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/script.phg +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/sqlite3.dll +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/vis.exe +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/vis.ini +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg/vis/zlib1.dll +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg_vis.egg-info/dependency_links.txt +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/phg_vis.egg-info/top_level.txt +0 -0
- {phg_vis-1.3.2 → phg_vis-1.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: phg_vis
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: A package for the PHG modeling language and 3D visualization tool.
|
|
5
5
|
Home-page: https://github.com/panguojun/Coordinate-System
|
|
6
6
|
Author: romeosoft
|
|
@@ -12,6 +12,11 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
12
12
|
Requires-Python: >=3.8
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
+
Requires-Dist: psutil
|
|
16
|
+
Provides-Extra: shader
|
|
17
|
+
Requires-Dist: numpy; extra == "shader"
|
|
18
|
+
Requires-Dist: pygame; extra == "shader"
|
|
19
|
+
Requires-Dist: PyOpenGL; extra == "shader"
|
|
15
20
|
|
|
16
21
|
# PHG - Python Hypergraphics Library
|
|
17
22
|
|
|
@@ -27,6 +32,8 @@ PHG (Python Hypergraphics) is a powerful 3D modeling and visualization library t
|
|
|
27
32
|
- **Pipe Visualization** - Specialized system for visualizing pipe structures with world/local coordinate support
|
|
28
33
|
- **Shader Conversion** - Convert PHG scripts to GLSL shaders for GPU rendering
|
|
29
34
|
- **Dual Rendering Modes** - Both real-time visualization (vis.exe) and offscreen rendering
|
|
35
|
+
- **AI Parser Bridge** - Use DGE++ PHG parser to normalize/enhance scripts before visualization
|
|
36
|
+
- **Web Viewer** - Export OBJ and view in a three.js browser viewer
|
|
30
37
|
- **Python Integration** - Comprehensive Python API for all features
|
|
31
38
|
|
|
32
39
|
---
|
|
@@ -42,6 +49,11 @@ Or install from source:
|
|
|
42
49
|
pip install phg
|
|
43
50
|
```
|
|
44
51
|
|
|
52
|
+
Shader renderer dependencies (optional):
|
|
53
|
+
```bash
|
|
54
|
+
pip install phg_vis[shader]
|
|
55
|
+
```
|
|
56
|
+
|
|
45
57
|
---
|
|
46
58
|
|
|
47
59
|
## 🚀 Quick Start
|
|
@@ -86,6 +98,49 @@ phg.image(scene, filename="tower.png")
|
|
|
86
98
|
phg.image("sphere(5);|||view=2 width=1920 height=1080", filename="top_view.png")
|
|
87
99
|
```
|
|
88
100
|
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## ✨ Unified Visualization API
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import phg
|
|
107
|
+
|
|
108
|
+
# Traditional vis.exe
|
|
109
|
+
phg.visualize("box(10);", mode="vis")
|
|
110
|
+
|
|
111
|
+
# Shader ray-march preview (GLSL)
|
|
112
|
+
phg.visualize("sphere(5);", mode="shader", width=800, height=600)
|
|
113
|
+
|
|
114
|
+
# Web (three.js) viewer
|
|
115
|
+
phg.visualize("box(10);", mode="web", out_html="view.html")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### AI Parser Bridge (for improved PHG)
|
|
119
|
+
Use DGE++ PHG parser to normalize/enhance scripts before visualization:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import phg
|
|
123
|
+
|
|
124
|
+
phg.visualize(script, mode="vis", ai=True)
|
|
125
|
+
phg.visualize(script, mode="shader", ai=True)
|
|
126
|
+
phg.visualize(script, mode="web", ai=True, out_html="ai_view.html")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Environment override (optional):
|
|
130
|
+
```
|
|
131
|
+
set PHG_AI_ROOT=C:\Users\18858\Documents\_AILab\DGE++\PHG
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Web live server (serves HTML + OBJ):
|
|
135
|
+
```python
|
|
136
|
+
phg.web_serve(script, host="127.0.0.1", port=8766, ai_root=None)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Notes for web viewer:
|
|
140
|
+
- Uses three.js CDN (requires network access)
|
|
141
|
+
- Uses AI bridge to export OBJ; ensure DGE++ is available
|
|
142
|
+
- Use `web_serve` to avoid file:// loader restrictions
|
|
143
|
+
|
|
89
144
|
---
|
|
90
145
|
|
|
91
146
|
## 📖 Syntax Reference
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: phg_vis
|
|
3
|
-
Version: 1.3.2
|
|
4
|
-
Summary: A package for the PHG modeling language and 3D visualization tool.
|
|
5
|
-
Home-page: https://github.com/panguojun/Coordinate-System
|
|
6
|
-
Author: romeosoft
|
|
7
|
-
Author-email: 18858146@qq.com
|
|
8
|
-
Platform: Windows
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
-
Requires-Python: >=3.8
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
|
|
16
1
|
# PHG - Python Hypergraphics Library
|
|
17
2
|
|
|
18
3
|
PHG (Python Hypergraphics) is a powerful 3D modeling and visualization library that combines a minimalist modeling language with Python integration. It provides procedural 3D scene generation, shader-based rendering, and specialized pipe system visualization.
|
|
@@ -25,26 +10,33 @@ PHG (Python Hypergraphics) is a powerful 3D modeling and visualization library t
|
|
|
25
10
|
- **Hierarchical Modeling** - Support for nested nodes and transform inheritance
|
|
26
11
|
- **Parametric Design** - Flexible property system and function definitions
|
|
27
12
|
- **Pipe Visualization** - Specialized system for visualizing pipe structures with world/local coordinate support
|
|
28
|
-
- **Shader Conversion** - Convert PHG scripts to GLSL shaders for GPU rendering
|
|
29
|
-
- **Dual Rendering Modes** - Both real-time visualization (vis.exe) and offscreen rendering
|
|
30
|
-
- **
|
|
13
|
+
- **Shader Conversion** - Convert PHG scripts to GLSL shaders for GPU rendering
|
|
14
|
+
- **Dual Rendering Modes** - Both real-time visualization (vis.exe) and offscreen rendering
|
|
15
|
+
- **AI Parser Bridge** - Use DGE++ PHG parser to normalize/enhance scripts before visualization
|
|
16
|
+
- **Web Viewer** - Export OBJ and view in a three.js browser viewer
|
|
17
|
+
- **Python Integration** - Comprehensive Python API for all features
|
|
31
18
|
|
|
32
19
|
---
|
|
33
20
|
|
|
34
21
|
## 📦 Installation
|
|
35
22
|
|
|
36
23
|
```bash
|
|
37
|
-
pip install phg_vis
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Or install from source:
|
|
41
|
-
```bash
|
|
42
|
-
pip install phg
|
|
43
|
-
```
|
|
24
|
+
pip install phg_vis
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install from source:
|
|
28
|
+
```bash
|
|
29
|
+
pip install phg
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Shader renderer dependencies (optional):
|
|
33
|
+
```bash
|
|
34
|
+
pip install phg_vis[shader]
|
|
35
|
+
```
|
|
44
36
|
|
|
45
37
|
---
|
|
46
38
|
|
|
47
|
-
## 🚀 Quick Start
|
|
39
|
+
## 🚀 Quick Start
|
|
48
40
|
|
|
49
41
|
### Python Usage
|
|
50
42
|
|
|
@@ -83,8 +75,51 @@ scene = """
|
|
|
83
75
|
phg.image(scene, filename="tower.png")
|
|
84
76
|
|
|
85
77
|
# Method 3: Multi-view rendering
|
|
86
|
-
phg.image("sphere(5);|||view=2 width=1920 height=1080", filename="top_view.png")
|
|
87
|
-
```
|
|
78
|
+
phg.image("sphere(5);|||view=2 width=1920 height=1080", filename="top_view.png")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ✨ Unified Visualization API
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import phg
|
|
87
|
+
|
|
88
|
+
# Traditional vis.exe
|
|
89
|
+
phg.visualize("box(10);", mode="vis")
|
|
90
|
+
|
|
91
|
+
# Shader ray-march preview (GLSL)
|
|
92
|
+
phg.visualize("sphere(5);", mode="shader", width=800, height=600)
|
|
93
|
+
|
|
94
|
+
# Web (three.js) viewer
|
|
95
|
+
phg.visualize("box(10);", mode="web", out_html="view.html")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### AI Parser Bridge (for improved PHG)
|
|
99
|
+
Use DGE++ PHG parser to normalize/enhance scripts before visualization:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import phg
|
|
103
|
+
|
|
104
|
+
phg.visualize(script, mode="vis", ai=True)
|
|
105
|
+
phg.visualize(script, mode="shader", ai=True)
|
|
106
|
+
phg.visualize(script, mode="web", ai=True, out_html="ai_view.html")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Environment override (optional):
|
|
110
|
+
```
|
|
111
|
+
set PHG_AI_ROOT=C:\Users\18858\Documents\_AILab\DGE++\PHG
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Web live server (serves HTML + OBJ):
|
|
115
|
+
```python
|
|
116
|
+
phg.web_serve(script, host="127.0.0.1", port=8766, ai_root=None)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Notes for web viewer:
|
|
120
|
+
- Uses three.js CDN (requires network access)
|
|
121
|
+
- Uses AI bridge to export OBJ; ensure DGE++ is available
|
|
122
|
+
- Use `web_serve` to avoid file:// loader restrictions
|
|
88
123
|
|
|
89
124
|
---
|
|
90
125
|
|
|
@@ -11,21 +11,33 @@ Main Features:
|
|
|
11
11
|
- Multiple pipe visualization support
|
|
12
12
|
- Real-time and image rendering capabilities
|
|
13
13
|
|
|
14
|
-
Version: 1.
|
|
15
|
-
Author: PanGuoJun
|
|
16
|
-
License: MIT
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
from .
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
Version: 1.4.0
|
|
15
|
+
Author: PanGuoJun
|
|
16
|
+
License: MIT
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
import tempfile
|
|
21
|
+
|
|
22
|
+
from .visphg import vis, image
|
|
23
|
+
from .shader_render import ShaderRenderer, render_shader
|
|
24
|
+
from .phg_to_shader import PHGToShaderConverter, phg_to_shader
|
|
25
|
+
from .pipe_string_phg import (
|
|
26
|
+
world_to_local_pipe_str,
|
|
27
|
+
local_pipe_to_phg,
|
|
28
|
+
world_pipe_to_phg,
|
|
29
|
+
world_pipestr_vis,
|
|
30
|
+
local_pipestr_vis,
|
|
31
|
+
multiple_pipes_vis
|
|
32
|
+
)
|
|
33
|
+
from .ai_bridge import (
|
|
34
|
+
compile_ai_phg,
|
|
35
|
+
vis_ai,
|
|
36
|
+
image_ai,
|
|
37
|
+
export_ai_obj,
|
|
38
|
+
web_view_ai,
|
|
39
|
+
)
|
|
40
|
+
from .web_three import write_three_view_html, serve_three_view
|
|
29
41
|
|
|
30
42
|
# Extend ShaderRenderer class to support direct PHG rendering
|
|
31
43
|
class PHGShaderRenderer(ShaderRenderer):
|
|
@@ -52,8 +64,8 @@ class PHGShaderRenderer(ShaderRenderer):
|
|
|
52
64
|
|
|
53
65
|
return self.render_shader(shader_code, duration, interactive)
|
|
54
66
|
|
|
55
|
-
# Convenience functions
|
|
56
|
-
def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Renderer"):
|
|
67
|
+
# Convenience functions
|
|
68
|
+
def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Renderer"):
|
|
57
69
|
"""
|
|
58
70
|
Directly render PHG script
|
|
59
71
|
|
|
@@ -79,7 +91,7 @@ def convert_phg_to_shader(phg_script: str) -> str:
|
|
|
79
91
|
Returns:
|
|
80
92
|
shader_code: GLSL shader code
|
|
81
93
|
"""
|
|
82
|
-
return phg_to_shader(phg_script)
|
|
94
|
+
return phg_to_shader(phg_script)
|
|
83
95
|
|
|
84
96
|
def visualize_pipe_variants(pipe_variants, start_position=None, colors=None, coordinate_system='world'):
|
|
85
97
|
"""
|
|
@@ -262,8 +274,8 @@ def generate_pipe_variants_from_rules(base_pipe, num_variants=5, apply_rules=Non
|
|
|
262
274
|
return variants[:num_variants]
|
|
263
275
|
|
|
264
276
|
# Enhanced pipe visualization with transformation support
|
|
265
|
-
def visualize_pipe_with_transformations(pipe_string, start_position=None,
|
|
266
|
-
transformations=None, show_variants=3):
|
|
277
|
+
def visualize_pipe_with_transformations(pipe_string, start_position=None,
|
|
278
|
+
transformations=None, show_variants=3):
|
|
267
279
|
"""
|
|
268
280
|
Visualize a pipe string along with its transformed variants
|
|
269
281
|
|
|
@@ -284,23 +296,82 @@ def visualize_pipe_with_transformations(pipe_string, start_position=None,
|
|
|
284
296
|
)
|
|
285
297
|
|
|
286
298
|
# Create comparison visualization
|
|
287
|
-
return visualize_pipe_variants(variants, start_position)
|
|
299
|
+
return visualize_pipe_variants(variants, start_position)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def web_view(script: str, out_html: str = "phg_view.html", out_obj: str = None,
|
|
303
|
+
ai_root: str = None, title: str = "PHG Web Viewer") -> str:
|
|
304
|
+
"""
|
|
305
|
+
Export OBJ via AI parser and write a three.js HTML viewer.
|
|
306
|
+
"""
|
|
307
|
+
return web_view_ai(script, out_html=out_html, out_obj=out_obj, ai_root=ai_root, title=title)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def web_serve(script: str, host: str = "127.0.0.1", port: int = 8766,
|
|
311
|
+
ai_root: str = None, title: str = "PHG Web Viewer") -> str:
|
|
312
|
+
"""
|
|
313
|
+
Export OBJ via AI parser, write HTML, and serve with a local HTTP server.
|
|
314
|
+
"""
|
|
315
|
+
temp_dir = tempfile.mkdtemp(prefix="phg_web_")
|
|
316
|
+
out_obj = os.path.join(temp_dir, "scene.obj")
|
|
317
|
+
out_html = os.path.join(temp_dir, "viewer.html")
|
|
318
|
+
web_view_ai(script, out_html=out_html, out_obj=out_obj, ai_root=ai_root, title=title)
|
|
319
|
+
return serve_three_view(out_obj, html_path=out_html, host=host, port=port, title=title)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def visualize(script: str, mode: str = "vis", ai: bool = False, **kwargs):
|
|
323
|
+
"""
|
|
324
|
+
Unified visualization entrypoint.
|
|
325
|
+
mode: vis | image | shader | web
|
|
326
|
+
ai: use AI parser (DGE++) to normalize/expand before visualization
|
|
327
|
+
"""
|
|
328
|
+
mode = (mode or "vis").lower()
|
|
329
|
+
ai_root = kwargs.pop("ai_root", None)
|
|
330
|
+
|
|
331
|
+
if mode in ("vis", "native", "exe"):
|
|
332
|
+
return vis_ai(script, ai_root=ai_root) if ai else vis(script)
|
|
333
|
+
|
|
334
|
+
if mode in ("image", "img", "png"):
|
|
335
|
+
filename = kwargs.pop("filename", "shot.png")
|
|
336
|
+
return image_ai(script, filename=filename, ai_root=ai_root) if ai else image(script, filename=filename)
|
|
337
|
+
|
|
338
|
+
if mode in ("shader", "ray", "rt"):
|
|
339
|
+
phg_script = compile_ai_phg(script, ai_root=ai_root, include_setup=True) if ai else script
|
|
340
|
+
return render_phg(phg_script, **kwargs)
|
|
341
|
+
|
|
342
|
+
if mode in ("web", "three"):
|
|
343
|
+
out_html = kwargs.pop("out_html", "phg_view.html")
|
|
344
|
+
out_obj = kwargs.pop("out_obj", None)
|
|
345
|
+
title = kwargs.pop("title", "PHG Web Viewer")
|
|
346
|
+
return web_view_ai(script, out_html=out_html, out_obj=out_obj, ai_root=ai_root, title=title)
|
|
347
|
+
|
|
348
|
+
raise ValueError(f"Unknown mode: {mode}")
|
|
288
349
|
|
|
289
|
-
__all__ = [
|
|
290
|
-
# Core visualization functions
|
|
291
|
-
'vis',
|
|
292
|
-
'image',
|
|
350
|
+
__all__ = [
|
|
351
|
+
# Core visualization functions
|
|
352
|
+
'vis',
|
|
353
|
+
'image',
|
|
354
|
+
'visualize',
|
|
293
355
|
|
|
294
356
|
# Shader rendering
|
|
295
357
|
'ShaderRenderer',
|
|
296
358
|
'render_shader',
|
|
297
359
|
'render_phg',
|
|
298
|
-
'PHGShaderRenderer',
|
|
360
|
+
'PHGShaderRenderer',
|
|
299
361
|
|
|
300
362
|
# PHG conversion
|
|
301
363
|
'PHGToShaderConverter',
|
|
302
|
-
'phg_to_shader',
|
|
303
|
-
'convert_phg_to_shader',
|
|
364
|
+
'phg_to_shader',
|
|
365
|
+
'convert_phg_to_shader',
|
|
366
|
+
'compile_ai_phg',
|
|
367
|
+
'vis_ai',
|
|
368
|
+
'image_ai',
|
|
369
|
+
'export_ai_obj',
|
|
370
|
+
'web_view',
|
|
371
|
+
'web_view_ai',
|
|
372
|
+
'web_serve',
|
|
373
|
+
'write_three_view_html',
|
|
374
|
+
'serve_three_view',
|
|
304
375
|
|
|
305
376
|
# Pipe visualization
|
|
306
377
|
'world_pipe_to_phg',
|
|
@@ -313,17 +384,17 @@ __all__ = [
|
|
|
313
384
|
'visualize_pipe_variants',
|
|
314
385
|
'create_pipe_comparison_grid',
|
|
315
386
|
'generate_pipe_variants_from_rules',
|
|
316
|
-
'visualize_pipe_with_transformations',
|
|
317
|
-
]
|
|
318
|
-
|
|
319
|
-
__version__ = "1.
|
|
320
|
-
__author__ = "PanGuoJun"
|
|
321
|
-
__description__ = "Python Hypergraphics Library"
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
print(f"PHG {__version__} - {__description__}")
|
|
325
|
-
print("[OK] Visualization module loaded")
|
|
326
|
-
print("[OK] Shader converter loaded")
|
|
327
|
-
print("[OK] Pipe visualization loaded")
|
|
328
|
-
print("[OK] Multiple pipe visualization support loaded")
|
|
329
|
-
print("[OK] Pipe transformation utilities loaded")
|
|
387
|
+
'visualize_pipe_with_transformations',
|
|
388
|
+
]
|
|
389
|
+
|
|
390
|
+
__version__ = "1.4.0"
|
|
391
|
+
__author__ = "PanGuoJun"
|
|
392
|
+
__description__ = "Python Hypergraphics Library"
|
|
393
|
+
|
|
394
|
+
if os.environ.get("PHG_VERBOSE"):
|
|
395
|
+
print(f"PHG {__version__} - {__description__}")
|
|
396
|
+
print("[OK] Visualization module loaded")
|
|
397
|
+
print("[OK] Shader converter loaded")
|
|
398
|
+
print("[OK] Pipe visualization loaded")
|
|
399
|
+
print("[OK] Multiple pipe visualization support loaded")
|
|
400
|
+
print("[OK] Pipe transformation utilities loaded")
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AI bridge for PHG (DGE++ parser -> normalized PHG -> vis.exe / web).
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
import tempfile
|
|
12
|
+
from typing import Any, Dict, Iterable, List, Optional
|
|
13
|
+
|
|
14
|
+
from .visphg import vis as _vis, image as _image
|
|
15
|
+
from .web_three import write_three_view_html
|
|
16
|
+
|
|
17
|
+
DEFAULT_AI_ROOT = r"C:\Users\18858\Documents\_AILab\DGE++\PHG"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def resolve_ai_root(ai_root: Optional[str] = None) -> str:
|
|
21
|
+
root = ai_root or os.environ.get("PHG_AI_ROOT") or DEFAULT_AI_ROOT
|
|
22
|
+
if not os.path.isdir(root):
|
|
23
|
+
raise FileNotFoundError(
|
|
24
|
+
f"AI PHG root not found: {root}. "
|
|
25
|
+
"Set PHG_AI_ROOT or pass ai_root explicitly."
|
|
26
|
+
)
|
|
27
|
+
return root
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _run_ai_cli(args: List[str], ai_root: Optional[str] = None, timeout: int = 120) -> subprocess.CompletedProcess:
|
|
31
|
+
root = resolve_ai_root(ai_root)
|
|
32
|
+
cmd = [sys.executable, "-m", "phg"] + args
|
|
33
|
+
return subprocess.run(
|
|
34
|
+
cmd,
|
|
35
|
+
cwd=root,
|
|
36
|
+
capture_output=True,
|
|
37
|
+
text=True,
|
|
38
|
+
timeout=timeout,
|
|
39
|
+
check=False,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _write_temp_phg(script: str) -> str:
|
|
44
|
+
fd, path = tempfile.mkstemp(suffix=".phg")
|
|
45
|
+
os.close(fd)
|
|
46
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
47
|
+
f.write(script)
|
|
48
|
+
return path
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def dump_scene(script: str, ai_root: Optional[str] = None) -> Dict[str, Any]:
|
|
52
|
+
"""
|
|
53
|
+
Use AI PHG (DGE++) to parse script and dump scene JSON.
|
|
54
|
+
"""
|
|
55
|
+
phg_path = _write_temp_phg(script)
|
|
56
|
+
fd, json_path = tempfile.mkstemp(suffix=".json")
|
|
57
|
+
os.close(fd)
|
|
58
|
+
try:
|
|
59
|
+
proc = _run_ai_cli(["dump", phg_path, "--out", json_path], ai_root=ai_root)
|
|
60
|
+
if proc.returncode != 0:
|
|
61
|
+
raise RuntimeError(proc.stderr.strip() or proc.stdout.strip() or "AI dump failed")
|
|
62
|
+
with open(json_path, "r", encoding="utf-8") as f:
|
|
63
|
+
return json.load(f)
|
|
64
|
+
finally:
|
|
65
|
+
for p in (phg_path, json_path):
|
|
66
|
+
try:
|
|
67
|
+
os.remove(p)
|
|
68
|
+
except OSError:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _format_value(value: Any) -> str:
|
|
73
|
+
if value is None:
|
|
74
|
+
return ""
|
|
75
|
+
if isinstance(value, bool):
|
|
76
|
+
return "1" if value else "0"
|
|
77
|
+
if isinstance(value, (int, float)):
|
|
78
|
+
return str(value)
|
|
79
|
+
if isinstance(value, (list, tuple)):
|
|
80
|
+
return ",".join(str(v) for v in value)
|
|
81
|
+
return str(value)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _emit_props(props: Dict[str, Any], indent: str) -> List[str]:
|
|
85
|
+
lines = []
|
|
86
|
+
for key, value in props.items():
|
|
87
|
+
val = _format_value(value)
|
|
88
|
+
if val == "":
|
|
89
|
+
lines.append(f"{indent}{key};")
|
|
90
|
+
else:
|
|
91
|
+
lines.append(f"{indent}{key}:{val};")
|
|
92
|
+
return lines
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _emit_node(node: Dict[str, Any], indent: str = " ") -> List[str]:
|
|
96
|
+
name = node.get("name", "node")
|
|
97
|
+
props = node.get("props", {}) or {}
|
|
98
|
+
children = node.get("children", []) or []
|
|
99
|
+
|
|
100
|
+
lines = [f"{indent}{name}{{"]
|
|
101
|
+
lines.extend(_emit_props(props, indent + " "))
|
|
102
|
+
for child in children:
|
|
103
|
+
lines.extend(_emit_node(child, indent + " "))
|
|
104
|
+
lines.append(f"{indent}}}")
|
|
105
|
+
return lines
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def scene_to_phg(scene: Dict[str, Any], include_setup: bool = True) -> str:
|
|
109
|
+
"""
|
|
110
|
+
Convert AI scene JSON (dump) to normalized PHG script.
|
|
111
|
+
"""
|
|
112
|
+
root_props = scene.get("props", {}) or {}
|
|
113
|
+
root_children = scene.get("children", []) or []
|
|
114
|
+
|
|
115
|
+
lines = ["{"]
|
|
116
|
+
if root_props:
|
|
117
|
+
# Preserve root-level props by creating a synthetic node.
|
|
118
|
+
root_node = {
|
|
119
|
+
"name": scene.get("name", "root"),
|
|
120
|
+
"props": root_props,
|
|
121
|
+
"children": root_children,
|
|
122
|
+
}
|
|
123
|
+
lines.extend(_emit_node(root_node, indent=" "))
|
|
124
|
+
else:
|
|
125
|
+
for child in root_children:
|
|
126
|
+
lines.extend(_emit_node(child, indent=" "))
|
|
127
|
+
lines.append("}")
|
|
128
|
+
if include_setup:
|
|
129
|
+
lines.append("setup_draw();")
|
|
130
|
+
return "\n".join(lines)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def compile_ai_phg(script: str, ai_root: Optional[str] = None, include_setup: bool = True) -> str:
|
|
134
|
+
scene = dump_scene(script, ai_root=ai_root)
|
|
135
|
+
return scene_to_phg(scene, include_setup=include_setup)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def vis_ai(script: str, ai_root: Optional[str] = None) -> None:
|
|
139
|
+
phg_script = compile_ai_phg(script, ai_root=ai_root, include_setup=True)
|
|
140
|
+
_vis(phg_script)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def image_ai(script: str, filename: str = "shot.png", ai_root: Optional[str] = None) -> None:
|
|
144
|
+
phg_script = compile_ai_phg(script, ai_root=ai_root, include_setup=True)
|
|
145
|
+
_image(phg_script, filename=filename)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def export_ai_obj(script: str, out_obj: str, ai_root: Optional[str] = None) -> str:
|
|
149
|
+
phg_path = _write_temp_phg(script)
|
|
150
|
+
try:
|
|
151
|
+
proc = _run_ai_cli(["export", phg_path, "--out", out_obj], ai_root=ai_root)
|
|
152
|
+
if proc.returncode != 0:
|
|
153
|
+
raise RuntimeError(proc.stderr.strip() or proc.stdout.strip() or "AI export failed")
|
|
154
|
+
finally:
|
|
155
|
+
try:
|
|
156
|
+
os.remove(phg_path)
|
|
157
|
+
except OSError:
|
|
158
|
+
pass
|
|
159
|
+
return out_obj
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def web_view_ai(
|
|
163
|
+
script: str,
|
|
164
|
+
out_html: str,
|
|
165
|
+
out_obj: Optional[str] = None,
|
|
166
|
+
ai_root: Optional[str] = None,
|
|
167
|
+
title: str = "PHG Web Viewer",
|
|
168
|
+
) -> str:
|
|
169
|
+
if out_obj is None:
|
|
170
|
+
base, _ = os.path.splitext(out_html)
|
|
171
|
+
out_obj = base + ".obj"
|
|
172
|
+
export_ai_obj(script, out_obj, ai_root=ai_root)
|
|
173
|
+
write_three_view_html(out_obj, out_html, title=title)
|
|
174
|
+
return out_html
|