phg-vis 1.2.1__py3-none-any.whl → 1.3.1__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/shader_render.py ADDED
@@ -0,0 +1,425 @@
1
+ import pygame
2
+ import numpy as np
3
+ from OpenGL.GL import *
4
+ from OpenGL.GL.shaders import compileProgram, compileShader
5
+ import sys
6
+ import time
7
+
8
+ class Camera:
9
+ """Camera class with mouse interaction controls"""
10
+
11
+ def __init__(self):
12
+ # Start further back to see the whole scene
13
+ self.position = np.array([0.0, 3.0, 12.0], dtype=np.float32) # Camera position - further back
14
+ self.target = np.array([0.0, 0.0, 0.0], dtype=np.float32) # Look at target
15
+ self.up = np.array([0.0, 1.0, 0.0], dtype=np.float32) # Up direction
16
+
17
+ # Camera parameters
18
+ self.fov = 45.0 # Field of view
19
+ self.zoom_speed = 0.5 # Increased zoom speed
20
+ self.rotate_speed = 0.01 # Increased rotate speed
21
+ self.pan_speed = 0.02 # Increased pan speed
22
+
23
+ # Mouse state
24
+ self.last_mouse_pos = None
25
+ self.is_rotating = False
26
+ self.is_panning = False
27
+
28
+ def zoom(self, delta):
29
+ """Zoom control"""
30
+ direction = self.target - self.position
31
+ distance = np.linalg.norm(direction)
32
+
33
+ # Limit min and max distance
34
+ min_distance = 1.0
35
+ max_distance = 100.0
36
+
37
+ new_distance = distance * (1.0 - delta * self.zoom_speed)
38
+ new_distance = np.clip(new_distance, min_distance, max_distance)
39
+
40
+ self.position = self.target - direction * (new_distance / distance)
41
+ print(f"Zoom: position={self.position}, distance={new_distance}")
42
+
43
+ def rotate(self, delta_x, delta_y):
44
+ """Rotation control"""
45
+ # Calculate vector from target to camera (inverse of camera to target)
46
+ direction = self.position - self.target
47
+ distance = np.linalg.norm(direction)
48
+
49
+ if distance < 0.001:
50
+ return
51
+
52
+ # Spherical coordinates rotation
53
+ # Convert to spherical coordinates
54
+ theta = np.arctan2(direction[0], direction[2]) # Horizontal angle (around Y axis)
55
+ phi = np.arctan2(direction[1], np.sqrt(direction[0]**2 + direction[2]**2)) # Vertical angle
56
+
57
+ # Apply rotation (inverted for more intuitive control)
58
+ theta -= delta_x * self.rotate_speed
59
+ phi += delta_y * self.rotate_speed # Inverted Y for more natural control
60
+
61
+ # Limit vertical angle (avoid flipping)
62
+ phi = np.clip(phi, -np.pi/2 + 0.1, np.pi/2 - 0.1)
63
+
64
+ # Convert back to Cartesian coordinates
65
+ new_x = distance * np.sin(theta) * np.cos(phi)
66
+ new_y = distance * np.sin(phi)
67
+ new_z = distance * np.cos(theta) * np.cos(phi)
68
+
69
+ self.position = self.target + np.array([new_x, new_y, new_z])
70
+
71
+ print(f"Rotate: position={self.position}")
72
+
73
+ def pan(self, delta_x, delta_y):
74
+ """Pan control"""
75
+ # Calculate camera coordinate system
76
+ forward = normalize(self.target - self.position)
77
+ right = normalize(np.cross(forward, self.up))
78
+ up = normalize(np.cross(right, forward))
79
+
80
+ # Apply pan (inverted for more intuitive control)
81
+ pan_distance = 0.1
82
+ pan_vector = -delta_x * right * self.pan_speed + delta_y * up * self.pan_speed
83
+
84
+ self.position += pan_vector
85
+ self.target += pan_vector
86
+
87
+ print(f"Pan: position={self.position}, target={self.target}")
88
+
89
+ def normalize(v):
90
+ """Normalize a vector"""
91
+ norm = np.linalg.norm(v)
92
+ if norm == 0:
93
+ return v
94
+ return v / norm
95
+
96
+ class ShaderRenderer:
97
+ """
98
+ Shader renderer class for visualizing GLSL shaders
99
+
100
+ Usage:
101
+ renderer = ShaderRenderer()
102
+ renderer.render_shader(fragment_shader_code)
103
+ """
104
+
105
+ def __init__(self, width=800, height=600, title="Shader Renderer"):
106
+ """
107
+ Initialize Shader renderer
108
+
109
+ Args:
110
+ width: Window width
111
+ height: Window height
112
+ title: Window title
113
+ """
114
+ self.width = width
115
+ self.height = height
116
+ self.title = title
117
+ self.is_running = False
118
+ self.shader_program = None
119
+ self.start_time = 0
120
+ self.camera = Camera()
121
+ self.show_help = True
122
+
123
+ self.vertex_shader_src = """
124
+ #version 330 core
125
+ layout (location = 0) in vec3 aPos;
126
+ layout (location = 1) in vec2 aTexCoord;
127
+
128
+ out vec2 TexCoord;
129
+
130
+ void main()
131
+ {
132
+ gl_Position = vec4(aPos, 1.0);
133
+ TexCoord = aTexCoord;
134
+ }
135
+ """
136
+
137
+ self._init_pygame()
138
+ self._init_opengl()
139
+ self._create_geometry()
140
+ self._init_font()
141
+
142
+ def _init_pygame(self):
143
+ """Initialize Pygame and OpenGL context"""
144
+ pygame.init()
145
+ self.screen = pygame.display.set_mode((self.width, self.height), pygame.OPENGL | pygame.DOUBLEBUF)
146
+ pygame.display.set_caption(self.title)
147
+
148
+ def _init_opengl(self):
149
+ """Initialize OpenGL settings"""
150
+ glClearColor(0.0, 0.0, 0.0, 1.0)
151
+ glEnable(GL_BLEND)
152
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
153
+
154
+ def _init_font(self):
155
+ """Initialize font for text rendering"""
156
+ self.font = pygame.font.Font(None, 24)
157
+ self.small_font = pygame.font.Font(None, 18)
158
+
159
+ def _create_geometry(self):
160
+ """Create geometry required for rendering"""
161
+ # Vertex data: position + texture coordinates
162
+ self.vertices = np.array([
163
+ # Position # Texture coordinates
164
+ -1.0, -1.0, 0.0, 0.0, 0.0,
165
+ 1.0, -1.0, 0.0, 1.0, 0.0,
166
+ 1.0, 1.0, 0.0, 1.0, 1.0,
167
+ -1.0, 1.0, 0.0, 0.0, 1.0
168
+ ], dtype=np.float32)
169
+
170
+ self.indices = np.array([
171
+ 0, 1, 2,
172
+ 2, 3, 0
173
+ ], dtype=np.uint32)
174
+
175
+ # Create VAO, VBO, EBO
176
+ self.VAO = glGenVertexArrays(1)
177
+ self.VBO = glGenBuffers(1)
178
+ self.EBO = glGenBuffers(1)
179
+
180
+ glBindVertexArray(self.VAO)
181
+
182
+ glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
183
+ glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
184
+
185
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
186
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
187
+
188
+ # Position attribute
189
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * self.vertices.itemsize, ctypes.c_void_p(0))
190
+ glEnableVertexAttribArray(0)
191
+
192
+ # Texture coordinate attribute
193
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * self.vertices.itemsize, ctypes.c_void_p(3 * self.vertices.itemsize))
194
+ glEnableVertexAttribArray(1)
195
+
196
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
197
+ glBindVertexArray(0)
198
+
199
+ def _compile_shader(self, fragment_src):
200
+ """
201
+ Compile shader program
202
+
203
+ Args:
204
+ fragment_src: Fragment shader code
205
+
206
+ Returns:
207
+ shader_program: Compiled shader program, None if failed
208
+ """
209
+ try:
210
+ vertex_shader = compileShader(self.vertex_shader_src, GL_VERTEX_SHADER)
211
+ fragment_shader = compileShader(fragment_src, GL_FRAGMENT_SHADER)
212
+ shader_program = compileProgram(vertex_shader, fragment_shader)
213
+ return shader_program
214
+ except Exception as e:
215
+ print(f"Shader compilation error: {e}")
216
+ return None
217
+
218
+ def _render_help_text(self):
219
+ """Render help text on screen"""
220
+ # Switch to 2D rendering for text
221
+ glDisable(GL_DEPTH_TEST)
222
+
223
+ # Create a semi-transparent background for better readability
224
+ help_lines = [
225
+ "=== CAMERA CONTROLS ===",
226
+ "LEFT CLICK + DRAG: Rotate Camera",
227
+ "MIDDLE CLICK + DRAG: Pan Camera",
228
+ "MOUSE WHEEL: Zoom In/Out",
229
+ "R: Reset Camera Position",
230
+ "H: Toggle This Help",
231
+ "ESC: Exit Renderer",
232
+ "",
233
+ "Camera debugging enabled - check console"
234
+ ]
235
+
236
+ y_offset = 20
237
+ for i, line in enumerate(help_lines):
238
+ if i == 0: # Header
239
+ text_surface = self.font.render(line, True, (255, 255, 0))
240
+ else:
241
+ text_surface = self.small_font.render(line, True, (255, 255, 255))
242
+ self.screen.blit(text_surface, (20, y_offset))
243
+ y_offset += 22 if i == 0 else 18
244
+
245
+ # Camera position info
246
+ cam_info = [
247
+ f"Camera Pos: ({self.camera.position[0]:.1f}, {self.camera.position[1]:.1f}, {self.camera.position[2]:.1f})",
248
+ f"Camera Target: ({self.camera.target[0]:.1f}, {self.camera.target[1]:.1f}, {self.camera.target[2]:.1f})"
249
+ ]
250
+
251
+ y_offset += 10
252
+ for info in cam_info:
253
+ text_surface = self.small_font.render(info, True, (0, 255, 255))
254
+ self.screen.blit(text_surface, (20, y_offset))
255
+ y_offset += 18
256
+
257
+ glEnable(GL_DEPTH_TEST)
258
+
259
+ def render_shader(self, fragment_shader, duration=0, interactive=True):
260
+ """
261
+ Render specified shader
262
+
263
+ Args:
264
+ fragment_shader: Fragment shader code string
265
+ duration: Render duration in seconds, 0 for infinite
266
+ interactive: Allow interaction (ESC to exit)
267
+
268
+ Returns:
269
+ success: Whether rendering was successful
270
+ """
271
+ # Compile shader
272
+ self.shader_program = self._compile_shader(fragment_shader)
273
+ if not self.shader_program:
274
+ return False
275
+
276
+ # Get uniform locations
277
+ time_loc = glGetUniformLocation(self.shader_program, "time")
278
+ resolution_loc = glGetUniformLocation(self.shader_program, "resolution")
279
+ mouse_loc = glGetUniformLocation(self.shader_program, "mouse")
280
+ camera_pos_loc = glGetUniformLocation(self.shader_program, "cameraPosition")
281
+ camera_target_loc = glGetUniformLocation(self.shader_program, "cameraTarget")
282
+ camera_up_loc = glGetUniformLocation(self.shader_program, "cameraUp")
283
+ camera_fov_loc = glGetUniformLocation(self.shader_program, "cameraFov")
284
+
285
+ self.is_running = True
286
+ self.start_time = time.time()
287
+ clock = pygame.time.Clock()
288
+
289
+ mouse_pos = [0.0, 0.0]
290
+
291
+ print("Renderer started! Camera controls:")
292
+ print("- Left mouse button + drag: Rotate")
293
+ print("- Middle mouse button + drag: Pan")
294
+ print("- Mouse wheel: Zoom")
295
+ print("- R: Reset camera")
296
+ print("- H: Toggle help")
297
+
298
+ while self.is_running:
299
+ current_time = time.time() - self.start_time
300
+
301
+ # Handle events
302
+ for event in pygame.event.get():
303
+ if event.type == pygame.QUIT:
304
+ self.is_running = False
305
+ elif event.type == pygame.KEYDOWN:
306
+ if event.key == pygame.K_ESCAPE and interactive:
307
+ self.is_running = False
308
+ elif event.key == pygame.K_r: # R key to reset camera
309
+ self.camera = Camera()
310
+ print("Camera reset to default position")
311
+ elif event.key == pygame.K_h: # H key to toggle help
312
+ self.show_help = not self.show_help
313
+ print(f"Help display: {'ON' if self.show_help else 'OFF'}")
314
+
315
+ # Handle mouse events for camera control
316
+ if interactive:
317
+ if event.type == pygame.MOUSEBUTTONDOWN:
318
+ if event.button == 1: # Left button - rotate
319
+ self.camera.is_rotating = True
320
+ self.camera.last_mouse_pos = event.pos
321
+ print("Rotation started")
322
+ elif event.button == 2: # Middle button - pan
323
+ self.camera.is_panning = True
324
+ self.camera.last_mouse_pos = event.pos
325
+ print("Panning started")
326
+ elif event.button == 4: # Wheel up - zoom in
327
+ self.camera.zoom(1.0)
328
+ elif event.button == 5: # Wheel down - zoom out
329
+ self.camera.zoom(-1.0)
330
+
331
+ elif event.type == pygame.MOUSEBUTTONUP:
332
+ if event.button == 1: # Left button release
333
+ self.camera.is_rotating = False
334
+ print("Rotation ended")
335
+ elif event.button == 2: # Middle button release
336
+ self.camera.is_panning = False
337
+ print("Panning ended")
338
+ self.camera.last_mouse_pos = None
339
+
340
+ elif event.type == pygame.MOUSEMOTION:
341
+ # Update mouse position for shader
342
+ mouse_pos[0] = event.pos[0] / self.width
343
+ mouse_pos[1] = 1.0 - event.pos[1] / self.height
344
+
345
+ # Handle camera movement
346
+ if self.camera.last_mouse_pos is not None:
347
+ delta_x = event.pos[0] - self.camera.last_mouse_pos[0]
348
+ delta_y = event.pos[1] - self.camera.last_mouse_pos[1]
349
+
350
+ if self.camera.is_rotating:
351
+ self.camera.rotate(delta_x, delta_y)
352
+ elif self.camera.is_panning:
353
+ self.camera.pan(delta_x, delta_y)
354
+
355
+ self.camera.last_mouse_pos = event.pos
356
+
357
+ # Check duration
358
+ if duration > 0 and current_time >= duration:
359
+ break
360
+
361
+ # Render
362
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
363
+
364
+ glUseProgram(self.shader_program)
365
+
366
+ # Set uniforms
367
+ if time_loc != -1:
368
+ glUniform1f(time_loc, current_time)
369
+ if resolution_loc != -1:
370
+ glUniform2f(resolution_loc, self.width, self.height)
371
+ if mouse_loc != -1:
372
+ glUniform2f(mouse_loc, mouse_pos[0], mouse_pos[1])
373
+ if camera_pos_loc != -1:
374
+ glUniform3f(camera_pos_loc,
375
+ self.camera.position[0],
376
+ self.camera.position[1],
377
+ self.camera.position[2])
378
+ if camera_target_loc != -1:
379
+ glUniform3f(camera_target_loc,
380
+ self.camera.target[0],
381
+ self.camera.target[1],
382
+ self.camera.target[2])
383
+ if camera_up_loc != -1:
384
+ glUniform3f(camera_up_loc,
385
+ self.camera.up[0],
386
+ self.camera.up[1],
387
+ self.camera.up[2])
388
+ if camera_fov_loc != -1:
389
+ glUniform1f(camera_fov_loc, self.camera.fov)
390
+
391
+ glBindVertexArray(self.VAO)
392
+ glDrawElements(GL_TRIANGLES, len(self.indices), GL_UNSIGNED_INT, None)
393
+ glBindVertexArray(0)
394
+
395
+ # Render help text if enabled
396
+ if self.show_help:
397
+ self._render_help_text()
398
+
399
+ pygame.display.flip()
400
+ clock.tick(60)
401
+
402
+ return True
403
+
404
+ def close(self):
405
+ """Clean up resources"""
406
+ if self.shader_program:
407
+ glDeleteProgram(self.shader_program)
408
+ pygame.quit()
409
+
410
+ # Convenience function
411
+ def render_shader(fragment_shader, width=800, height=600, duration=0, title="Shader Renderer"):
412
+ """
413
+ Convenience function: Directly render shader
414
+
415
+ Args:
416
+ fragment_shader: Fragment shader code
417
+ width: Window width
418
+ height: Window height
419
+ duration: Render duration in seconds
420
+ title: Window title
421
+ """
422
+ renderer = ShaderRenderer(width, height, title)
423
+ success = renderer.render_shader(fragment_shader, duration)
424
+ renderer.close()
425
+ return success
phg/vis/GCU.dll CHANGED
Binary file
phg/vis/vis.exe CHANGED
Binary file
phg/vis/vis.ini CHANGED
@@ -1,4 +1,4 @@
1
- CAMERA=0.000,10.000,18.000;0.000,0.000,0.000;0.000,1.000,0.000;0.724;1.610;0;10.000;0.000,0.000,0.000
1
+ CAMERA=4.057,2.604,-0.507;3.490,2.240,-0.436;0.000,1.000,0.000;0.175;1.610;0;10.000;0.000,0.000,0.000
2
2
  CONSOLE=true
