phg-vis 1.3.1__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 +220 -4
- phg/pipe_string_phg.py +254 -128
- {phg_vis-1.3.1.dist-info → phg_vis-1.3.2.dist-info}/METADATA +1 -1
- {phg_vis-1.3.1.dist-info → phg_vis-1.3.2.dist-info}/RECORD +7 -7
- {phg_vis-1.3.1.dist-info → phg_vis-1.3.2.dist-info}/LICENSE +0 -0
- {phg_vis-1.3.1.dist-info → phg_vis-1.3.2.dist-info}/WHEEL +0 -0
- {phg_vis-1.3.1.dist-info → phg_vis-1.3.2.dist-info}/top_level.txt +0 -0
phg/__init__.py
CHANGED
|
@@ -8,9 +8,10 @@ Main Features:
|
|
|
8
8
|
- PHG script visualization via vis.exe
|
|
9
9
|
- Shader-based rendering with GLSL conversion
|
|
10
10
|
- Pipe system visualization with world/local coordinate systems
|
|
11
|
+
- Multiple pipe visualization support
|
|
11
12
|
- Real-time and image rendering capabilities
|
|
12
13
|
|
|
13
|
-
Version:
|
|
14
|
+
Version: 1.3.1
|
|
14
15
|
Author: PanGuoJun
|
|
15
16
|
License: MIT
|
|
16
17
|
"""
|
|
@@ -22,7 +23,8 @@ from .pipe_string_phg import (
|
|
|
22
23
|
world_pipe_to_phg,
|
|
23
24
|
local_pipe_to_phg,
|
|
24
25
|
world_pipestr_vis,
|
|
25
|
-
local_pipestr_vis
|
|
26
|
+
local_pipestr_vis,
|
|
27
|
+
multiple_pipes_vis
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
# Extend ShaderRenderer class to support direct PHG rendering
|
|
@@ -79,6 +81,211 @@ def convert_phg_to_shader(phg_script: str) -> str:
|
|
|
79
81
|
"""
|
|
80
82
|
return phg_to_shader(phg_script)
|
|
81
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
|
|
104
|
+
|
|
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))
|
|
116
|
+
|
|
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'):
|
|
144
|
+
"""
|
|
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)
|
|
288
|
+
|
|
82
289
|
__all__ = [
|
|
83
290
|
# Core visualization functions
|
|
84
291
|
'vis',
|
|
@@ -100,6 +307,13 @@ __all__ = [
|
|
|
100
307
|
'local_pipe_to_phg',
|
|
101
308
|
'world_pipestr_vis',
|
|
102
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',
|
|
103
317
|
]
|
|
104
318
|
|
|
105
319
|
__version__ = "1.3.1"
|
|
@@ -109,5 +323,7 @@ __description__ = "Python Hypergraphics Library"
|
|
|
109
323
|
# Package initialization information
|
|
110
324
|
print(f"PHG {__version__} - {__description__}")
|
|
111
325
|
print("[OK] Visualization module loaded")
|
|
112
|
-
print("[OK] Shader converter loaded")
|
|
113
|
-
print("[OK] Pipe visualization 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
CHANGED
|
@@ -2,59 +2,59 @@
|
|
|
2
2
|
Pipe String to PHG Converter
|
|
3
3
|
============================
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- world_pipe_to_phg:
|
|
10
|
-
- local_pipe_to_phg:
|
|
11
|
-
- world_pipestr_vis:
|
|
12
|
-
- local_pipestr_vis:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- F:
|
|
16
|
-
- B:
|
|
17
|
-
- R:
|
|
18
|
-
- L:
|
|
19
|
-
- U:
|
|
20
|
-
- D:
|
|
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
21
|
"""
|
|
22
22
|
|
|
23
23
|
import phg
|
|
24
24
|
from coordinate_system import vec3, quat, coord3
|
|
25
25
|
|
|
26
|
-
#
|
|
26
|
+
# Default color and pipe radius
|
|
27
27
|
DEFAULT_PIPE_COLOR = (0, 55, 255)
|
|
28
28
|
DEFAULT_PIPE_RADIUS = 0.3
|
|
29
29
|
|
|
30
30
|
def world_pipe_to_phg(world_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
31
31
|
"""
|
|
32
|
-
|
|
32
|
+
Convert world coordinate system pipe string to PHG script
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
world_pipe_str:
|
|
36
|
-
start_c:
|
|
37
|
-
pipe_color:
|
|
38
|
-
pipe_radius:
|
|
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
39
|
|
|
40
|
-
|
|
41
|
-
PHG
|
|
40
|
+
Returns:
|
|
41
|
+
PHG script string
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
#
|
|
44
|
+
# World coordinate direction definitions
|
|
45
45
|
world_directions = {
|
|
46
|
-
'F': vec3(0, 0, 1), #
|
|
47
|
-
'B': vec3(0, 0, -1), #
|
|
48
|
-
'R': vec3(1, 0, 0), #
|
|
49
|
-
'L': vec3(-1, 0, 0), #
|
|
50
|
-
'U': vec3(0, 1, 0), #
|
|
51
|
-
'D': vec3(0, -1, 0) #
|
|
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
52
|
}
|
|
53
53
|
|
|
54
|
-
#
|
|
54
|
+
# Parse color
|
|
55
55
|
r, g, b = pipe_color
|
|
56
56
|
|
|
57
|
-
#
|
|
57
|
+
# Pipe component mapping (all components use fixed length 1.0)
|
|
58
58
|
pipe_components = {
|
|
59
59
|
'F': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:90;z:-0.5;}};z:1.0}}',
|
|
60
60
|
'B': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:-90;z:{-1.0-0.5};}};z:1.0}}',
|
|
@@ -64,78 +64,78 @@ def world_pipe_to_phg(world_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pi
|
|
|
64
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
65
|
}
|
|
66
66
|
|
|
67
|
-
#
|
|
67
|
+
# Initialize current coordinate system (using starting coordinate)
|
|
68
68
|
cur_c = coord3(start_c.o, start_c.Q())
|
|
69
69
|
|
|
70
|
-
#
|
|
70
|
+
# Store all pipe component scripts
|
|
71
71
|
script_parts = []
|
|
72
72
|
|
|
73
|
-
#
|
|
73
|
+
# Iterate through each character in pipe string
|
|
74
74
|
for move_char in world_pipe_str:
|
|
75
75
|
if move_char not in pipe_components:
|
|
76
|
-
print(f"
|
|
76
|
+
print(f"Warning: Unknown pipe character '{move_char}', skipped")
|
|
77
77
|
continue
|
|
78
78
|
|
|
79
|
-
#
|
|
79
|
+
# Get current movement direction in world coordinates
|
|
80
80
|
world_dir = world_directions[move_char]
|
|
81
81
|
|
|
82
|
-
#
|
|
82
|
+
# Transform world direction to current local coordinate system
|
|
83
83
|
local_dir = vec3(
|
|
84
|
-
world_dir.dot(cur_c.ux), #
|
|
85
|
-
world_dir.dot(cur_c.uy), #
|
|
86
|
-
world_dir.dot(cur_c.uz) #
|
|
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
87
|
)
|
|
88
88
|
|
|
89
|
-
#
|
|
89
|
+
# Find component with largest absolute value to determine main movement direction
|
|
90
90
|
abs_components = [abs(local_dir.x), abs(local_dir.y), abs(local_dir.z)]
|
|
91
91
|
max_idx = abs_components.index(max(abs_components))
|
|
92
92
|
|
|
93
|
-
#
|
|
94
|
-
if max_idx == 0: # X
|
|
93
|
+
# Determine local movement direction based on maximum component
|
|
94
|
+
if max_idx == 0: # X-axis
|
|
95
95
|
local_move = 'R' if local_dir.x > 0 else 'L'
|
|
96
|
-
elif max_idx == 1: # Y
|
|
96
|
+
elif max_idx == 1: # Y-axis
|
|
97
97
|
local_move = 'U' if local_dir.y > 0 else 'D'
|
|
98
|
-
else: # Z
|
|
98
|
+
else: # Z-axis
|
|
99
99
|
local_move = 'F' if local_dir.z > 0 else 'B'
|
|
100
100
|
|
|
101
|
-
#
|
|
101
|
+
# Add corresponding pipe component script
|
|
102
102
|
script_parts.append(pipe_components[local_move])
|
|
103
103
|
|
|
104
|
-
#
|
|
104
|
+
# Update current coordinate system (simulate new position and direction after movement)
|
|
105
105
|
if local_move == 'F':
|
|
106
|
-
#
|
|
106
|
+
# Forward: move 1.0 unit along local Z-axis positive direction
|
|
107
107
|
cur_c = cur_c * coord3(vec3(0, 0, 1.0))
|
|
108
108
|
elif local_move == 'B':
|
|
109
|
-
#
|
|
109
|
+
# Backward: move 1.0 unit along local Z-axis negative direction
|
|
110
110
|
cur_c = cur_c * coord3(vec3(0, 0, -1.0))
|
|
111
111
|
elif local_move == 'R':
|
|
112
|
-
#
|
|
112
|
+
# Right turn: rotate -90 degrees around Y-axis, then move 1.0 unit along X-axis
|
|
113
113
|
rotation = quat(-3.1416 / 2, cur_c.uy)
|
|
114
114
|
cur_c = cur_c * rotation
|
|
115
115
|
cur_c = cur_c * coord3(vec3(1.0, 0, 0))
|
|
116
116
|
elif local_move == 'L':
|
|
117
|
-
#
|
|
117
|
+
# Left turn: rotate 90 degrees around Y-axis, then move 1.0 unit along X-axis
|
|
118
118
|
rotation = quat(3.1416 / 2, cur_c.uy)
|
|
119
119
|
cur_c = cur_c * rotation
|
|
120
120
|
cur_c = cur_c * coord3(vec3(-1.0, 0, 0))
|
|
121
121
|
elif local_move == 'U':
|
|
122
|
-
#
|
|
122
|
+
# Up turn: rotate 90 degrees around X-axis, then move 1.0 unit along Y-axis
|
|
123
123
|
rotation = quat(3.1416 / 2, cur_c.ux)
|
|
124
124
|
cur_c = cur_c * rotation
|
|
125
125
|
cur_c = cur_c * coord3(vec3(0, 1.0, 0))
|
|
126
126
|
elif local_move == 'D':
|
|
127
|
-
#
|
|
127
|
+
# Down turn: rotate -90 degrees around X-axis, then move 1.0 unit along Y-axis
|
|
128
128
|
rotation = quat(-3.1416 / 2, cur_c.ux)
|
|
129
129
|
cur_c = cur_c * rotation
|
|
130
130
|
cur_c = cur_c * coord3(vec3(0, -1.0, 0))
|
|
131
131
|
|
|
132
|
-
#
|
|
132
|
+
# Combine all pipe component scripts
|
|
133
133
|
inner_script = ',\n'.join(script_parts)
|
|
134
134
|
|
|
135
|
-
#
|
|
135
|
+
# Get quaternion of starting coordinate system
|
|
136
136
|
q = start_c.Q()
|
|
137
137
|
|
|
138
|
-
#
|
|
138
|
+
# Build complete PHG script
|
|
139
139
|
complete_script = f"""{{
|
|
140
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
141
|
<{inner_script}>}}
|
|
@@ -146,22 +146,22 @@ def world_pipe_to_phg(world_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pi
|
|
|
146
146
|
|
|
147
147
|
def local_pipe_to_phg(local_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
148
148
|
"""
|
|
149
|
-
|
|
149
|
+
Convert local coordinate system pipe string to PHG script
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
local_pipe_str:
|
|
153
|
-
start_c:
|
|
154
|
-
pipe_color:
|
|
155
|
-
pipe_radius:
|
|
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
156
|
|
|
157
|
-
|
|
158
|
-
PHG
|
|
157
|
+
Returns:
|
|
158
|
+
PHG script string
|
|
159
159
|
"""
|
|
160
160
|
|
|
161
|
-
#
|
|
161
|
+
# Parse color
|
|
162
162
|
r, g, b = pipe_color
|
|
163
163
|
|
|
164
|
-
#
|
|
164
|
+
# Pipe component mapping (all components use fixed length 1.0)
|
|
165
165
|
pipe_components = {
|
|
166
166
|
'F': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:90;z:-0.5;}};z:1.0}}',
|
|
167
167
|
'B': f'{{{{rgb:{r},{g},{b};md:cylinder {pipe_radius} 1.0;rx:-90;z:{-1.0-0.5};}};z:1.0}}',
|
|
@@ -171,25 +171,25 @@ def local_pipe_to_phg(local_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pi
|
|
|
171
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
172
|
}
|
|
173
173
|
|
|
174
|
-
#
|
|
174
|
+
# Store all pipe component scripts
|
|
175
175
|
script_parts = []
|
|
176
176
|
|
|
177
|
-
#
|
|
177
|
+
# Iterate through each character in pipe string
|
|
178
178
|
for move_char in local_pipe_str:
|
|
179
179
|
if move_char not in pipe_components:
|
|
180
|
-
print(f"
|
|
180
|
+
print(f"Warning: Unknown pipe character '{move_char}', skipped")
|
|
181
181
|
continue
|
|
182
182
|
|
|
183
|
-
#
|
|
183
|
+
# Directly use local coordinate system movement commands
|
|
184
184
|
script_parts.append(pipe_components[move_char])
|
|
185
185
|
|
|
186
|
-
#
|
|
186
|
+
# Combine all pipe component scripts
|
|
187
187
|
inner_script = ',\n'.join(script_parts)
|
|
188
188
|
|
|
189
|
-
#
|
|
189
|
+
# Get quaternion of starting coordinate system
|
|
190
190
|
q = start_c.Q()
|
|
191
191
|
|
|
192
|
-
#
|
|
192
|
+
# Build complete PHG script
|
|
193
193
|
complete_script = f"""{{
|
|
194
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
195
|
<{inner_script}>}}
|
|
@@ -198,88 +198,214 @@ def local_pipe_to_phg(local_pipe_str, start_c, pipe_color=DEFAULT_PIPE_COLOR, pi
|
|
|
198
198
|
return complete_script
|
|
199
199
|
|
|
200
200
|
|
|
201
|
-
def world_pipestr_vis(
|
|
201
|
+
def world_pipestr_vis(world_pipe_strs, start_c=None, pipe_colors=None, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
202
202
|
"""
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
start_c:
|
|
208
|
-
|
|
209
|
-
pipe_radius:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
PHG
|
|
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
213
|
"""
|
|
214
|
-
#
|
|
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
|
|
215
230
|
if start_c is None:
|
|
216
231
|
start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
217
232
|
|
|
218
|
-
#
|
|
219
|
-
|
|
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)
|
|
220
240
|
|
|
221
|
-
#
|
|
241
|
+
# Combine all pipe scripts
|
|
242
|
+
combined_script = "{\n" + ",\n".join(script_parts) + "\n}"
|
|
243
|
+
|
|
244
|
+
# Call visualization function
|
|
222
245
|
try:
|
|
223
|
-
|
|
224
|
-
|
|
246
|
+
phg.vis(combined_script)
|
|
247
|
+
print(f"Visualizing {len(world_pipe_strs)} world coordinate pipes")
|
|
225
248
|
except ImportError:
|
|
226
|
-
print("
|
|
249
|
+
print("Warning: Cannot import visualization module, returning PHG script")
|
|
227
250
|
|
|
228
|
-
return
|
|
251
|
+
return combined_script
|
|
229
252
|
|
|
230
253
|
|
|
231
|
-
def local_pipestr_vis(
|
|
254
|
+
def local_pipestr_vis(local_pipe_strs, start_c=None, pipe_colors=None, pipe_radius=DEFAULT_PIPE_RADIUS):
|
|
232
255
|
"""
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
start_c:
|
|
238
|
-
|
|
239
|
-
pipe_radius:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
PHG
|
|
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
|
|
243
266
|
"""
|
|
244
|
-
#
|
|
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
|
|
245
283
|
if start_c is None:
|
|
246
284
|
start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
247
285
|
|
|
248
|
-
#
|
|
249
|
-
|
|
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}"
|
|
250
296
|
|
|
251
|
-
#
|
|
297
|
+
# Call visualization function
|
|
252
298
|
try:
|
|
253
|
-
|
|
254
|
-
|
|
299
|
+
phg.vis(combined_script)
|
|
300
|
+
print(f"Visualizing {len(local_pipe_strs)} local coordinate pipes")
|
|
255
301
|
except ImportError:
|
|
256
|
-
print("
|
|
302
|
+
print("Warning: Cannot import visualization module, returning PHG script")
|
|
257
303
|
|
|
258
|
-
return
|
|
304
|
+
return combined_script
|
|
259
305
|
|
|
260
306
|
|
|
261
|
-
|
|
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
|
|
262
353
|
if __name__ == "__main__":
|
|
263
|
-
#
|
|
354
|
+
# Create starting coordinate system (example)
|
|
264
355
|
start_coord = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
|
|
265
356
|
|
|
266
|
-
#
|
|
267
|
-
example_world_pipe = "FFRUD" #
|
|
268
|
-
print("
|
|
357
|
+
# Example 1: Single world coordinate pipe string
|
|
358
|
+
example_world_pipe = "FFRUD" # Forward twice, right, up, down
|
|
359
|
+
print("World Coordinate Pipe Example:")
|
|
269
360
|
phg_script = world_pipe_to_phg(example_world_pipe, start_coord)
|
|
270
|
-
print("
|
|
361
|
+
print("Generated PHG Script:")
|
|
271
362
|
print(phg_script)
|
|
272
363
|
print()
|
|
273
364
|
|
|
274
|
-
#
|
|
275
|
-
example_local_pipe = "FFRUD" #
|
|
276
|
-
print("
|
|
365
|
+
# Example 2: Single local coordinate pipe string
|
|
366
|
+
example_local_pipe = "FFRUD" # Movements in local coordinate system
|
|
367
|
+
print("Local Coordinate Pipe Example:")
|
|
277
368
|
phg_script = local_pipe_to_phg(example_local_pipe, start_coord)
|
|
278
|
-
print("
|
|
369
|
+
print("Generated PHG Script:")
|
|
279
370
|
print(phg_script)
|
|
280
371
|
print()
|
|
281
372
|
|
|
282
|
-
#
|
|
283
|
-
print("
|
|
284
|
-
|
|
285
|
-
#
|
|
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')
|
|
@@ -1,6 +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=
|
|
3
|
+
phg/pipe_string_phg.py,sha256=xoG8AtHRae_sOskSZxTc7lBgwnemv1u8Ko9GvnvHr8Q,16257
|
|
4
4
|
phg/shader_render.py,sha256=_T8IFp1h5Hcj8TMMHwFMbxhGdHLnOqka7pJ4pde7zMA,16780
|
|
5
5
|
phg/visphg.py,sha256=CtALoNJs0eDT8wnXk_76XG4UsOcV6cWucvWqz7AhOSc,1923
|
|
6
6
|
phg/vis/GCU.dll,sha256=k_slWZ5nOzZNi9zCe0_SKc0F7zXoLyRuRDomyirPY4I,2687488
|
|
@@ -15,8 +15,8 @@ phg/vis/vis.exe,sha256=9LGgETiO4lwhz_gJzdUg6gPP9EwGLT5SuLjN3wR2sso,1388032
|
|
|
15
15
|
phg/vis/vis.ini,sha256=IjS0Av2BqresPR2oGCOoq5zliXN2wFRMK3rXcU15vKs,161
|
|
16
16
|
phg/vis/zlib1.dll,sha256=oVw_r326ve3oveVZhlSiF8BloZQ6lfqXJEAhUYfMjOQ,89088
|
|
17
17
|
phg/vis/imgui/main.lua,sha256=AIB5dpGrPHXuRiNW7Bg7eu5Lpi2DDcn6n4JS7OS1Hdk,4742
|
|
18
|
-
phg_vis-1.3.
|
|
19
|
-
phg_vis-1.3.
|
|
20
|
-
phg_vis-1.3.
|
|
21
|
-
phg_vis-1.3.
|
|
22
|
-
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
|