yapcad.viewer package
Submodules
yapcad.viewer.api_server module
REST API and WebSocket Server
Flask-based REST API and SocketIO WebSocket server for remote viewer control.
This module provides a complete HTTP API for controlling the VTK viewer programmatically, along with WebSocket support for real-time event streaming.
Example Usage
Basic server startup:
from yapcad.viewer import VTKViewer, ViewerAPIServer, ViewerConfig
config = ViewerConfig(stl_dir="/path/to/stls")
viewer = VTKViewer(config)
server = ViewerAPIServer(viewer)
server.run(port=5000)
With custom configuration:
server = ViewerAPIServer(viewer, cors_origins=["http://localhost:3000"])
server.run(host="0.0.0.0", port=8080, debug=True)
REST API Endpoints
Status and Information:
GET /status- Get viewer statusGET /parts- List loaded partsGET /config- Get viewer configuration
Part Management:
POST /load- Load parts from JSON or part listPOST /reload- Reload positions from JSON filePOST /clear- Clear all parts
Rendering Controls:
POST /xray- Toggle or set x-ray modePOST /highlight- Highlight specific parts
Camera Controls:
POST /camera/reset- Reset camera to defaultPOST /camera/set- Set camera positionPOST /camera/orbit- Orbit camera around focal pointPOST /camera/focus- Focus on a specific part
Screenshot:
GET /screenshot- Capture and return screenshotPOST /screenshot- Capture and save screenshot
WebSocket Events
Server-to-Client:
status- Viewer status updatespart_loaded- Part was loadedpart_removed- Part was removedparts_cleared- All parts clearedxray_changed- X-ray mode changedcamera_changed- Camera position changedscreenshot_saved- Screenshot capturedselection_changed- Selection/highlight changederror- Error occurred
Client-to-Server:
command- Execute a viewer commandsubscribe- Subscribe to event typesunsubscribe- Unsubscribe from event types
Dependencies
Requires Flask and related packages:
pip install flask flask-socketio flask-cors
- class yapcad.viewer.api_server.ViewerAPIServer(viewer: VTKViewer, cors_origins: List[str] | None = None, async_mode: str = 'threading')[source]
Bases:
objectREST API and WebSocket server for the VTK viewer.
This class wraps a VTKViewer instance and provides HTTP endpoints and WebSocket events for remote control and monitoring.
- Parameters:
viewer (VTKViewer) – The viewer instance to control.
cors_origins (list of str, optional) – Allowed CORS origins. Default: [“*”] (all origins).
async_mode (str, optional) – SocketIO async mode. Default: “threading”.
- Variables:
viewer (VTKViewer) – The controlled viewer instance.
app (Flask) – The Flask application.
socketio (SocketIO) – The SocketIO instance.
Examples
Basic usage:
viewer = VTKViewer(config) server = ViewerAPIServer(viewer) server.run(port=5000)
With pre-configured Flask app:
app = Flask(__name__) viewer = VTKViewer(config) server = ViewerAPIServer(viewer) # Add custom routes to server.app server.run()
- run(host: str = '127.0.0.1', port: int = 5000, debug: bool = False, use_reloader: bool = False, viewer_in_background: bool = True)[source]
Start the API server.
- Parameters:
host (str, optional) – Host to bind to. Default: “127.0.0.1”.
port (int, optional) – Port to listen on. Default: 5000.
debug (bool, optional) – Enable Flask debug mode. Default: False.
use_reloader (bool, optional) – Enable auto-reload on code changes. Default: False.
viewer_in_background (bool, optional) – Run viewer rendering in background thread. Default: True.
Notes
This method blocks. The viewer render loop runs in a background thread if viewer_in_background is True.
Examples
Start server on default port:
server.run()
Start on custom host/port:
server.run(host="0.0.0.0", port=8080)
Start with debug mode:
server.run(debug=True)
yapcad.viewer.config module
Viewer Configuration
Configuration dataclass for the VTK viewer and API server.
Example Usage
Basic configuration:
from yapcad.viewer import ViewerConfig
config = ViewerConfig(
stl_dir="/path/to/stl/files",
positions_file="/path/to/positions.json",
window_size=(1600, 1000),
background_color=(0.12, 0.12, 0.15)
)
Configuration with file-based commands (backward compatibility):
config = ViewerConfig(
stl_dir="/path/to/stl/files",
command_file="/path/to/viewer_cmd.txt",
screenshot_dir="/path/to/screenshots"
)
- class yapcad.viewer.config.ViewerConfig(stl_dir: str, positions_file: str | None = None, command_file: str | None = None, screenshot_dir: str | None = None, window_size: Tuple[int, int]=(1600, 1000), window_title: str = 'yapCAD Assembly Viewer', background_color: Tuple[float, float, float]=(0.12, 0.12, 0.15), default_opacity: float = 1.0, xray_opacity: float = 0.4, default_color: Tuple[float, float, float]=(0.4, 0.4, 0.4), color_palette: Dict[str, ~typing.Tuple[float, float, float]]=<factory>, enable_multi_viewport: bool = True, command_poll_interval_ms: int = 100)[source]
Bases:
objectConfiguration for the VTK assembly viewer.
This dataclass holds all configuration options for the viewer including file paths, window settings, rendering options, and color schemes.
- Parameters:
stl_dir (str or Path) – Directory containing STL files to load.
positions_file (str or Path, optional) –
JSON file containing part positions and transforms. Expected format:
{ "PART_NAME": { "transform_matrix": [[...], [...], [...], [...]], "stl_file": "optional/path/to/file.stl", "color": [r, g, b] # optional, 0-1 range }, ... }
command_file (str or Path, optional) – Path to file-based command interface for backward compatibility. Commands are read from this file and executed.
screenshot_dir (str or Path, optional) – Directory for saving screenshots. Defaults to stl_dir/renders.
window_size (tuple of int, optional) – Window dimensions (width, height). Default: (1600, 1000).
window_title (str, optional) – Window title. Default: “yapCAD Assembly Viewer”.
background_color (tuple of float, optional) – Background color as RGB (0-1 range). Default: (0.12, 0.12, 0.15).
default_opacity (float, optional) – Default opacity for parts. Default: 1.0.
xray_opacity (float, optional) – Opacity when x-ray mode is enabled. Default: 0.4.
default_color (tuple of float, optional) – Default part color as RGB (0-1 range). Default: (0.4, 0.4, 0.4).
color_palette (dict, optional) – Named color palette for automatic color assignment. Keys are color names, values are RGB tuples (0-1 range).
enable_multi_viewport (bool, optional) – Enable 4-viewport mode (ISO, TOP, FRONT, SIDE). Default: True.
command_poll_interval_ms (int, optional) – Interval in milliseconds for polling command file. Default: 100.
- Variables:
stl_dir (Path) – Resolved STL directory path.
positions_file (Path or None) – Resolved positions file path.
command_file (Path or None) – Resolved command file path.
screenshot_dir (Path) – Resolved screenshot directory path.
Examples
Minimal configuration:
config = ViewerConfig(stl_dir="/my/stls")
Full configuration:
config = ViewerConfig( stl_dir="/my/stls", positions_file="/my/positions.json", window_size=(1920, 1080), background_color=(0.1, 0.1, 0.12), color_palette={ "primary": (0.2, 0.4, 0.8), "secondary": (0.8, 0.4, 0.2), "highlight": (1.0, 0.9, 0.2) } )
- background_color: Tuple[float, float, float] = (0.12, 0.12, 0.15)
- color_palette: Dict[str, Tuple[float, float, float]]
- command_file: str | None = None
- property command_path: Path | None
Get the resolved command file path.
- command_poll_interval_ms: int = 100
- default_color: Tuple[float, float, float] = (0.4, 0.4, 0.4)
- default_opacity: float = 1.0
- enable_multi_viewport: bool = True
- classmethod from_dict(data: Dict[str, Any]) ViewerConfig[source]
Create configuration from dictionary.
- Parameters:
data (dict) – Configuration dictionary.
- Returns:
New configuration instance.
- Return type:
- get_color(name: str) Tuple[float, float, float][source]
Get a color from the palette by name.
- Parameters:
name (str) – Color name (case-insensitive).
- Returns:
RGB color tuple (0-1 range).
- Return type:
tuple of float
Examples
>>> config = ViewerConfig(stl_dir="/tmp") >>> config.get_color("blue") (0.2, 0.4, 0.8) >>> config.get_color("unknown") # Returns default (0.4, 0.4, 0.4)
- positions_file: str | None = None
- property positions_path: Path | None
Get the resolved positions file path.
- screenshot_dir: str | None = None
- property screenshot_path: Path
Get the resolved screenshot directory path.
- stl_dir: str
- property stl_path: Path
Get the resolved STL directory path.
- to_dict() Dict[str, Any][source]
Convert configuration to dictionary.
- Returns:
Configuration as a dictionary suitable for JSON serialization.
- Return type:
dict
- window_size: Tuple[int, int] = (1600, 1000)
- window_title: str = 'yapCAD Assembly Viewer'
- xray_opacity: float = 0.4
yapcad.viewer.events module
WebSocket Event Types
Defines event types for WebSocket communication between the viewer server and connected clients.
Event Categories
- Client-to-Server Events:
Commands sent from clients to control the viewer.
- Server-to-Client Events:
Notifications sent from the viewer to connected clients.
Example Usage
Sending events from server:
from yapcad.viewer.events import ServerEvent, PartLoadedEvent
event = PartLoadedEvent(
part_name="AXIS1_SUN_GEAR",
stl_file="gearbox/axis1_sun_gear.stl",
bounds=[-10, 10, -10, 10, 0, 20]
)
socketio.emit(event.event_type, event.to_dict())
Handling events on client:
socket.on('part_loaded', (data) => {
console.log(`Loaded: ${data.part_name}`);
});
- class yapcad.viewer.events.BaseEvent[source]
Bases:
objectBase class for all WebSocket events.
- Variables:
event_type (str) – The event type identifier.
- event_type: str
- class yapcad.viewer.events.CameraChangedEvent(viewport: str, position: Tuple[float, float, float], focal_point: Tuple[float, float, float], view_up: Tuple[float, float, float] = (0.0, 0.0, 1.0))[source]
Bases:
BaseEventEvent emitted when camera position changes.
- Variables:
viewport (str) – Viewport name that changed.
position (tuple of float) – New camera position (x, y, z).
focal_point (tuple of float) – New focal point (x, y, z).
view_up (tuple of float) – View up vector.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“viewport”: “ISO”, “position”: [100.0, 100.0, 100.0], “focal_point”: [0.0, 0.0, 50.0], “view_up”: [0.0, 0.0, 1.0]
}
- focal_point: Tuple[float, float, float]
- position: Tuple[float, float, float]
- view_up: Tuple[float, float, float] = (0.0, 0.0, 1.0)
- viewport: str
- class yapcad.viewer.events.CommandMessage(command: str, params: Dict[str, ~typing.Any]=<factory>)[source]
Bases:
objectCommand message sent from client to server.
- Variables:
command (str) – Command type (from CommandType enum).
params (dict, optional) – Command parameters.
Example
Load command:
{ "command": "load", "params": { "parts": ["AXIS1_SUN_GEAR", "AXIS1_RING_HOUSING"], "clear": true } }
Screenshot command:
{ "command": "screenshot", "params": { "filename": "my_screenshot.png" } }
- command: str
- classmethod from_dict(data: Dict[str, Any]) CommandMessage[source]
Create command from dictionary.
- Parameters:
data (dict) – Command data with ‘command’ and optional ‘params’.
- Returns:
Parsed command message.
- Return type:
- params: Dict[str, Any]
- class yapcad.viewer.events.CommandType(*values)[source]
Bases:
str,EnumTypes of commands that can be sent to the viewer.
Commands
- LOAD
Load parts into the viewer.
- CLEAR
Clear all loaded parts.
- RELOAD
Reload positions from JSON file.
- XRAY
Toggle or set x-ray mode.
- SCREENSHOT
Capture a screenshot.
- FOCUS
Focus camera on a specific part.
- HIGHLIGHT
Highlight specific parts.
- CAMERA_RESET
Reset camera to default position.
- CAMERA_SET
Set camera position directly.
- CAMERA_ORBIT
Orbit camera around focal point.
- MOVE
Move a part by relative offset.
- MOVE_TO
Move a part to absolute position.
- CAMERA_ORBIT = 'camera_orbit'
- CAMERA_RESET = 'camera_reset'
- CAMERA_SET = 'camera_set'
- CLEAR = 'clear'
- FOCUS = 'focus'
- HIGHLIGHT = 'highlight'
- LOAD = 'load'
- MOVE = 'move'
- MOVE_TO = 'move_to'
- RELOAD = 'reload'
- SCREENSHOT = 'screenshot'
- XRAY = 'xray'
- class yapcad.viewer.events.ErrorEvent(message: str, code: str | None = None, details: Dict[str, Any] | None = None)[source]
Bases:
BaseEventEvent emitted when an error occurs.
- Variables:
message (str) – Error message.
code (str, optional) – Error code for programmatic handling.
details (dict, optional) – Additional error details.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“message”: “Failed to load STL file”, “code”: “LOAD_ERROR”, “details”: {“file”: “missing.stl”}
}
- code: str | None = None
- details: Dict[str, Any] | None = None
- message: str
- class yapcad.viewer.events.EventType(*values)[source]
Bases:
str,EnumEnumeration of all WebSocket event types.
Client-to-Server
- COMMAND
Execute a viewer command.
- SUBSCRIBE
Subscribe to specific event types.
- UNSUBSCRIBE
Unsubscribe from event types.
Server-to-Client
- STATUS
Viewer status update.
- PART_LOADED
Part was loaded into the scene.
- PART_REMOVED
Part was removed from the scene.
- PARTS_CLEARED
All parts were cleared.
- XRAY_CHANGED
X-ray mode was toggled.
- CAMERA_CHANGED
Camera position/orientation changed.
- SCREENSHOT_SAVED
Screenshot was captured and saved.
- SELECTION_CHANGED
Part selection changed.
- ERROR
An error occurred.
- CAMERA_CHANGED = 'camera_changed'
- COMMAND = 'command'
- ERROR = 'error'
- PARTS_CLEARED = 'parts_cleared'
- PART_LOADED = 'part_loaded'
- PART_REMOVED = 'part_removed'
- SCREENSHOT_SAVED = 'screenshot_saved'
- SELECTION_CHANGED = 'selection_changed'
- STATUS = 'status'
- SUBSCRIBE = 'subscribe'
- UNSUBSCRIBE = 'unsubscribe'
- XRAY_CHANGED = 'xray_changed'
- class yapcad.viewer.events.PartLoadedEvent(part_name: str, stl_file: str, bounds: List[float] = <factory>, color: Tuple[float, float, float] | None=None)[source]
Bases:
BaseEventEvent emitted when a part is loaded.
- Variables:
part_name (str) – Name/identifier of the loaded part.
stl_file (str) – Path to the STL file.
bounds (list of float) – Bounding box [xmin, xmax, ymin, ymax, zmin, zmax].
color (tuple of float, optional) – RGB color (0-1 range).
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“part_name”: “AXIS1_SUN_GEAR”, “stl_file”: “gearbox/axis1_sun_gear.stl”, “bounds”: [-10.0, 10.0, -10.0, 10.0, 0.0, 20.0], “color”: [0.8, 0.5, 0.2]
}
- bounds: List[float]
- color: Tuple[float, float, float] | None = None
- part_name: str
- stl_file: str
- class yapcad.viewer.events.PartRemovedEvent(part_name: str)[source]
Bases:
BaseEventEvent emitted when a part is removed.
- Variables:
part_name (str) – Name of the removed part.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“part_name”: “AXIS1_SUN_GEAR”
}
- part_name: str
- class yapcad.viewer.events.PartsClearedEvent(previous_count: int)[source]
Bases:
BaseEventEvent emitted when all parts are cleared.
- Variables:
previous_count (int) – Number of parts that were cleared.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“previous_count”: 42
}
- previous_count: int
- class yapcad.viewer.events.ScreenshotSavedEvent(filename: str, filepath: str, size: Tuple[int, int] = (0, 0))[source]
Bases:
BaseEventEvent emitted when a screenshot is saved.
- Variables:
filename (str) – Name of the saved file.
filepath (str) – Full path to the saved file.
size (tuple of int) – Image dimensions (width, height).
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“filename”: “screenshot_001.png”, “filepath”: “/path/to/renders/screenshot_001.png”, “size”: [1600, 1000]
}
- filename: str
- filepath: str
- size: Tuple[int, int] = (0, 0)
- class yapcad.viewer.events.SelectionChangedEvent(selected_parts: List[str] = <factory>, highlighted_parts: List[str] = <factory>)[source]
Bases:
BaseEventEvent emitted when part selection changes.
- Variables:
selected_parts (list of str) – Names of currently selected parts.
highlighted_parts (list of str) – Names of currently highlighted parts.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“selected_parts”: [“AXIS1_SUN_GEAR”], “highlighted_parts”: [“AXIS1_SUN_GEAR”, “AXIS1_RING_HOUSING”]
}
- highlighted_parts: List[str]
- selected_parts: List[str]
- class yapcad.viewer.events.StatusEvent(part_count: int, xray_enabled: bool, viewport: str = 'ISO', camera_position: Tuple[float, float, float] = (0.0, 0.0, 0.0), camera_focal_point: Tuple[float, float, float] = (0.0, 0.0, 0.0))[source]
Bases:
BaseEventViewer status update event.
Sent periodically or on request to provide current viewer state.
- Variables:
part_count (int) – Number of parts currently loaded.
xray_enabled (bool) – Whether x-ray mode is active.
viewport (str) – Current active viewport name.
camera_position (tuple of float) – Camera position (x, y, z).
camera_focal_point (tuple of float) – Camera focal point (x, y, z).
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“part_count”: 42, “xray_enabled”: false, “viewport”: “ISO”, “camera_position”: [100.0, 100.0, 100.0], “camera_focal_point”: [0.0, 0.0, 50.0]
}
- camera_focal_point: Tuple[float, float, float] = (0.0, 0.0, 0.0)
- camera_position: Tuple[float, float, float] = (0.0, 0.0, 0.0)
- part_count: int
- viewport: str = 'ISO'
- xray_enabled: bool
- class yapcad.viewer.events.XrayChangedEvent(enabled: bool, opacity: float)[source]
Bases:
BaseEventEvent emitted when x-ray mode changes.
- Variables:
enabled (bool) – Whether x-ray mode is now enabled.
opacity (float) – Current opacity value.
Event (WebSocket)
---------------
name (Event)
Payload:: –
- {
“enabled”: true, “opacity”: 0.4
}
- enabled: bool
- opacity: float
yapcad.viewer.vtk_viewer module
VTK-Based Assembly Viewer
Core VTK rendering engine for the yapCAD assembly viewer.
This module provides a general-purpose STL viewer with multi-viewport support, transform application, and real-time rendering capabilities. It is designed to work with any assembly defined by JSON position files and STL directories.
Example Usage
Basic usage:
from yapcad.viewer import VTKViewer, ViewerConfig
config = ViewerConfig(
stl_dir="/path/to/stls",
positions_file="/path/to/positions.json"
)
viewer = VTKViewer(config)
viewer.load_from_json()
viewer.start()
Manual part loading:
viewer = VTKViewer(config)
viewer.add_part(
name="my_part",
stl_path="/path/to/part.stl",
transform=[[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]],
color=(0.8, 0.4, 0.2)
)
viewer.start()
With file-based commands (backward compatibility):
config = ViewerConfig(
stl_dir="/path/to/stls",
command_file="/path/to/viewer_cmd.txt"
)
viewer = VTKViewer(config)
viewer.start() # Will poll command file for instructions
Dependencies
Requires VTK >= 9.0:
pip install vtk
- class yapcad.viewer.vtk_viewer.VTKViewer(config: ViewerConfig)[source]
Bases:
objectVTK-based multi-viewport assembly viewer.
This class provides a complete 3D viewer for STL assemblies with support for multiple viewports, transform application, x-ray mode, and various camera controls.
- Parameters:
config (ViewerConfig) – Viewer configuration object.
- Variables:
config (ViewerConfig) – Current configuration.
actors (dict) – Mapping of part names to VTK actors.
positions (dict) – Current part positions loaded from JSON.
xray_mode (bool) – Whether x-ray mode is currently enabled.
Examples
Create viewer and load from JSON:
config = ViewerConfig( stl_dir="/my/stls", positions_file="/my/positions.json" ) viewer = VTKViewer(config) viewer.load_from_json() viewer.start()
Create viewer and add parts manually:
viewer = VTKViewer(ViewerConfig(stl_dir="/my/stls")) viewer.add_part("gear", "/my/stls/gear.stl", transform, (0.8, 0.5, 0.2)) viewer.add_part("housing", "/my/stls/housing.stl", transform, (0.4, 0.4, 0.4)) viewer.start()
- add_part(name: str, stl_path: str | Path, transform: List[List[float]] | None = None, color: Tuple[float, float, float] | None = None) bool[source]
Add a single part to the viewer.
- Parameters:
name (str) – Unique identifier for the part.
stl_path (str or Path) – Path to the STL file.
transform (list of list of float, optional) – 4x4 transformation matrix. Identity matrix if not provided.
color (tuple of float, optional) – RGB color (0-1 range). Auto-assigned if not provided.
- Returns:
True if part was loaded successfully.
- Return type:
bool
Examples
Add a part with transform:
transform = [ [1, 0, 0, 10], [0, 1, 0, 20], [0, 0, 1, 30], [0, 0, 0, 1] ] viewer.add_part("my_gear", "/path/to/gear.stl", transform, (0.8, 0.5, 0.2))
Add a part at origin with auto color:
viewer.add_part("housing", "/path/to/housing.stl")
- focus_part(name: str)[source]
Focus all cameras on a specific part.
- Parameters:
name (str) – Name of the part to focus on.
- Raises:
KeyError – If part name is not found.
- get_camera_state(viewport: str = 'ISO') Dict[str, Any][source]
Get current camera state.
- Parameters:
viewport (str, optional) – Viewport to query. Default: “ISO”.
- Returns:
Camera state with position, focal_point, view_up.
- Return type:
dict
- get_part_bounds(name: str) Tuple[float, ...] | None[source]
Get bounding box of a specific part.
- Parameters:
name (str) – Part name.
- Returns:
Bounding box (xmin, xmax, ymin, ymax, zmin, zmax) or None.
- Return type:
tuple of float or None
- get_part_names() List[str][source]
Get list of loaded part names.
- Returns:
Names of all loaded parts.
- Return type:
list of str
- get_status() StatusEvent[source]
Get current viewer status.
- Returns:
Current viewer status.
- Return type:
- highlight_parts(names: List[str], dim_opacity: float = 0.15)[source]
Highlight specific parts by dimming others.
- Parameters:
names (list of str) – Part names to highlight.
dim_opacity (float, optional) – Opacity for non-highlighted parts. Default: 0.15.
Examples
Highlight gears:
viewer.highlight_parts(["SUN_GEAR", "RING_HOUSING"])
Clear highlighting (show all):
viewer.highlight_parts([]) # Or pass all part names
- load_from_json(positions_file: str | Path | None = None) int[source]
Load all parts defined in a positions JSON file.
The JSON file should have the format:
{ "PART_NAME": { "transform_matrix": [[...], [...], [...], [...]], "stl_file": "path/to/file.stl", // optional "color": [r, g, b] // optional, 0-1 range }, ... }
- Parameters:
positions_file (str or Path, optional) – Path to positions JSON file. Uses config.positions_file if not provided.
- Returns:
Number of parts successfully loaded.
- Return type:
int
- Raises:
FileNotFoundError – If positions file doesn’t exist.
- load_parts(part_specs: List[Tuple[str, str, str | None]], clear: bool = True) int[source]
Load multiple parts from specifications.
- Parameters:
part_specs (list of tuple) – List of (stl_file, part_name, color_name) tuples. stl_file is relative to stl_dir. color_name is optional; if None, auto-assigned.
clear (bool, optional) – Clear existing parts first. Default: True.
- Returns:
Number of parts successfully loaded.
- Return type:
int
Examples
Load multiple parts:
parts = [ ("gearbox/sun_gear.stl", "SUN_GEAR", "orange"), ("gearbox/ring_housing.stl", "RING_HOUSING", "brown"), ("motors/servo.stl", "SERVO", "dark"), ] viewer.load_parts(parts)
- move_part(name: str, dx: float, dy: float, dz: float)[source]
Move a part by relative offset.
- Parameters:
name (str) – Part name.
dx (float) – X offset.
dy (float) – Y offset.
dz (float) – Z offset.
- Raises:
KeyError – If part name is not found.
- move_part_to(name: str, x: float, y: float, z: float)[source]
Move a part to absolute position (centers part at position).
- Parameters:
name (str) – Part name.
x (float) – Target X coordinate.
y (float) – Target Y coordinate.
z (float) – Target Z coordinate.
- Raises:
KeyError – If part name is not found.
- on_event(event_type: str, callback: Callable[[Any], None])[source]
Register a callback for viewer events.
- Parameters:
event_type (str) – Event type to listen for (e.g., “part_loaded”, “xray_changed”).
callback (callable) – Function to call when event occurs. Receives event object.
Examples
Track loaded parts:
def on_load(event): print(f"Loaded: {event.part_name}") viewer.on_event("part_loaded", on_load)
- orbit_camera(azimuth: float, elevation: float, distance: float, viewport: str = 'ISO')[source]
Position camera using spherical coordinates around focal point.
- Parameters:
azimuth (float) – Azimuth angle in degrees (rotation around Z axis).
elevation (float) – Elevation angle in degrees (angle from XY plane).
distance (float) – Distance from focal point.
viewport (str, optional) – Viewport to modify. Default: “ISO”.
Examples
Orbit to 45 degrees azimuth, 30 degrees elevation:
viewer.orbit_camera(azimuth=45, elevation=30, distance=500)
- reload_positions()[source]
Reload positions from the JSON file and update transforms.
This updates transforms without reloading STL files, which is faster for iterating on kinematic positions.
- remove_part(name: str) bool[source]
Remove a part from the viewer.
- Parameters:
name (str) – Name of the part to remove.
- Returns:
True if part was found and removed.
- Return type:
bool
- screenshot(filename: str | None = None, directory: str | Path | None = None) str[source]
Capture a screenshot.
- Parameters:
filename (str, optional) – Output filename. Default: “screenshot.png”.
directory (str or Path, optional) – Output directory. Uses config.screenshot_dir if not provided.
- Returns:
Full path to saved screenshot.
- Return type:
str
Examples
Save with default name:
path = viewer.screenshot()
Save with custom name:
path = viewer.screenshot("my_view.png")
Save to custom directory:
path = viewer.screenshot("view.png", "/my/images")
- set_camera(position: Tuple[float, float, float], focal_point: Tuple[float, float, float], viewport: str = 'ISO', view_up: Tuple[float, float, float] = (0, 0, 1))[source]
Set camera position and orientation.
- Parameters:
position (tuple of float) – Camera position (x, y, z).
focal_point (tuple of float) – Point camera is looking at (x, y, z).
viewport (str, optional) – Viewport to modify. Default: “ISO”.
view_up (tuple of float, optional) – Up direction vector. Default: (0, 0, 1).
Examples
Set camera for isometric view:
viewer.set_camera( position=(200, 200, 150), focal_point=(0, 0, 50) )
- set_xray(enabled: bool, opacity: float | None = None)[source]
Enable or disable x-ray mode.
- Parameters:
enabled (bool) – Whether to enable x-ray mode.
opacity (float, optional) – Opacity value when x-ray is enabled. Uses config default if not provided.
Examples
Enable x-ray:
viewer.set_xray(True)
Enable with custom opacity:
viewer.set_xray(True, opacity=0.3)
Disable:
viewer.set_xray(False)
- start()[source]
Start the viewer main loop (blocking).
This starts the VTK interactor and blocks until the window is closed. Use this for standalone viewer applications.
Examples
Basic standalone usage:
viewer = VTKViewer(config) viewer.load_from_json() viewer.start() # Blocks until window closed
Module contents
yapCAD Viewer Package
A VTK-based 3D assembly viewer with REST API and WebSocket support.
This package provides a general-purpose STL viewer for visualizing assemblies with support for:
Multi-viewport rendering (ISO, TOP, FRONT, SIDE)
Real-time part positioning via 4x4 transform matrices
X-ray mode for internal inspection
REST API for programmatic control
WebSocket events for real-time updates
Optional file-based command interface for backward compatibility
Example Usage
Basic viewer with positions file:
from yapcad.viewer import VTKViewer, ViewerConfig
config = ViewerConfig(
stl_dir="/path/to/stl/files",
positions_file="/path/to/positions.json"
)
viewer = VTKViewer(config)
viewer.load_from_json()
viewer.start()
With REST API server:
from yapcad.viewer import VTKViewer, ViewerAPIServer, ViewerConfig
config = ViewerConfig(stl_dir="/path/to/stls")
viewer = VTKViewer(config)
server = ViewerAPIServer(viewer)
server.run(port=5000) # Viewer runs in background thread
Dependencies
- Required:
vtk >= 9.0
- Optional (for API server):
flask >= 2.0
flask-socketio >= 5.0
flask-cors >= 3.0
Module Contents
VTKViewer- Core VTK-based viewer with multi-viewport supportViewerAPIServer- Flask REST API and SocketIO WebSocket serverViewerConfig- Configuration dataclassevents- WebSocket event type definitions
Viewer system contributed by Jeremy Mika.