A package for the PHG modeling language and 3D visualization tool.
Project description
PHG - Minimalist 3D Modeling Language
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.
🌟 Features
- Minimalist Syntax - Declarative node tree description
- Hierarchical Modeling - Support for nested nodes and transform inheritance
- Parametric Design - Flexible property system and function definitions
- Topological Structures - Two organization methods: sequence and array composition
- Visualization Rendering - Powerful offscreen rendering and screenshot capabilities
- Python Integration - Convenient Python API
📦 Installation
pip install phg_vis
Or install from source:
pip install phg
🚀 Quick Start
Python Usage
import phg
# Define PHG code
phg_code = """
{
# Create a simple cylinder
base{md:cylinder 5 10; rgb:100,150,200}
}setup_draw();
"""
# Execute PHG code
phg.run(phg_code)
Visualization Rendering
import phg
# Method 1: Direct rendering
phg.image("box(10);", filename="cube.png")
# Method 2: Complex scene rendering
scene = """
{
base{md:cylinder 10 2; rgb:100,100,100}
column{md:cylinder 5 20; y:2; rgb:200,200,200}
top{md:cone 5 3 3; y:22; rgb:150,150,150}
structure{[base,column,top]}
}setup_draw(structure);
"""
phg.image(scene, filename="tower.png")
# Method 3: Multi-view rendering
phg.image("sphere(5);|||view=2 width=1920 height=1080", filename="top_view.png")
📖 Syntax Reference
1. Basic Structure
{
# Scene node definitions
node definitions...
}setup();draw(); # or setup_draw();
Key Points:
- All nodes must be defined within the root node (anonymous braces)
- Call
setup();draw();orsetup_draw()at the end for scene rendering - Use
#for single-line comments
2. Node Definition
2.1 Basic Syntax
nodeName{attributes and content}
2.2 Node Attributes
| Attribute Type | Syntax | Description |
|---|---|---|
| Position | x:value y:value z:value |
Single-axis position |
| Position (Combined) | xyz:x,y,z |
Three-axis position |
| Rotation | rx:angle ry:angle rz:angle |
Single-axis rotation (degrees) |
| Rotation (Combined) | rxyz:x,y,z |
Three-axis rotation |
| Scale | s:scale |
Uniform scaling |
| Color | rgb:red,green,blue |
RGB color (0-255) |
| Tessellation | ts:subdivisions |
Curve/surface subdivision level |
Examples:
node1{x:10; y:20; z:30; rx:45; ry:90; rz:0}
node2{xyz:10,20,30; rxyz:45,90,0; s:2.0}
node3{rgb:255,128,0; ts:32}
2.3 Node Composition Methods
Sequence Composition (Transform Propagation):
parent{<child1,child2,child3>}
- Use angle brackets
<>for sequences - Parent node transforms are propagated sequentially to child nodes
- Commonly used for creating repetitive patterns (turbine blades, gear teeth)
Array Composition (Independent Transforms):
group{[item1,item2,item3]}
- Use square brackets
[]for arrays - Each child node maintains independent transforms
- Used for combining unrelated components
Comparison Example:
{
# Sequence: Each box accumulates rotation
gear1{<box1,box1,box1,box1>; rz:90} # Four boxes at 0°, 90°, 180°, 270°
# Array: Each box has independent transform
gear2{[box1{rz:0},box1{rz:90},box1{rz:180},box1{rz:270}]}
}
2.4 Node Reference and Reuse
# Define template node
template{md:cylinder 10 20}
# Reference node
instance1{template; x:10} # Inherit template and add translation
instance2{{template; s:0.5}; y:20} # Scale first, then translate
3. Model Definition (md Command)
3.1 Basic Syntax
{md:commandName param1 param2 ...}
3.2 2D Shapes
| Command | Syntax | Description |
|---|---|---|
| Rectangle | md:rect width height |
Rectangle |
| Circle | md:circle radius |
Circle |
| Ellipse | md:ellipse2d majorAxis minorAxis |
Ellipse |
| Polygon | md:poly x1,y1,z1 x2,y2,z2 ... |
Arbitrary polygon |
Examples:
rect1{md:rect 10 20}
circle1{md:circle 5; ts:64} # 64 subdivisions
triangle{md:poly 0,0,0 10,0,0 5,10,0}
3.3 3D Primitives
| Command | Syntax | Description |
|---|---|---|
| Cylinder | md:cylinder radius height |
Cylinder |
| Cone | md:cone bottomRadius topRadius height |
Cone/Frustum |
| Spherical Crown | md:sphericalcrown radiusX radiusY radiusZ |
Spherical cap/hemisphere |
| Box | md:box length width height |
Box |
Examples:
cylinder1{md:cylinder 5 10}
cone1{md:cone 5 2 8}
hemisphere{md:sphericalcrown 3 3 1.5}
box1{md:box 10 5 2}
3.4 Curve Commands
Interpolated Curves:
{md:ccurve interpolationType startNode endNode}
Interpolation Types:
lerpTX- Linear interpolation (tangent X direction)lerpTY- Linear interpolation (tangent Y direction)lerpTZ- Linear interpolation (tangent Z direction)lerp- Standard linear interpolation
Example:
{
p1{} p2{x:10; rz:15}
curve1{md:ccurve lerpTX p1 p2}
}
3.5 Surface Commands
Patch:
{md:face interpolationType curve1 curve2}
Extrusion:
{md:extrudex profile xStart yStart length}
Loft:
{md:loft profile1 profile2 path parameters}
4. Data Structures
4.1 Location Data (Locations)
{md:Locations;
list:"
1
1 0 0 # x coordinate
0 1 0 # y coordinate
0 0 1 # z coordinate
"
}
4.2 Curve Data (Curves)
{md:Curves;
list:"
type param1 param2 param3 dirX dirY dirZ
"
}
5. Control Statements
5.1 Conditional Statement
?(condition) { statement } : { else_statement };
5.2 Loop Statement
@n { statement1 ? (_i = x) ~; statement2; }
5.3 Function Definition
$functionName(args...) { statement; $return }
6. Scene Rendering Functions
setup();draw(); # Setup and draw entire scene
setup_draw(); # Combined call
setup_draw(node1); # Draw specified node
setup_draw(node1,node2,...); # Draw multiple specified nodes
🎨 Visualization Features
1. Interactive Screenshot (UI Button)
Click the Shot button in the 3D view interface to take a screenshot.
Features:
- One-click operation with auto-generated timestamped filename
- Default save location: Desktop as
screenshot_YYYYMMDD_HHMMSS.png - Real-time notification of screenshot results
2. Python API Rendering (Recommended)
import phg
# Default screenshot (shot.png)
phg.image("box(10);")
# Specify filename
phg.image("box(10);", filename="cube_render.png")
# Full path
phg.image("box(10);", filename="C:/output/result.png")
# Advanced: Custom resolution and view
phg_code = "box(10);"
phg.image(phg_code + "|||width=1920 height=1080 view=2")
3. HTTP API
Save to File:
POST http://127.0.0.1:5088/phg_img
Content-Type: text/plain
box(10);|||file=output.png width=1920 height=1080 view=0
Return Binary Data:
POST http://127.0.0.1:5088/phg_img
Content-Type: text/plain
box(10);|||width=800 height=600
4. Rendering Parameters
Request Body Format:
<PHG_CODE>|||<PARAMETERS>
Available Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
file |
string | - | Output filename, omit for binary return |
width |
int | 1288 | Render width (pixels) |
height |
int | 800 | Render height (pixels) |
view |
int | 3 | View mode (see table below) |
quality |
string | high | Render quality: high/low |
View Modes:
| Value | Mode | Description |
|---|---|---|
| 0 | Front | Front view (orthographic projection) |
| 1 | Right | Right view (orthographic projection) |
| 2 | Top | Top view (orthographic projection) |
| 3 | Perspective | Perspective view (default) |
5. Batch Rendering Example
import phg
# Batch generate different views
views = [(0,"front"), (1,"right"), (2,"top"), (3,"perspective")]
phg_code = "box(10);"
for view_id, view_name in views:
phg.image(
f"{phg_code}|||view={view_id}",
filename=f"cube_{view_name}.png"
)
# Batch render different sizes
for size in [5, 10, 15, 20]:
phg.image(f"box({size});", filename=f"box_{size}.png")
💡 Complete Examples
Example 1: Simple Geometry
{
# Create a cylinder with base
base{md:cylinder 10 2; rgb:100,100,100}
column{md:cylinder 5 20; y:2; rgb:200,200,200}
top{md:cone 5 3 3; y:22; rgb:150,150,150}
structure{[base,column,top]}
}setup_draw(structure);
Example 2: Parametric Gear
{
# Create gear tooth
tooth{md:box 2 5 3; z:10}
# Create gear by rotating around center (8 teeth)
gear{
<tooth,tooth,tooth,tooth,tooth,tooth,tooth,tooth>
rz:45 # Each tooth automatically rotates 45° (360/8)
}
# Center shaft
shaft{md:cylinder 3 10; rgb:50,50,50}
# Assembly
assembly{[gear,shaft]; rx:90}
}setup_draw(assembly);
Example 3: Turbine Blade (Complex Assembly)
{
# Define control points
p1{}
p2{x:4; rz:15}
p3{x:4; rz:-15}
# Create curves
c1{{md:ccurve lerpTX p1 p2}{md:ccurve lerpTX p1 p3}}
c2{c1; z:14; rz:75; s:0.75}
# Create blade surface
blade{{md:face lerp c1 c2; z:2; rz:90}ry:15}
# Create impeller (24 blades)
wheel{<blade,blade,blade,blade,blade,blade,blade,blade,
blade,blade,blade,blade,blade,blade,blade,blade,
blade,blade,blade,blade,blade,blade,blade,blade>}
# Hub
hub{md:cylinder 8 5; rgb:80,80,80}
# Assembly
turbine{[wheel,hub]}
}setup_draw(turbine);
Example 4: Python Rendering Workflow
import phg
# Define complex scene
scene = """
{
# Ground
ground{md:cylinder 20 0.5; rgb:80,80,80}
# Main structure
base{md:cylinder 5 2; y:0.5; rgb:150,150,150}
column{md:cylinder 2 10; y:3.5; rgb:200,200,200}
top{md:cone 3 0 2; y:9; rgb:180,180,180}
# Decoration
ring1{md:cylinder 4 0.3; y:5; rgb:255,200,0}
ring2{md:cylinder 4 0.3; y:7; rgb:255,200,0}
# Assembly
monument{[ground,base,column,top,ring1,ring2]}
}setup_draw(monument);
"""
# Render multiple views
phg.image(scene + "|||view=3", filename="monument_perspective.png")
phg.image(scene + "|||view=0", filename="monument_front.png")
phg.image(scene + "|||view=2 width=2560 height=1440", filename="monument_top_4k.png")
🎯 Best Practices
1. Naming Conventions
- Use meaningful node names
- Use lowercase letters and underscores
- Avoid using PHG keywords as node names
2. Structure Organization
- Group related nodes together
- Use comments to explain complex structures
- Use node references to reduce repetition
3. Performance Optimization
- Set appropriate tessellation levels (
tsparameter) - Reuse node definitions instead of recreating
- Use sequence and array composition appropriately
4. Debugging Tips
- Build complex models incrementally
- Use
setup_draw(nodeName)to test nodes individually - Check coordinate system and transform order
📚 Built-in Functions
Math Functions
rnd()- Random numbersin()- Sinecos()- Cosine
Node Operations
im()- Image operationson()- Enable nodewak()- Wake nodedump()- Dump node data
Data Conversion
tojson()- Convert to JSON format
🔧 Coordinate System
Coordinate System
- Uses right-hand coordinate system
- X-axis: Right
- Y-axis: Up
- Z-axis: Forward
Rotation Rules
- Rotation angle unit is degrees
- Positive rotation follows right-hand rule
Transform Order
- Transform order: Scale → Rotation → Translation
- Child node transforms are applied on top of parent transforms
❓ FAQ
Q1: What's the difference between sequences and arrays?
- Sequence
<a,b,c>equals{a {b {c}}}- Transforms accumulate - Array
[a,b,c]equals{{a}{b}{c}}- Transforms are independent
Q2: How to create repetitive structures?
Use sequence composition <> with rotation:
# Create 8 evenly distributed elements
element{md:box 2 2 2; z:10; rz:45}
ring{<element,element,element,element,element,element,element,element>}
Q3: How to set transparent background?
Currently the rendering engine uses RGB format and doesn't support transparent backgrounds. For transparency, remove the background color in post-processing.
Q4: Is there a resolution limit for rendering?
Recommended maximum resolution is 4096 x 4096. Excessively large resolutions may cause insufficient GPU memory or rendering failures.
🔗 Links
📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
PHG is inspired by concepts from group theory, aiming to provide a flexible way to describe complex data structures in programming. Special thanks to all developers who have contributed to the PHG ecosystem.
🤝 Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
© 2025 PHG - Minimalist 3D Modeling Language
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phg_vis-1.2.1.tar.gz.
File metadata
- Download URL: phg_vis-1.2.1.tar.gz
- Upload date:
- Size: 2.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2bb5800b1989669ded412d9b738ac920d3b4a927c5b27565c8b0cd835eb1f913
|
|
| MD5 |
6e42472804956dd4bbb25117aee6c54e
|
|
| BLAKE2b-256 |
337e5b285b3719f94dd9c18f825080b1b6713b00fb48c4067b4b277102b58b47
|
File details
Details for the file phg_vis-1.2.1-py3-none-any.whl.
File metadata
- Download URL: phg_vis-1.2.1-py3-none-any.whl
- Upload date:
- Size: 2.7 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2af36e29421a02f2a88459b9c9979953189bcc10597b1bbf89b7242aada8733
|
|
| MD5 |
4fef633b419b66074e8eb7a4fb7bf038
|
|
| BLAKE2b-256 |
e7698326a97a9774855d054ff4dd47b641aaad688d0d919ed191ddf538152519
|