phg-vis 1.3.0__py3-none-any.whl → 1.3.2__py3-none-any.whl
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/__init__.py +285 -38
- phg/pipe_string_phg.py +411 -0
- phg/vis/vis.ini +1 -1
- {phg_vis-1.3.0.dist-info → phg_vis-1.3.2.dist-info}/METADATA +124 -8
- {phg_vis-1.3.0.dist-info → phg_vis-1.3.2.dist-info}/RECORD +8 -7
- {phg_vis-1.3.0.dist-info → phg_vis-1.3.2.dist-info}/LICENSE +0 -0
- {phg_vis-1.3.0.dist-info → phg_vis-1.3.2.dist-info}/WHEEL +0 -0
- {phg_vis-1.3.0.dist-info → phg_vis-1.3.2.dist-info}/top_level.txt +0 -0
phg/__init__.py
CHANGED
|
@@ -1,48 +1,68 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
PHG - Python Hypergraphics Library
|
|
3
|
+
===================================
|
|
4
|
+
|
|
5
|
+
A powerful graphics library for procedural 3D visualization using PHG scripts.
|
|
6
|
+
|
|
7
|
+
Main Features:
|
|
8
|
+
- PHG script visualization via vis.exe
|
|
9
|
+
- Shader-based rendering with GLSL conversion
|
|
10
|
+
- Pipe system visualization with world/local coordinate systems
|
|
11
|
+
- Multiple pipe visualization support
|
|
12
|
+
- Real-time and image rendering capabilities
|
|
13
|
+
|
|
14
|
+
Version: 1.3.1
|
|
15
|
+
Author: PanGuoJun
|
|
16
|
+
License: MIT
|
|
4
17
|
"""
|
|
5
18
|
|
|
6
19
|
from .visphg import vis, image
|
|
7
20
|
from .shader_render import ShaderRenderer, render_shader
|
|
8
21
|
from .phg_to_shader import PHGToShaderConverter, phg_to_shader
|
|
22
|
+
from .pipe_string_phg import (
|
|
23
|
+
world_pipe_to_phg,
|
|
24
|
+
local_pipe_to_phg,
|
|
25
|
+
world_pipestr_vis,
|
|
26
|
+
local_pipestr_vis,
|
|
27
|
+
multiple_pipes_vis
|
|
28
|
+
)
|
|
9
29
|
|
|
10
|
-
#
|
|
30
|
+
# Extend ShaderRenderer class to support direct PHG rendering
|
|
11
31
|
class PHGShaderRenderer(ShaderRenderer):
|
|
12
|
-
"""
|
|
32
|
+
"""Shader renderer that supports direct PHG rendering"""
|
|
13
33
|
|
|
14
34
|
def render_phg(self, phg_script: str, duration=0, interactive=True):
|
|
15
35
|
"""
|
|
16
|
-
|
|
36
|
+
Render PHG script
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
phg_script: PHG
|
|
20
|
-
duration:
|
|
21
|
-
interactive:
|
|
38
|
+
Parameters:
|
|
39
|
+
phg_script: PHG script code
|
|
40
|
+
duration: Render duration
|
|
41
|
+
interactive: Whether to allow interaction
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
success:
|
|
43
|
+
Returns:
|
|
44
|
+
success: Whether rendering was successful
|
|
25
45
|
"""
|
|
26
46
|
converter = PHGToShaderConverter()
|
|
27
47
|
shader_code = converter.generate_shader_code(phg_script)
|
|
28
48
|
|
|
29
49
|
if not shader_code:
|
|
30
|
-
print("
|
|
50
|
+
print("Error: PHG conversion failed")
|
|
31
51
|
return False
|
|
32
52
|
|
|
33
53
|
return self.render_shader(shader_code, duration, interactive)
|
|
34
54
|
|
|
35
|
-
#
|
|
55
|
+
# Convenience functions
|
|
36
56
|
def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Renderer"):
|
|
37
57
|
"""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
phg_script: PHG
|
|
42
|
-
width:
|
|
43
|
-
height:
|
|
44
|
-
duration:
|
|
45
|
-
title:
|
|
58
|
+
Directly render PHG script
|
|
59
|
+
|
|
60
|
+
Parameters:
|
|
61
|
+
phg_script: PHG script code
|
|
62
|
+
width: Window width
|
|
63
|
+
height: Window height
|
|
64
|
+
duration: Render duration
|
|
65
|
+
title: Window title
|
|
46
66
|
"""
|
|
47
67
|
renderer = PHGShaderRenderer(width, height, title)
|
|
48
68
|
success = renderer.render_phg(phg_script, duration)
|
|
@@ -51,32 +71,259 @@ def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Re
|
|
|
51
71
|
|
|
52
72
|
def convert_phg_to_shader(phg_script: str) -> str:
|
|
53
73
|
"""
|
|
54
|
-
|
|
74
|
+
Convert PHG script to GLSL shader code
|
|
75
|
+
|
|
76
|
+
Parameters:
|
|
77
|
+
phg_script: PHG script
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
shader_code: GLSL shader code
|
|
81
|
+
"""
|
|
82
|
+
return phg_to_shader(phg_script)
|
|
83
|
+
|
|
84
|
+
def visualize_pipe_variants(pipe_variants, start_position=None, colors=None, coordinate_system='world'):
|
|
85
|
+
"""
|
|
86
|
+
Visualize multiple pipe variants for comparison
|
|
87
|
+
|
|
88
|
+
Parameters:
|
|
89
|
+
pipe_variants: List of pipe strings or configuration dictionaries
|
|
90
|
+
start_position: Starting coordinate (optional)
|
|
91
|
+
colors: List of colors for each pipe variant
|
|
92
|
+
coordinate_system: 'world' or 'local' coordinate system
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
PHG script string
|
|
96
|
+
"""
|
|
97
|
+
from coordinate_system import vec3, quat, coord3
|
|
98
|
+
|
|
99
|
+
# Handle start position
|
|
100
|
+
if start_position is None:
|
|
101
|
+
start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
102
|
+
else:
|
|
103
|
+
start_c = start_position
|
|
55
104
|
|
|
56
|
-
|
|
57
|
-
|
|
105
|
+
# Handle different input formats
|
|
106
|
+
if isinstance(pipe_variants[0], str):
|
|
107
|
+
# Simple list of pipe strings
|
|
108
|
+
if colors is None:
|
|
109
|
+
# Generate distinct colors for each variant
|
|
110
|
+
import colorsys
|
|
111
|
+
colors = []
|
|
112
|
+
for i in range(len(pipe_variants)):
|
|
113
|
+
hue = i / len(pipe_variants)
|
|
114
|
+
rgb = colorsys.hsv_to_rgb(hue, 0.8, 0.9)
|
|
115
|
+
colors.append(tuple(int(c * 255) for c in rgb))
|
|
58
116
|
|
|
59
|
-
|
|
60
|
-
|
|
117
|
+
if coordinate_system == 'world':
|
|
118
|
+
return world_pipestr_vis(pipe_variants, start_c, colors)
|
|
119
|
+
else:
|
|
120
|
+
return local_pipestr_vis(pipe_variants, start_c, colors)
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
# List of configuration dictionaries
|
|
124
|
+
pipe_configs = []
|
|
125
|
+
for i, variant in enumerate(pipe_variants):
|
|
126
|
+
if isinstance(variant, str):
|
|
127
|
+
config = {
|
|
128
|
+
'pipe_str': variant,
|
|
129
|
+
'start_c': start_c,
|
|
130
|
+
'color': colors[i] if colors else None,
|
|
131
|
+
'radius': 0.3
|
|
132
|
+
}
|
|
133
|
+
else:
|
|
134
|
+
config = variant
|
|
135
|
+
if 'start_c' not in config:
|
|
136
|
+
config['start_c'] = start_c
|
|
137
|
+
|
|
138
|
+
pipe_configs.append(config)
|
|
139
|
+
|
|
140
|
+
return multiple_pipes_vis(pipe_configs, coordinate_system)
|
|
141
|
+
|
|
142
|
+
def create_pipe_comparison_grid(pipe_strings, grid_size=(2, 2), start_position=None,
|
|
143
|
+
base_color=(0, 55, 255), coordinate_system='world'):
|
|
61
144
|
"""
|
|
62
|
-
|
|
145
|
+
Create a grid layout for comparing multiple pipe paths
|
|
146
|
+
|
|
147
|
+
Parameters:
|
|
148
|
+
pipe_strings: List of pipe strings to compare
|
|
149
|
+
grid_size: (rows, cols) for grid layout
|
|
150
|
+
start_position: Base starting position
|
|
151
|
+
base_color: Base color for pipes
|
|
152
|
+
coordinate_system: 'world' or 'local'
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
PHG script string
|
|
156
|
+
"""
|
|
157
|
+
from coordinate_system import vec3, quat, coord3
|
|
158
|
+
|
|
159
|
+
if start_position is None:
|
|
160
|
+
start_position = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
161
|
+
|
|
162
|
+
rows, cols = grid_size
|
|
163
|
+
spacing = 5.0 # Space between pipes in grid
|
|
164
|
+
|
|
165
|
+
pipe_configs = []
|
|
166
|
+
|
|
167
|
+
for i, pipe_str in enumerate(pipe_strings):
|
|
168
|
+
if i >= rows * cols:
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
row = i // cols
|
|
172
|
+
col = i % cols
|
|
173
|
+
|
|
174
|
+
# Calculate position in grid
|
|
175
|
+
x_offset = col * spacing
|
|
176
|
+
z_offset = row * spacing
|
|
177
|
+
|
|
178
|
+
# Create individual start position for this pipe
|
|
179
|
+
individual_start = coord3(
|
|
180
|
+
vec3(
|
|
181
|
+
start_position.o.x + x_offset,
|
|
182
|
+
start_position.o.y,
|
|
183
|
+
start_position.o.z + z_offset
|
|
184
|
+
),
|
|
185
|
+
start_position.Q()
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Generate color variation
|
|
189
|
+
color_variation = (
|
|
190
|
+
min(255, base_color[0] + (i * 30) % 100),
|
|
191
|
+
min(255, base_color[1] + (i * 50) % 100),
|
|
192
|
+
min(255, base_color[2] + (i * 70) % 100)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
pipe_configs.append({
|
|
196
|
+
'pipe_str': pipe_str,
|
|
197
|
+
'start_c': individual_start,
|
|
198
|
+
'color': color_variation,
|
|
199
|
+
'radius': 0.25 + (i * 0.05) # Vary radius slightly
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
return multiple_pipes_vis(pipe_configs, coordinate_system)
|
|
203
|
+
|
|
204
|
+
def generate_pipe_variants_from_rules(base_pipe, num_variants=5, apply_rules=None):
|
|
205
|
+
"""
|
|
206
|
+
Generate pipe variants using transformation rules
|
|
207
|
+
|
|
208
|
+
Parameters:
|
|
209
|
+
base_pipe: Base pipe string
|
|
210
|
+
num_variants: Number of variants to generate
|
|
211
|
+
apply_rules: List of rules to apply ('swap', 'insert', 'cancel')
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
List of pipe variant strings
|
|
215
|
+
"""
|
|
216
|
+
if apply_rules is None:
|
|
217
|
+
apply_rules = ['swap', 'insert', 'cancel']
|
|
218
|
+
|
|
219
|
+
variants = [base_pipe]
|
|
220
|
+
|
|
221
|
+
# Import the pipe transformer if available
|
|
222
|
+
try:
|
|
223
|
+
from .pipe_string_phg import PipeStringTransformer
|
|
224
|
+
transformer = PipeStringTransformer()
|
|
225
|
+
|
|
226
|
+
for _ in range(num_variants - 1):
|
|
227
|
+
current_pipe = base_pipe
|
|
228
|
+
|
|
229
|
+
# Apply random transformations
|
|
230
|
+
import random
|
|
231
|
+
for _ in range(random.randint(1, 3)):
|
|
232
|
+
rule = random.choice(apply_rules)
|
|
233
|
+
|
|
234
|
+
if rule == 'swap' and len(current_pipe) >= 2:
|
|
235
|
+
i, j = random.sample(range(len(current_pipe)), 2)
|
|
236
|
+
current_pipe = transformer.swap_positions(current_pipe, i, j)
|
|
237
|
+
|
|
238
|
+
elif rule == 'insert':
|
|
239
|
+
position = random.randint(0, len(current_pipe))
|
|
240
|
+
direction = random.choice(list(transformer.CANCEL_PAIRS.keys()))
|
|
241
|
+
current_pipe = transformer.insert_cancel_pair(current_pipe, position, direction)
|
|
242
|
+
|
|
243
|
+
elif rule == 'cancel':
|
|
244
|
+
current_pipe = transformer.cancel_adjacent_pairs(current_pipe)
|
|
245
|
+
|
|
246
|
+
# Simplify and add if valid
|
|
247
|
+
simplified = transformer.simplify_path(current_pipe)
|
|
248
|
+
if simplified not in variants:
|
|
249
|
+
variants.append(simplified)
|
|
250
|
+
|
|
251
|
+
except ImportError:
|
|
252
|
+
# Fallback: simple variant generation
|
|
253
|
+
import random
|
|
254
|
+
for i in range(num_variants - 1):
|
|
255
|
+
# Simple character shuffling
|
|
256
|
+
pipe_list = list(base_pipe)
|
|
257
|
+
random.shuffle(pipe_list)
|
|
258
|
+
variant = ''.join(pipe_list)
|
|
259
|
+
if variant not in variants:
|
|
260
|
+
variants.append(variant)
|
|
261
|
+
|
|
262
|
+
return variants[:num_variants]
|
|
263
|
+
|
|
264
|
+
# Enhanced pipe visualization with transformation support
|
|
265
|
+
def visualize_pipe_with_transformations(pipe_string, start_position=None,
|
|
266
|
+
transformations=None, show_variants=3):
|
|
267
|
+
"""
|
|
268
|
+
Visualize a pipe string along with its transformed variants
|
|
269
|
+
|
|
270
|
+
Parameters:
|
|
271
|
+
pipe_string: Base pipe string
|
|
272
|
+
start_position: Starting coordinate
|
|
273
|
+
transformations: List of transformation rules to apply
|
|
274
|
+
show_variants: Number of variants to show
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
PHG script string
|
|
278
|
+
"""
|
|
279
|
+
# Generate variants
|
|
280
|
+
variants = generate_pipe_variants_from_rules(
|
|
281
|
+
pipe_string,
|
|
282
|
+
num_variants=show_variants + 1, # +1 for original
|
|
283
|
+
apply_rules=transformations
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Create comparison visualization
|
|
287
|
+
return visualize_pipe_variants(variants, start_position)
|
|
63
288
|
|
|
64
289
|
__all__ = [
|
|
65
|
-
|
|
66
|
-
'
|
|
67
|
-
'
|
|
290
|
+
# Core visualization functions
|
|
291
|
+
'vis',
|
|
292
|
+
'image',
|
|
293
|
+
|
|
294
|
+
# Shader rendering
|
|
295
|
+
'ShaderRenderer',
|
|
68
296
|
'render_shader',
|
|
69
|
-
'PHGToShaderConverter',
|
|
70
|
-
'PHGShaderRenderer',
|
|
71
297
|
'render_phg',
|
|
298
|
+
'PHGShaderRenderer',
|
|
299
|
+
|
|
300
|
+
# PHG conversion
|
|
301
|
+
'PHGToShaderConverter',
|
|
302
|
+
'phg_to_shader',
|
|
72
303
|
'convert_phg_to_shader',
|
|
73
|
-
|
|
304
|
+
|
|
305
|
+
# Pipe visualization
|
|
306
|
+
'world_pipe_to_phg',
|
|
307
|
+
'local_pipe_to_phg',
|
|
308
|
+
'world_pipestr_vis',
|
|
309
|
+
'local_pipestr_vis',
|
|
310
|
+
'multiple_pipes_vis',
|
|
311
|
+
|
|
312
|
+
# Enhanced pipe visualization
|
|
313
|
+
'visualize_pipe_variants',
|
|
314
|
+
'create_pipe_comparison_grid',
|
|
315
|
+
'generate_pipe_variants_from_rules',
|
|
316
|
+
'visualize_pipe_with_transformations',
|
|
74
317
|
]
|
|
75
318
|
|
|
76
|
-
__version__ = "
|
|
77
|
-
__author__ = "
|
|
78
|
-
__description__ = "Python
|
|
319
|
+
__version__ = "1.3.1"
|
|
320
|
+
__author__ = "PanGuoJun"
|
|
321
|
+
__description__ = "Python Hypergraphics Library"
|
|
79
322
|
|
|
80
|
-
#
|
|
323
|
+
# Package initialization information
|
|
81
324
|
print(f"PHG {__version__} - {__description__}")
|
|
82
|
-
print("
|
|
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")
|
phg/pipe_string_phg.py
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pipe String to PHG Converter
|
|
3
|
+
============================
|
|
4
|
+
|
|
5
|
+
This module provides functionality to convert pipe strings into PHG (Python Graphics) scripts.
|
|
6
|
+
Supports both world coordinate system and local coordinate system pipe descriptions.
|
|
7
|
+
|
|
8
|
+
Main Features:
|
|
9
|
+
- world_pipe_to_phg: World coordinate system pipe conversion
|
|
10
|
+
- local_pipe_to_phg: Local coordinate system pipe conversion
|
|
11
|
+
- world_pipestr_vis: Direct visualization for world coordinate pipes
|
|
12
|
+
- local_pipestr_vis: Direct visualization for local coordinate pipes
|
|
13
|
+
|
|
14
|
+
Pipe String Format:
|
|
15
|
+
- F: Forward
|
|
16
|
+
- B: Backward
|
|
17
|
+
- R: Right
|
|
18
|
+
- L: Left
|
|
19
|
+
- U: Up
|
|
20
|
+
- D: Down
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import phg
|
|
24
|
+
from coordinate_system import vec3, quat, coord3
|
|
25
|
+
|
|
26
|
+
# Default color and pipe radius
|
|
27
|
+
DEFAULT_PIPE_COLOR = (0, 55, 255)
|
|
28
|
+
DEFAULT_PIPE_RADIUS = 0.3
|
|
29
|
+
|
|
30
|
+
def world_pipe_to_phg(world_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
31
|
+
"""
|
|
32
|
+
Convert world coordinate system pipe string to PHG script
|
|
33
|
+
|
|
34
|
+
Parameters:
|
|
35
|
+
world_pipe_str: World coordinate pipe string (e.g., "FFRUD")
|
|
36
|
+
start_c: Starting coordinate system
|
|
37
|
+
pipe_color: Pipe color as (R, G, B) tuple
|
|
38
|
+
pipe_radius: Pipe radius
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
PHG script string
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# World coordinate direction definitions
|
|
45
|
+
world_directions = {
|
|
46
|
+
'F': vec3(0, 0, 1), # Forward (World Z+)
|
|
47
|
+
'B': vec3(0, 0, -1), # Backward (World Z-)
|
|
48
|
+
'R': vec3(1, 0, 0), # Right (World X+)
|
|
49
|
+
'L': vec3(-1, 0, 0), # Left (World X-)
|
|
50
|
+
'U': vec3(0, 1, 0), # Up (World Y+)
|
|
51
|
+
'D': vec3(0, -1, 0) # Down (World Y-)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Parse color
|
|
55
|
+
r, g, b = pipe_color
|
|
56
|
+
|
|
57
|
+
# Pipe component mapping (all components use fixed length 1.0)
|
|
58
|
+
pipe_components = {
|
|
59
|
+
'F': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:90;z:-0.5;}};z:1.0}}',
|
|
60
|
+
'B': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:-90;z:{-1.0-0.5};}};z:1.0}}',
|
|
61
|
+
'R': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}ry:90;x:1.0;z:-1.0}}}},{{x:1.0;ry:-90;}}',
|
|
62
|
+
'L': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}ry:-90;m:x;z:-1.0;x:-1.0}}}},{{x:-1.0;ry:90;}}',
|
|
63
|
+
'U': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}rz:90;y:1.0;z:-1}}}},{{y:1.0;rx:90;}}',
|
|
64
|
+
'D': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}rz:-90;y:-1;z:-1}}}},{{y:-1.0;rx:-90;}}'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Initialize current coordinate system (using starting coordinate)
|
|
68
|
+
cur_c = coord3(start_c.o, start_c.Q())
|
|
69
|
+
|
|
70
|
+
# Store all pipe component scripts
|
|
71
|
+
script_parts = []
|
|
72
|
+
|
|
73
|
+
# Iterate through each character in pipe string
|
|
74
|
+
for move_char in world_pipe_str:
|
|
75
|
+
if move_char not in pipe_components:
|
|
76
|
+
print(f"Warning: Unknown pipe character '{move_char}', skipped")
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
# Get current movement direction in world coordinates
|
|
80
|
+
world_dir = world_directions[move_char]
|
|
81
|
+
|
|
82
|
+
# Transform world direction to current local coordinate system
|
|
83
|
+
local_dir = vec3(
|
|
84
|
+
world_dir.dot(cur_c.ux), # Component in local X-axis
|
|
85
|
+
world_dir.dot(cur_c.uy), # Component in local Y-axis
|
|
86
|
+
world_dir.dot(cur_c.uz) # Component in local Z-axis
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Find component with largest absolute value to determine main movement direction
|
|
90
|
+
abs_components = [abs(local_dir.x), abs(local_dir.y), abs(local_dir.z)]
|
|
91
|
+
max_idx = abs_components.index(max(abs_components))
|
|
92
|
+
|
|
93
|
+
# Determine local movement direction based on maximum component
|
|
94
|
+
if max_idx == 0: # X-axis
|
|
95
|
+
local_move = 'R' if local_dir.x > 0 else 'L'
|
|
96
|
+
elif max_idx == 1: # Y-axis
|
|
97
|
+
local_move = 'U' if local_dir.y > 0 else 'D'
|
|
98
|
+
else: # Z-axis
|
|
99
|
+
local_move = 'F' if local_dir.z > 0 else 'B'
|
|
100
|
+
|
|
101
|
+
# Add corresponding pipe component script
|
|
102
|
+
script_parts.append(pipe_components[local_move])
|
|
103
|
+
|
|
104
|
+
# Update current coordinate system (simulate new position and direction after movement)
|
|
105
|
+
if local_move == 'F':
|
|
106
|
+
# Forward: move 1.0 unit along local Z-axis positive direction
|
|
107
|
+
cur_c = cur_c * coord3(vec3(0, 0, 1.0))
|
|
108
|
+
elif local_move == 'B':
|
|
109
|
+
# Backward: move 1.0 unit along local Z-axis negative direction
|
|
110
|
+
cur_c = cur_c * coord3(vec3(0, 0, -1.0))
|
|
111
|
+
elif local_move == 'R':
|
|
112
|
+
# Right turn: rotate -90 degrees around Y-axis, then move 1.0 unit along X-axis
|
|
113
|
+
rotation = quat(-3.1416 / 2, cur_c.uy)
|
|
114
|
+
cur_c = cur_c * rotation
|
|
115
|
+
cur_c = cur_c * coord3(vec3(1.0, 0, 0))
|
|
116
|
+
elif local_move == 'L':
|
|
117
|
+
# Left turn: rotate 90 degrees around Y-axis, then move 1.0 unit along X-axis
|
|
118
|
+
rotation = quat(3.1416 / 2, cur_c.uy)
|
|
119
|
+
cur_c = cur_c * rotation
|
|
120
|
+
cur_c = cur_c * coord3(vec3(-1.0, 0, 0))
|
|
121
|
+
elif local_move == 'U':
|
|
122
|
+
# Up turn: rotate 90 degrees around X-axis, then move 1.0 unit along Y-axis
|
|
123
|
+
rotation = quat(3.1416 / 2, cur_c.ux)
|
|
124
|
+
cur_c = cur_c * rotation
|
|
125
|
+
cur_c = cur_c * coord3(vec3(0, 1.0, 0))
|
|
126
|
+
elif local_move == 'D':
|
|
127
|
+
# Down turn: rotate -90 degrees around X-axis, then move 1.0 unit along Y-axis
|
|
128
|
+
rotation = quat(-3.1416 / 2, cur_c.ux)
|
|
129
|
+
cur_c = cur_c * rotation
|
|
130
|
+
cur_c = cur_c * coord3(vec3(0, -1.0, 0))
|
|
131
|
+
|
|
132
|
+
# Combine all pipe component scripts
|
|
133
|
+
inner_script = ',\n'.join(script_parts)
|
|
134
|
+
|
|
135
|
+
# Get quaternion of starting coordinate system
|
|
136
|
+
q = start_c.Q()
|
|
137
|
+
|
|
138
|
+
# Build complete PHG script
|
|
139
|
+
complete_script = f"""{{
|
|
140
|
+
{{xyz:{start_c.o.x},{start_c.o.y},{start_c.o.z};q:{q.w},{q.x},{q.y},{q.z};s:0.5;
|
|
141
|
+
<{inner_script}>}}
|
|
142
|
+
}}"""
|
|
143
|
+
|
|
144
|
+
return complete_script
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def local_pipe_to_phg(local_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
148
|
+
"""
|
|
149
|
+
Convert local coordinate system pipe string to PHG script
|
|
150
|
+
|
|
151
|
+
Parameters:
|
|
152
|
+
local_pipe_str: Local coordinate pipe string (e.g., "FFRUD")
|
|
153
|
+
start_c: Starting coordinate system
|
|
154
|
+
pipe_color: Pipe color as (R, G, B) tuple
|
|
155
|
+
pipe_radius: Pipe radius
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
PHG script string
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
# Parse color
|
|
162
|
+
r, g, b = pipe_color
|
|
163
|
+
|
|
164
|
+
# Pipe component mapping (all components use fixed length 1.0)
|
|
165
|
+
pipe_components = {
|
|
166
|
+
'F': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:90;z:-0.5;}};z:1.0}}',
|
|
167
|
+
'B': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:-90;z:{-1.0-0.5};}};z:1.0}}',
|
|
168
|
+
'R': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}ry:90;x:1.0;z:-1.0}}}},{{x:1.0;ry:-90;}}',
|
|
169
|
+
'L': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}ry:-90;m:x;z:-1.0;x:-1.0}}}},{{x:-1.0;ry:90;}}',
|
|
170
|
+
'U': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}rz:90;y:1.0;z:-1}}}},{{y:1.0;rx:90;}}',
|
|
171
|
+
'D': f'{{{{{{rgb:{r},{g},{b};md:elbow 90 0.5 {pipe_radius};x:0.5;z:0.5;}}rz:-90;y:-1;z:-1}}}},{{y:-1.0;rx:-90;}}'
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# Store all pipe component scripts
|
|
175
|
+
script_parts = []
|
|
176
|
+
|
|
177
|
+
# Iterate through each character in pipe string
|
|
178
|
+
for move_char in local_pipe_str:
|
|
179
|
+
if move_char not in pipe_components:
|
|
180
|
+
print(f"Warning: Unknown pipe character '{move_char}', skipped")
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
# Directly use local coordinate system movement commands
|
|
184
|
+
script_parts.append(pipe_components[move_char])
|
|
185
|
+
|
|
186
|
+
# Combine all pipe component scripts
|
|
187
|
+
inner_script = ',\n'.join(script_parts)
|
|
188
|
+
|
|
189
|
+
# Get quaternion of starting coordinate system
|
|
190
|
+
q = start_c.Q()
|
|
191
|
+
|
|
192
|
+
# Build complete PHG script
|
|
193
|
+
complete_script = f"""{{
|
|
194
|
+
{{xyz:{start_c.o.x},{start_c.o.y},{start_c.o.z};q:{q.w},{q.x},{q.y},{q.z};s:0.5;
|
|
195
|
+
<{inner_script}>}}
|
|
196
|
+
}}"""
|
|
197
|
+
|
|
198
|
+
return complete_script
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def world_pipestr_vis(world_pipe_strs, start_c=None, pipe_colors=None, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
202
|
+
"""
|
|
203
|
+
Direct visualization for world coordinate pipe strings with support for multiple pipes
|
|
204
|
+
|
|
205
|
+
Parameters:
|
|
206
|
+
world_pipe_strs: World coordinate pipe string or list of strings (e.g., "FFRUD" or ["FFR", "LLU"])
|
|
207
|
+
start_c: Starting coordinate system, defaults to origin
|
|
208
|
+
pipe_colors: Single color or list of colors as (R, G, B) tuples
|
|
209
|
+
pipe_radius: Pipe radius
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
PHG script string
|
|
213
|
+
"""
|
|
214
|
+
# Handle single string input
|
|
215
|
+
if isinstance(world_pipe_strs, str):
|
|
216
|
+
world_pipe_strs = [world_pipe_strs]
|
|
217
|
+
|
|
218
|
+
# Handle single color input
|
|
219
|
+
if pipe_colors is None:
|
|
220
|
+
pipe_colors = [DEFAULT_PIPE_COLOR] * len(world_pipe_strs)
|
|
221
|
+
elif isinstance(pipe_colors, tuple):
|
|
222
|
+
pipe_colors = [pipe_colors] * len(world_pipe_strs)
|
|
223
|
+
|
|
224
|
+
# Ensure colors list matches pipes list length
|
|
225
|
+
if len(pipe_colors) != len(world_pipe_strs):
|
|
226
|
+
pipe_colors = [DEFAULT_PIPE_COLOR] * len(world_pipe_strs)
|
|
227
|
+
print("Warning: Colors list length doesn't match pipes list, using default colors")
|
|
228
|
+
|
|
229
|
+
# Use default origin if no starting coordinate provided
|
|
230
|
+
if start_c is None:
|
|
231
|
+
start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
232
|
+
|
|
233
|
+
# Generate PHG scripts for all pipes
|
|
234
|
+
script_parts = []
|
|
235
|
+
for i, (pipe_str, color) in enumerate(zip(world_pipe_strs, pipe_colors)):
|
|
236
|
+
phg_script = world_pipe_to_phg(pipe_str, start_c, color, pipe_radius)
|
|
237
|
+
# Extract inner content between outer braces
|
|
238
|
+
inner_content = phg_script.strip()[1:-1].strip()
|
|
239
|
+
script_parts.append(inner_content)
|
|
240
|
+
|
|
241
|
+
# Combine all pipe scripts
|
|
242
|
+
combined_script = "{\n" + ",\n".join(script_parts) + "\n}"
|
|
243
|
+
|
|
244
|
+
# Call visualization function
|
|
245
|
+
try:
|
|
246
|
+
phg.vis(combined_script)
|
|
247
|
+
print(f"Visualizing {len(world_pipe_strs)} world coordinate pipes")
|
|
248
|
+
except ImportError:
|
|
249
|
+
print("Warning: Cannot import visualization module, returning PHG script")
|
|
250
|
+
|
|
251
|
+
return combined_script
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def local_pipestr_vis(local_pipe_strs, start_c=None, pipe_colors=None, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
255
|
+
"""
|
|
256
|
+
Direct visualization for local coordinate pipe strings with support for multiple pipes
|
|
257
|
+
|
|
258
|
+
Parameters:
|
|
259
|
+
local_pipe_strs: Local coordinate pipe string or list of strings (e.g., "FFRUD" or ["FFR", "LLU"])
|
|
260
|
+
start_c: Starting coordinate system, defaults to origin
|
|
261
|
+
pipe_colors: Single color or list of colors as (R, G, B) tuples
|
|
262
|
+
pipe_radius: Pipe radius
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
PHG script string
|
|
266
|
+
"""
|
|
267
|
+
# Handle single string input
|
|
268
|
+
if isinstance(local_pipe_strs, str):
|
|
269
|
+
local_pipe_strs = [local_pipe_strs]
|
|
270
|
+
|
|
271
|
+
# Handle single color input
|
|
272
|
+
if pipe_colors is None:
|
|
273
|
+
pipe_colors = [DEFAULT_PIPE_COLOR] * len(local_pipe_strs)
|
|
274
|
+
elif isinstance(pipe_colors, tuple):
|
|
275
|
+
pipe_colors = [pipe_colors] * len(local_pipe_strs)
|
|
276
|
+
|
|
277
|
+
# Ensure colors list matches pipes list length
|
|
278
|
+
if len(pipe_colors) != len(local_pipe_strs):
|
|
279
|
+
pipe_colors = [DEFAULT_PIPE_COLOR] * len(local_pipe_strs)
|
|
280
|
+
print("Warning: Colors list length doesn't match pipes list, using default colors")
|
|
281
|
+
|
|
282
|
+
# Use default origin if no starting coordinate provided
|
|
283
|
+
if start_c is None:
|
|
284
|
+
start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
285
|
+
|
|
286
|
+
# Generate PHG scripts for all pipes
|
|
287
|
+
script_parts = []
|
|
288
|
+
for i, (pipe_str, color) in enumerate(zip(local_pipe_strs, pipe_colors)):
|
|
289
|
+
phg_script = local_pipe_to_phg(pipe_str, start_c, color, pipe_radius)
|
|
290
|
+
# Extract inner content between outer braces
|
|
291
|
+
inner_content = phg_script.strip()[1:-1].strip()
|
|
292
|
+
script_parts.append(inner_content)
|
|
293
|
+
|
|
294
|
+
# Combine all pipe scripts
|
|
295
|
+
combined_script = "{\n" + ",\n".join(script_parts) + "\n}"
|
|
296
|
+
|
|
297
|
+
# Call visualization function
|
|
298
|
+
try:
|
|
299
|
+
phg.vis(combined_script)
|
|
300
|
+
print(f"Visualizing {len(local_pipe_strs)} local coordinate pipes")
|
|
301
|
+
except ImportError:
|
|
302
|
+
print("Warning: Cannot import visualization module, returning PHG script")
|
|
303
|
+
|
|
304
|
+
return combined_script
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def multiple_pipes_vis(pipe_configs, coordinate_system='world'):
|
|
308
|
+
"""
|
|
309
|
+
Advanced visualization for multiple pipes with individual configurations
|
|
310
|
+
|
|
311
|
+
Parameters:
|
|
312
|
+
pipe_configs: List of pipe configuration dictionaries with keys:
|
|
313
|
+
- 'pipe_str': Pipe string (required)
|
|
314
|
+
- 'start_c': Starting coordinate (optional, defaults to origin)
|
|
315
|
+
- 'color': Pipe color (optional, defaults to DEFAULT_PIPE_COLOR)
|
|
316
|
+
- 'radius': Pipe radius (optional, defaults to DEFAULT_PIPE_RADIUS)
|
|
317
|
+
coordinate_system: 'world' or 'local' coordinate system
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
PHG script string
|
|
321
|
+
"""
|
|
322
|
+
script_parts = []
|
|
323
|
+
|
|
324
|
+
for i, config in enumerate(pipe_configs):
|
|
325
|
+
pipe_str = config.get('pipe_str')
|
|
326
|
+
start_c = config.get('start_c', coord3(vec3(0, 0, 0), quat(1, 0, 0, 0)))
|
|
327
|
+
color = config.get('color', DEFAULT_PIPE_COLOR)
|
|
328
|
+
radius = config.get('radius', DEFAULT_PIPE_RADIUS)
|
|
329
|
+
|
|
330
|
+
if coordinate_system.lower() == 'world':
|
|
331
|
+
phg_script = world_pipe_to_phg(pipe_str, start_c, color, radius)
|
|
332
|
+
else:
|
|
333
|
+
phg_script = local_pipe_to_phg(pipe_str, start_c, color, radius)
|
|
334
|
+
|
|
335
|
+
# Extract inner content
|
|
336
|
+
inner_content = phg_script.strip()[1:-1].strip()
|
|
337
|
+
script_parts.append(inner_content)
|
|
338
|
+
|
|
339
|
+
# Combine all pipe scripts
|
|
340
|
+
combined_script = "{\n" + ",\n".join(script_parts) + "\n}"
|
|
341
|
+
|
|
342
|
+
# Call visualization
|
|
343
|
+
try:
|
|
344
|
+
phg.vis(combined_script)
|
|
345
|
+
print(f"Visualizing {len(pipe_configs)} pipes in {coordinate_system} coordinate system")
|
|
346
|
+
except ImportError:
|
|
347
|
+
print("Warning: Cannot import visualization module, returning PHG script")
|
|
348
|
+
|
|
349
|
+
return combined_script
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
# Usage Examples
|
|
353
|
+
if __name__ == "__main__":
|
|
354
|
+
# Create starting coordinate system (example)
|
|
355
|
+
start_coord = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
356
|
+
|
|
357
|
+
# Example 1: Single world coordinate pipe string
|
|
358
|
+
example_world_pipe = "FFRUD" # Forward twice, right, up, down
|
|
359
|
+
print("World Coordinate Pipe Example:")
|
|
360
|
+
phg_script = world_pipe_to_phg(example_world_pipe, start_coord)
|
|
361
|
+
print("Generated PHG Script:")
|
|
362
|
+
print(phg_script)
|
|
363
|
+
print()
|
|
364
|
+
|
|
365
|
+
# Example 2: Single local coordinate pipe string
|
|
366
|
+
example_local_pipe = "FFRUD" # Movements in local coordinate system
|
|
367
|
+
print("Local Coordinate Pipe Example:")
|
|
368
|
+
phg_script = local_pipe_to_phg(example_local_pipe, start_coord)
|
|
369
|
+
print("Generated PHG Script:")
|
|
370
|
+
print(phg_script)
|
|
371
|
+
print()
|
|
372
|
+
|
|
373
|
+
# Example 3: Multiple pipes visualization
|
|
374
|
+
print("Multiple Pipes Visualization Example:")
|
|
375
|
+
|
|
376
|
+
# Multiple world coordinate pipes with different colors
|
|
377
|
+
world_pipes = ["FFR", "LLU", "RRD"]
|
|
378
|
+
world_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
|
|
379
|
+
world_pipestr_vis(world_pipes, start_coord, world_colors)
|
|
380
|
+
print()
|
|
381
|
+
|
|
382
|
+
# Multiple local coordinate pipes
|
|
383
|
+
local_pipes = ["FFR", "BBL", "UUD"]
|
|
384
|
+
local_colors = [(255, 255, 0), (255, 0, 255), (0, 255, 255)] # Yellow, Magenta, Cyan
|
|
385
|
+
local_pipestr_vis(local_pipes, start_coord, local_colors)
|
|
386
|
+
print()
|
|
387
|
+
|
|
388
|
+
# Example 4: Advanced multiple pipes configuration
|
|
389
|
+
print("Advanced Multiple Pipes Configuration:")
|
|
390
|
+
pipe_configs = [
|
|
391
|
+
{
|
|
392
|
+
'pipe_str': 'FFR',
|
|
393
|
+
'start_c': coord3(vec3(0, 0, 0), quat(1, 0, 0, 0)),
|
|
394
|
+
'color': (255, 100, 100),
|
|
395
|
+
'radius': 0.4
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
'pipe_str': 'LLU',
|
|
399
|
+
'start_c': coord3(vec3(5, 0, 0), quat(1, 0, 0, 0)),
|
|
400
|
+
'color': (100, 255, 100),
|
|
401
|
+
'radius': 0.3
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
'pipe_str': 'RRD',
|
|
405
|
+
'start_c': coord3(vec3(0, 5, 0), quat(1, 0, 0, 0)),
|
|
406
|
+
'color': (100, 100, 255),
|
|
407
|
+
'radius': 0.2
|
|
408
|
+
}
|
|
409
|
+
]
|
|
410
|
+
|
|
411
|
+
multiple_pipes_vis(pipe_configs, 'world')
|
phg/vis/vis.ini
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: phg_vis
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
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
|
|
@@ -13,20 +13,21 @@ Requires-Python: >=3.8
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
|
|
16
|
-
# PHG -
|
|
16
|
+
# PHG - Python Hypergraphics Library
|
|
17
17
|
|
|
18
|
-
PHG (
|
|
18
|
+
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.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
## 🌟 Features
|
|
23
23
|
|
|
24
|
-
- **Minimalist Syntax** - Declarative node tree description
|
|
24
|
+
- **Minimalist Syntax** - Declarative node tree description for 3D scenes
|
|
25
25
|
- **Hierarchical Modeling** - Support for nested nodes and transform inheritance
|
|
26
26
|
- **Parametric Design** - Flexible property system and function definitions
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
27
|
+
- **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
|
+
- **Python Integration** - Comprehensive Python API for all features
|
|
30
31
|
|
|
31
32
|
---
|
|
32
33
|
|
|
@@ -402,6 +403,122 @@ for size in [5, 10, 15, 20]:
|
|
|
402
403
|
|
|
403
404
|
---
|
|
404
405
|
|
|
406
|
+
## 🔧 Pipe Visualization System
|
|
407
|
+
|
|
408
|
+
PHG includes a specialized pipe visualization system for creating 3D pipe structures from simple string commands.
|
|
409
|
+
|
|
410
|
+
### Pipe String Commands
|
|
411
|
+
|
|
412
|
+
- **F** - Forward (move forward in current direction)
|
|
413
|
+
- **B** - Back (move backward in current direction)
|
|
414
|
+
- **R** - Right (turn right and move)
|
|
415
|
+
- **L** - Left (turn left and move)
|
|
416
|
+
- **U** - Up (turn up and move)
|
|
417
|
+
- **D** - Down (turn down and move)
|
|
418
|
+
|
|
419
|
+
### World Coordinate System
|
|
420
|
+
|
|
421
|
+
World coordinate pipes use absolute directions regardless of current orientation:
|
|
422
|
+
|
|
423
|
+
```python
|
|
424
|
+
import phg
|
|
425
|
+
from coordinate_system import vec3, quat, coord3
|
|
426
|
+
|
|
427
|
+
# Create a pipe in world coordinates
|
|
428
|
+
# F moves along world Z+, R moves along world X+, etc.
|
|
429
|
+
start_pos = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
430
|
+
phg_script = phg.world_pipestr_vis("FFRRUD", start_pos)
|
|
431
|
+
|
|
432
|
+
# Custom pipe appearance
|
|
433
|
+
phg.world_pipestr_vis(
|
|
434
|
+
"FFLLUU",
|
|
435
|
+
start_pos,
|
|
436
|
+
pipe_color=(255, 100, 50), # Orange pipe
|
|
437
|
+
pipe_radius=0.5 # Thicker pipe
|
|
438
|
+
)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Local Coordinate System
|
|
442
|
+
|
|
443
|
+
Local coordinate pipes use directions relative to current orientation:
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
import phg
|
|
447
|
+
from coordinate_system import vec3, quat, coord3
|
|
448
|
+
|
|
449
|
+
# Create a pipe in local coordinates
|
|
450
|
+
# F moves forward relative to current orientation
|
|
451
|
+
start_pos = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
452
|
+
phg_script = phg.local_pipestr_vis("FFRRUD", start_pos)
|
|
453
|
+
|
|
454
|
+
# The same string produces different results in local vs world coordinates
|
|
455
|
+
phg.local_pipestr_vis(
|
|
456
|
+
"FFRRFF", # Forward, Forward, Right turn, Right turn, Forward, Forward
|
|
457
|
+
start_pos,
|
|
458
|
+
pipe_color=(0, 255, 100) # Green pipe
|
|
459
|
+
)
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Direct PHG Script Generation
|
|
463
|
+
|
|
464
|
+
For advanced use cases, you can generate PHG scripts without immediate visualization:
|
|
465
|
+
|
|
466
|
+
```python
|
|
467
|
+
import phg
|
|
468
|
+
from coordinate_system import vec3, quat, coord3
|
|
469
|
+
|
|
470
|
+
start = coord3(vec3(5, 0, 0), quat(1, 0, 0, 0))
|
|
471
|
+
|
|
472
|
+
# Generate PHG script for world coordinates
|
|
473
|
+
world_phg = phg.world_pipe_to_phg("FFRUD", start)
|
|
474
|
+
|
|
475
|
+
# Generate PHG script for local coordinates
|
|
476
|
+
local_phg = phg.local_pipe_to_phg("FFRUD", start)
|
|
477
|
+
|
|
478
|
+
# Visualize later
|
|
479
|
+
phg.vis(world_phg)
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Example: Complex Pipe System
|
|
483
|
+
|
|
484
|
+
```python
|
|
485
|
+
import phg
|
|
486
|
+
from coordinate_system import vec3, quat, coord3
|
|
487
|
+
|
|
488
|
+
# Create a complex pipe network
|
|
489
|
+
def create_pipe_network():
|
|
490
|
+
# Main pipeline
|
|
491
|
+
main_pipe = phg.world_pipestr_vis(
|
|
492
|
+
"FFFFRRFFRRUUFFLLFF",
|
|
493
|
+
coord3(vec3(0, 0, 0), quat(1, 0, 0, 0)),
|
|
494
|
+
pipe_color=(100, 100, 255),
|
|
495
|
+
pipe_radius=0.5
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
# Branch 1
|
|
499
|
+
branch1 = phg.world_pipestr_vis(
|
|
500
|
+
"RRUUFFFF",
|
|
501
|
+
coord3(vec3(4, 0, 0), quat(1, 0, 0, 0)),
|
|
502
|
+
pipe_color=(255, 100, 100),
|
|
503
|
+
pipe_radius=0.3
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
# Branch 2
|
|
507
|
+
branch2 = phg.local_pipestr_vis(
|
|
508
|
+
"FFLLDDFF",
|
|
509
|
+
coord3(vec3(8, 2, 2), quat(1, 0, 0, 0)),
|
|
510
|
+
pipe_color=(100, 255, 100),
|
|
511
|
+
pipe_radius=0.3
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
return main_pipe, branch1, branch2
|
|
515
|
+
|
|
516
|
+
# Create and visualize the network
|
|
517
|
+
pipes = create_pipe_network()
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
405
522
|
## 💡 Complete Examples
|
|
406
523
|
|
|
407
524
|
### Example 1: Simple Geometry
|
|
@@ -581,7 +698,6 @@ Recommended maximum resolution is **4096 x 4096**. Excessively large resolutions
|
|
|
581
698
|
## 🔗 Links
|
|
582
699
|
|
|
583
700
|
- [PyPI Package](https://pypi.org/project/phg/)
|
|
584
|
-
- [Official Documentation](https://your.documentation.link)
|
|
585
701
|
- [Mathematical Foundation](https://github.com/panguojun/Coordinate-System)
|
|
586
702
|
|
|
587
703
|
---
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
phg/__init__.py,sha256=
|
|
1
|
+
phg/__init__.py,sha256=kH5hF-vqbLqzBE_xkOYabiYFtdb4CXtlwl67uPbDHpo,10767
|
|
2
2
|
phg/phg_to_shader.py,sha256=rb_LnGE1Py08oz72ES5CnjyCDbjVWDU3If0cYZq4SUU,15172
|
|
3
|
+
phg/pipe_string_phg.py,sha256=xoG8AtHRae_sOskSZxTc7lBgwnemv1u8Ko9GvnvHr8Q,16257
|
|
3
4
|
phg/shader_render.py,sha256=_T8IFp1h5Hcj8TMMHwFMbxhGdHLnOqka7pJ4pde7zMA,16780
|
|
4
5
|
phg/visphg.py,sha256=CtALoNJs0eDT8wnXk_76XG4UsOcV6cWucvWqz7AhOSc,1923
|
|
5
6
|
phg/vis/GCU.dll,sha256=k_slWZ5nOzZNi9zCe0_SKc0F7zXoLyRuRDomyirPY4I,2687488
|
|
@@ -11,11 +12,11 @@ phg/vis/pycoder.exe,sha256=joyuVRBleLmOsxQjaq1iauHxC0BbQGKf8Mnwmx4xrVA,61440
|
|
|
11
12
|
phg/vis/script.phg,sha256=HfEBk9omTAfm-KywupQwAwqgHqsr5hCS0f7gfBH1mYY,123
|
|
12
13
|
phg/vis/sqlite3.dll,sha256=pTf_jpQLK7vaDLipxp4qhPB_MkByPgC-RKXTmmKiy_w,1066496
|
|
13
14
|
phg/vis/vis.exe,sha256=9LGgETiO4lwhz_gJzdUg6gPP9EwGLT5SuLjN3wR2sso,1388032
|
|
14
|
-
phg/vis/vis.ini,sha256=
|
|
15
|
+
phg/vis/vis.ini,sha256=IjS0Av2BqresPR2oGCOoq5zliXN2wFRMK3rXcU15vKs,161
|
|
15
16
|
phg/vis/zlib1.dll,sha256=oVw_r326ve3oveVZhlSiF8BloZQ6lfqXJEAhUYfMjOQ,89088
|
|
16
17
|
phg/vis/imgui/main.lua,sha256=AIB5dpGrPHXuRiNW7Bg7eu5Lpi2DDcn6n4JS7OS1Hdk,4742
|
|
17
|
-
phg_vis-1.3.
|
|
18
|
-
phg_vis-1.3.
|
|
19
|
-
phg_vis-1.3.
|
|
20
|
-
phg_vis-1.3.
|
|
21
|
-
phg_vis-1.3.
|
|
18
|
+
phg_vis-1.3.2.dist-info/LICENSE,sha256=tDnRkJxBYPzWdfh2gArRqrUPJxQZRZHJVs68qqBHIq4,1083
|
|
19
|
+
phg_vis-1.3.2.dist-info/METADATA,sha256=gMSdSe_22WeBMCBSxhLdpIYV4EbiP7NhJPVf_FnKQKU,17945
|
|
20
|
+
phg_vis-1.3.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
21
|
+
phg_vis-1.3.2.dist-info/top_level.txt,sha256=5GGhpTP8yi-zTXwW2HrI-zcxKxIM_nHXhL7r0iIDE_k,4
|
|
22
|
+
phg_vis-1.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|