3
3
  ENABLE_DUAL_SCREEN=false
4
4
  HOSTIP=127.0.0.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: phg_vis
3
- Version: 1.2.1
3
+ Version: 1.3.1
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 - Minimalist 3D Modeling Language
16
+ # PHG - Python Hypergraphics Library
17
17
 
18
- PHG (Bacteriophage) is a specialized modeling language for describing 3D scene node trees. Combining concepts from group theory, it provides custom overloading capabilities for variables and operations, making it particularly suitable for describing complex 3D scenes and 2D sprite structures.
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
- - **Topological Structures** - Two organization methods: sequence and array composition
28
- - **Visualization Rendering** - Powerful offscreen rendering and screenshot capabilities
29
- - **Python Integration** - Convenient Python API
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
  ---
@@ -0,0 +1,22 @@
1
+ phg/__init__.py,sha256=TvWMc1ho6g9enlj0nhtr5eidViu6xyt0CrUOW31Q9F4,3097
2
+ phg/phg_to_shader.py,sha256=rb_LnGE1Py08oz72ES5CnjyCDbjVWDU3If0cYZq4SUU,15172
3
+ phg/pipe_string_phg.py,sha256=FPFatph2WCVoUzEflIJWRotwH0Yb79VJaKvmyaj4zDI,10654
4
+ phg/shader_render.py,sha256=_T8IFp1h5Hcj8TMMHwFMbxhGdHLnOqka7pJ4pde7zMA,16780
5
+ phg/visphg.py,sha256=CtALoNJs0eDT8wnXk_76XG4UsOcV6cWucvWqz7AhOSc,1923
6
+ phg/vis/GCU.dll,sha256=k_slWZ5nOzZNi9zCe0_SKc0F7zXoLyRuRDomyirPY4I,2687488
7
+ phg/vis/dragpad.exe,sha256=4qWG4VH1vginIGpKkBHwEBFlpTY8G6xPejeloJurNkE,51712
8
+ phg/vis/dragpad_config.ini,sha256=MD5no-RjzzcBxyz3JWuI88qH5Q4WVivRLqk_1GE5VQY,78
9
+ phg/vis/freeglut.dll,sha256=UguleTwzNznvcYqQ9qWDtplQUj1vAH27-ah64uK1QYE,266240
10
+ phg/vis/lua.dll,sha256=Hu9gnBvdBIpM-DeVH1Cem5BrW5YZz1_9LvWrD_9jkCY,247296
11
+ phg/vis/pycoder.exe,sha256=joyuVRBleLmOsxQjaq1iauHxC0BbQGKf8Mnwmx4xrVA,61440
12
+ phg/vis/script.phg,sha256=HfEBk9omTAfm-KywupQwAwqgHqsr5hCS0f7gfBH1mYY,123
13
+ phg/vis/sqlite3.dll,sha256=pTf_jpQLK7vaDLipxp4qhPB_MkByPgC-RKXTmmKiy_w,1066496
14
+ phg/vis/vis.exe,sha256=9LGgETiO4lwhz_gJzdUg6gPP9EwGLT5SuLjN3wR2sso,1388032
15
+ phg/vis/vis.ini,sha256=IjS0Av2BqresPR2oGCOoq5zliXN2wFRMK3rXcU15vKs,161
16
+ phg/vis/zlib1.dll,sha256=oVw_r326ve3oveVZhlSiF8BloZQ6lfqXJEAhUYfMjOQ,89088
17
+ phg/vis/imgui/main.lua,sha256=AIB5dpGrPHXuRiNW7Bg7eu5Lpi2DDcn6n4JS7OS1Hdk,4742
18
+ phg_vis-1.3.1.dist-info/LICENSE,sha256=tDnRkJxBYPzWdfh2gArRqrUPJxQZRZHJVs68qqBHIq4,1083
19
+ phg_vis-1.3.1.dist-info/METADATA,sha256=rJB_6RA15BncZfzq2BPKCgI02cesmNrB67eIzPtdpbM,17945
20
+ phg_vis-1.3.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
21
+ phg_vis-1.3.1.dist-info/top_level.txt,sha256=5GGhpTP8yi-zTXwW2HrI-zcxKxIM_nHXhL7r0iIDE_k,4
22
+ phg_vis-1.3.1.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- phg/__init__.py,sha256=NJ8TboT5zwztJYpKB68iVO3kSkeKas2A6-8dzoN5XyE,79
2
- phg/visphg.py,sha256=CtALoNJs0eDT8wnXk_76XG4UsOcV6cWucvWqz7AhOSc,1923
3
- phg/vis/GCU.dll,sha256=L0zNAMJlTY4xJo_tMFHahZt1lt3XdcYZUpJBY9u8iwI,2673664
4
- phg/vis/dragpad.exe,sha256=4qWG4VH1vginIGpKkBHwEBFlpTY8G6xPejeloJurNkE,51712
5
- phg/vis/dragpad_config.ini,sha256=MD5no-RjzzcBxyz3JWuI88qH5Q4WVivRLqk_1GE5VQY,78
6
- phg/vis/freeglut.dll,sha256=UguleTwzNznvcYqQ9qWDtplQUj1vAH27-ah64uK1QYE,266240
7
- phg/vis/lua.dll,sha256=Hu9gnBvdBIpM-DeVH1Cem5BrW5YZz1_9LvWrD_9jkCY,247296
8
- phg/vis/pycoder.exe,sha256=joyuVRBleLmOsxQjaq1iauHxC0BbQGKf8Mnwmx4xrVA,61440
9
- phg/vis/script.phg,sha256=HfEBk9omTAfm-KywupQwAwqgHqsr5hCS0f7gfBH1mYY,123
10
- phg/vis/sqlite3.dll,sha256=pTf_jpQLK7vaDLipxp4qhPB_MkByPgC-RKXTmmKiy_w,1066496
11
- phg/vis/vis.exe,sha256=Th41OzrW5t-0KQfLkw_0dZVUuQ5catAJS7EOrSlUSgo,1388032
12
- phg/vis/vis.ini,sha256=bmF3_kgbLAkiNBQi0ErDE9laZjvOmUSb9GQAISV8qeA,161
13
- phg/vis/zlib1.dll,sha256=oVw_r326ve3oveVZhlSiF8BloZQ6lfqXJEAhUYfMjOQ,89088
14
- phg/vis/imgui/main.lua,sha256=AIB5dpGrPHXuRiNW7Bg7eu5Lpi2DDcn6n4JS7OS1Hdk,4742
15
- phg_vis-1.2.1.dist-info/LICENSE,sha256=tDnRkJxBYPzWdfh2gArRqrUPJxQZRZHJVs68qqBHIq4,1083
16
- phg_vis-1.2.1.dist-info/METADATA,sha256=upOOXCMVRg3b65ronejn8nO1AyDeNMMt9N_DcmDmC2A,14855
17
- phg_vis-1.2.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
18
- phg_vis-1.2.1.dist-info/top_level.txt,sha256=5GGhpTP8yi-zTXwW2HrI-zcxKxIM_nHXhL7r0iIDE_k,4
19
- phg_vis-1.2.1.dist-info/RECORD,,