phg-vis 1.3.1__tar.gz → 1.3.2__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.
Files changed (28) hide show
  1. {phg_vis-1.3.1/phg_vis.egg-info → phg_vis-1.3.2}/PKG-INFO +1 -1
  2. phg_vis-1.3.2/phg/__init__.py +329 -0
  3. phg_vis-1.3.2/phg/pipe_string_phg.py +411 -0
  4. {phg_vis-1.3.1 → phg_vis-1.3.2/phg_vis.egg-info}/PKG-INFO +1 -1
  5. {phg_vis-1.3.1 → phg_vis-1.3.2}/setup.py +1 -1
  6. phg_vis-1.3.1/phg/__init__.py +0 -113
  7. phg_vis-1.3.1/phg/pipe_string_phg.py +0 -285
  8. {phg_vis-1.3.1 → phg_vis-1.3.2}/LICENSE +0 -0
  9. {phg_vis-1.3.1 → phg_vis-1.3.2}/MANIFEST.in +0 -0
  10. {phg_vis-1.3.1 → phg_vis-1.3.2}/README.md +0 -0
  11. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/phg_to_shader.py +0 -0
  12. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/shader_render.py +0 -0
  13. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/GCU.dll +0 -0
  14. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/dragpad.exe +0 -0
  15. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/dragpad_config.ini +0 -0
  16. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/freeglut.dll +0 -0
  17. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/imgui/main.lua +0 -0
  18. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/lua.dll +0 -0
  19. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/script.phg +0 -0
  20. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/sqlite3.dll +0 -0
  21. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/vis.exe +0 -0
  22. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/vis.ini +0 -0
  23. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/vis/zlib1.dll +0 -0
  24. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg/visphg.py +0 -0
  25. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg_vis.egg-info/SOURCES.txt +0 -0
  26. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg_vis.egg-info/dependency_links.txt +0 -0
  27. {phg_vis-1.3.1 → phg_vis-1.3.2}/phg_vis.egg-info/top_level.txt +0 -0
  28. {phg_vis-1.3.1 → phg_vis-1.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: phg_vis
3
- Version: 1.3.1
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
@@ -0,0 +1,329 @@
1
+ """
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
17
+ """
18
+
19
+ from .visphg import vis, image
20
+ from .shader_render import ShaderRenderer, render_shader
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
+ )
29
+
30
+ # Extend ShaderRenderer class to support direct PHG rendering
31
+ class PHGShaderRenderer(ShaderRenderer):
32
+ """Shader renderer that supports direct PHG rendering"""
33
+
34
+ def render_phg(self, phg_script: str, duration=0, interactive=True):
35
+ """
36
+ Render PHG script
37
+
38
+ Parameters:
39
+ phg_script: PHG script code
40
+ duration: Render duration
41
+ interactive: Whether to allow interaction
42
+
43
+ Returns:
44
+ success: Whether rendering was successful
45
+ """
46
+ converter = PHGToShaderConverter()
47
+ shader_code = converter.generate_shader_code(phg_script)
48
+
49
+ if not shader_code:
50
+ print("Error: PHG conversion failed")
51
+ return False
52
+
53
+ return self.render_shader(shader_code, duration, interactive)
54
+
55
+ # Convenience functions
56
+ def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Renderer"):
57
+ """
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
66
+ """
67
+ renderer = PHGShaderRenderer(width, height, title)
68
+ success = renderer.render_phg(phg_script, duration)
69
+ renderer.close()
70
+ return success
71
+
72
+ def convert_phg_to_shader(phg_script: str) -> str:
73
+ """
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
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
+
289
+ __all__ = [
290
+ # Core visualization functions
291
+ 'vis',
292
+ 'image',
293
+
294
+ # Shader rendering
295
+ 'ShaderRenderer',
296
+ 'render_shader',
297
+ 'render_phg',
298
+ 'PHGShaderRenderer',
299
+
300
+ # PHG conversion
301
+ 'PHGToShaderConverter',
302
+ 'phg_to_shader',
303
+ 'convert_phg_to_shader',
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',
317
+ ]
318
+
319
+ __version__ = "1.3.1"
320
+ __author__ = "PanGuoJun"
321
+ __description__ = "Python Hypergraphics Library"
322
+
323
+ # Package initialization information
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")
@@ -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')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: phg_vis
3
- Version: 1.3.1
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
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='phg_vis',
5
- version='1.3.1',
5
+ version='1.3.2',
6
6
  packages=find_packages(),
7
7
  include_package_data=True,
8
8
  description='A package for the PHG modeling language and 3D visualization tool.',
@@ -1,113 +0,0 @@
1
- """
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
- - Real-time and image rendering capabilities
12
-
13
- Version: 0.2.0
14
- Author: PanGuoJun
15
- License: MIT
16
- """
17
-
18
- from .visphg import vis, image
19
- from .shader_render import ShaderRenderer, render_shader
20
- from .phg_to_shader import PHGToShaderConverter, phg_to_shader
21
- from .pipe_string_phg import (
22
- world_pipe_to_phg,
23
- local_pipe_to_phg,
24
- world_pipestr_vis,
25
- local_pipestr_vis
26
- )
27
-
28
- # Extend ShaderRenderer class to support direct PHG rendering
29
- class PHGShaderRenderer(ShaderRenderer):
30
- """Shader renderer that supports direct PHG rendering"""
31
-
32
- def render_phg(self, phg_script: str, duration=0, interactive=True):
33
- """
34
- Render PHG script
35
-
36
- Parameters:
37
- phg_script: PHG script code
38
- duration: Render duration
39
- interactive: Whether to allow interaction
40
-
41
- Returns:
42
- success: Whether rendering was successful
43
- """
44
- converter = PHGToShaderConverter()
45
- shader_code = converter.generate_shader_code(phg_script)
46
-
47
- if not shader_code:
48
- print("Error: PHG conversion failed")
49
- return False
50
-
51
- return self.render_shader(shader_code, duration, interactive)
52
-
53
- # Convenience functions
54
- def render_phg(phg_script: str, width=800, height=600, duration=0, title="PHG Renderer"):
55
- """
56
- Directly render PHG script
57
-
58
- Parameters:
59
- phg_script: PHG script code
60
- width: Window width
61
- height: Window height
62
- duration: Render duration
63
- title: Window title
64
- """
65
- renderer = PHGShaderRenderer(width, height, title)
66
- success = renderer.render_phg(phg_script, duration)
67
- renderer.close()
68
- return success
69
-
70
- def convert_phg_to_shader(phg_script: str) -> str:
71
- """
72
- Convert PHG script to GLSL shader code
73
-
74
- Parameters:
75
- phg_script: PHG script
76
-
77
- Returns:
78
- shader_code: GLSL shader code
79
- """
80
- return phg_to_shader(phg_script)
81
-
82
- __all__ = [
83
- # Core visualization functions
84
- 'vis',
85
- 'image',
86
-
87
- # Shader rendering
88
- 'ShaderRenderer',
89
- 'render_shader',
90
- 'render_phg',
91
- 'PHGShaderRenderer',
92
-
93
- # PHG conversion
94
- 'PHGToShaderConverter',
95
- 'phg_to_shader',
96
- 'convert_phg_to_shader',
97
-
98
- # Pipe visualization
99
- 'world_pipe_to_phg',
100
- 'local_pipe_to_phg',
101
- 'world_pipestr_vis',
102
- 'local_pipestr_vis',
103
- ]
104
-
105
- __version__ = "1.3.1"
106
- __author__ = "PanGuoJun"
107
- __description__ = "Python Hypergraphics Library"
108
-
109
- # Package initialization information
110
- print(f"PHG {__version__} - {__description__}")
111
- print("[OK] Visualization module loaded")
112
- print("[OK] Shader converter loaded")
113
- print("[OK] Pipe visualization loaded")
@@ -1,285 +0,0 @@
1
- """
2
- Pipe String to PHG Converter
3
- ============================
4
-
5
- 该模块提供了管道字符串转换为PHG(Python Graphics)脚本的功能。
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: 前进 (Forward)
16
- - B: 后退 (Back)
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
- # 默认颜色和管径
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
- 将世界坐标系下的管道字符串转换为PHG脚本
33
-
34
- 参数:
35
- world_pipe_str: 世界坐标系管道字符串(如 "FFRUD")
36
- start_c: 起始坐标系
37
- pipe_color: 管道颜色,格式为(R, G, B)元组
38
- pipe_radius: 管道半径
39
-
40
- 返回:
41
- PHG脚本字符串
42
- """
43
-
44
- # 世界坐标系方向定义
45
- world_directions = {
46
- 'F': vec3(0, 0, 1), # 前(世界Z+)
47
- 'B': vec3(0, 0, -1), # 后(世界Z-)
48
- 'R': vec3(1, 0, 0), # 右(世界X+)
49
- 'L': vec3(-1, 0, 0), # 左(世界X-)
50
- 'U': vec3(0, 1, 0), # 上(世界Y+)
51
- 'D': vec3(0, -1, 0) # 下(世界Y-)
52
- }
53
-
54
- # 解析颜色
55
- r, g, b = pipe_color
56
-
57
- # 管道部件映射(所有部件使用固定长度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
- # 初始化当前坐标系(使用起始坐标系)
68
- cur_c = coord3(start_c.o, start_c.Q())
69
-
70
- # 存储所有管道部件的脚本
71
- script_parts = []
72
-
73
- # 遍历管道字符串中的每个字符
74
- for move_char in world_pipe_str:
75
- if move_char not in pipe_components:
76
- print(f"警告: 未知的管道字符 '{move_char}',已跳过")
77
- continue
78
-
79
- # 获取当前移动在世界坐标系中的方向
80
- world_dir = world_directions[move_char]
81
-
82
- # 将世界方向转换到当前局部坐标系
83
- local_dir = vec3(
84
- world_dir.dot(cur_c.ux), # 在局部X轴的分量
85
- world_dir.dot(cur_c.uy), # 在局部Y轴的分量
86
- world_dir.dot(cur_c.uz) # 在局部Z轴的分量
87
- )
88
-
89
- # 找到绝对值最大的分量来确定主要移动方向
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
- # 根据最大分量确定局部移动方向
94
- if max_idx == 0: # X轴
95
- local_move = 'R' if local_dir.x > 0 else 'L'
96
- elif max_idx == 1: # Y轴
97
- local_move = 'U' if local_dir.y > 0 else 'D'
98
- else: # Z轴
99
- local_move = 'F' if local_dir.z > 0 else 'B'
100
-
101
- # 添加对应的管道部件脚本
102
- script_parts.append(pipe_components[local_move])
103
-
104
- # 更新当前坐标系(模拟移动后的新位置和方向)
105
- if local_move == 'F':
106
- # 前进:沿局部Z轴正方向移动1.0单位
107
- cur_c = cur_c * coord3(vec3(0, 0, 1.0))
108
- elif local_move == 'B':
109
- # 后退:沿局部Z轴负方向移动1.0单位
110
- cur_c = cur_c * coord3(vec3(0, 0, -1.0))
111
- elif local_move == 'R':
112
- # 右转:绕Y轴旋转-90度,然后沿X轴移动1.0单位
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
- # 左转:绕Y轴旋转90度,然后沿X轴移动1.0单位
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
- # 上转:绕X轴旋转90度,然后沿Y轴移动1.0单位
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
- # 下转:绕X轴旋转-90度,然后沿Y轴移动1.0单位
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
- # 组合所有管道部件的脚本
133
- inner_script = ',\n'.join(script_parts)
134
-
135
- # 获取起始坐标系的四元数
136
- q = start_c.Q()
137
-
138
- # 构建完整的PHG脚本
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
- 将局部坐标系下的管道字符串转换为PHG脚本
150
-
151
- 参数:
152
- local_pipe_str: 局部坐标系管道字符串(如 "FFRUD")
153
- start_c: 起始坐标系
154
- pipe_color: 管道颜色,格式为(R, G, B)元组
155
- pipe_radius: 管道半径
156
-
157
- 返回:
158
- PHG脚本字符串
159
- """
160
-
161
- # 解析颜色
162
- r, g, b = pipe_color
163
-
164
- # 管道部件映射(所有部件使用固定长度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
- # 存储所有管道部件的脚本
175
- script_parts = []
176
-
177
- # 遍历管道字符串中的每个字符
178
- for move_char in local_pipe_str:
179
- if move_char not in pipe_components:
180
- print(f"警告: 未知的管道字符 '{move_char}',已跳过")
181
- continue
182
-
183
- # 直接使用局部坐标系的移动命令
184
- script_parts.append(pipe_components[move_char])
185
-
186
- # 组合所有管道部件的脚本
187
- inner_script = ',\n'.join(script_parts)
188
-
189
- # 获取起始坐标系的四元数
190
- q = start_c.Q()
191
-
192
- # 构建完整的PHG脚本
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_str, start_c=None, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
202
- """
203
- 世界坐标系管道字符串直接可视化
204
-
205
- 参数:
206
- world_pipe_str: 世界坐标系管道字符串(如 "FFRUD")
207
- start_c: 起始坐标系,默认为原点
208
- pipe_color: 管道颜色,格式为(R, G, B)元组
209
- pipe_radius: 管道半径
210
-
211
- 返回:
212
- PHG脚本字符串
213
- """
214
- # 如果没有提供起始坐标系,使用默认原点
215
- if start_c is None:
216
- start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
217
-
218
- # 生成PHG脚本
219
- phg_script = world_pipe_to_phg(world_pipe_str, start_c, pipe_color, pipe_radius)
220
-
221
- # 调用可视化函数
222
- try:
223
- from .visphg import vis
224
- vis(phg_script)
225
- except ImportError:
226
- print("警告: 无法导入可视化模块,返回PHG脚本")
227
-
228
- return phg_script
229
-
230
-
231
- def local_pipestr_vis(local_pipe_str, start_c=None, pipe_color=DEFAULT_PIPE_COLOR, pipe_radius=DEFAULT_PIPE_RADIUS):
232
- """
233
- 局部坐标系管道字符串直接可视化
234
-
235
- 参数:
236
- local_pipe_str: 局部坐标系管道字符串(如 "FFRUD")
237
- start_c: 起始坐标系,默认为原点
238
- pipe_color: 管道颜色,格式为(R, G, B)元组
239
- pipe_radius: 管道半径
240
-
241
- 返回:
242
- PHG脚本字符串
243
- """
244
- # 如果没有提供起始坐标系,使用默认原点
245
- if start_c is None:
246
- start_c = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
247
-
248
- # 生成PHG脚本
249
- phg_script = local_pipe_to_phg(local_pipe_str, start_c, pipe_color, pipe_radius)
250
-
251
- # 调用可视化函数
252
- try:
253
- from .visphg import vis
254
- vis(phg_script)
255
- except ImportError:
256
- print("警告: 无法导入可视化模块,返回PHG脚本")
257
-
258
- return phg_script
259
-
260
-
261
- # 使用示例
262
- if __name__ == "__main__":
263
- # 创建起始坐标系(示例)
264
- start_coord = coord3(vec3(0, 0, 0), quat(1, 0, 0, 0))
265
-
266
- # 示例1: 世界坐标系管道字符串
267
- example_world_pipe = "FFRUD" # 前进2次,右转,上转,下转
268
- print("世界坐标系管道示例:")
269
- phg_script = world_pipe_to_phg(example_world_pipe, start_coord)
270
- print("生成的PHG脚本:")
271
- print(phg_script)
272
- print()
273
-
274
- # 示例2: 局部坐标系管道字符串
275
- example_local_pipe = "FFRUD" # 在局部坐标系中的移动
276
- print("局部坐标系管道示例:")
277
- phg_script = local_pipe_to_phg(example_local_pipe, start_coord)
278
- print("生成的PHG脚本:")
279
- print(phg_script)
280
- print()
281
-
282
- # 示例3: 直接可视化
283
- print("直接可视化示例:")
284
- # world_pipestr_vis(example_world_pipe) # 世界坐标系可视化
285
- # local_pipestr_vis(example_local_pipe) # 局部坐标系可视化
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes