Domain Visualizer#

The pilot’s domain viewer (RDomainWidget) shows 2D and 3D unstructured-mesh domains and fields, rendered through Qt’s QRhi. It is hosted as a sub-window in the pilot and is fully controllable from Python: populate the scene, navigate the camera, toggle layers, and capture frames from code the same way the mouse drives them.

Showing a domain#

  • Mesh wireframe: updateMesh(mesh) draws the unstructured mesh (2D faces or 3D cells) as a wireframe; showMesh(on) toggles it.

  • Colored field: updateColorField(vertices, colors, indices) draws per-vertex-colored triangles over the domain. The field is swappable at runtime: call it again to replace the previous one.

  • Boundary highlight: showBoundary(ibc, on) highlights boundary set ibc.

  • Orientation guide: showAxis(on) shows a small axis triad in the corner, two axes for a 2D domain and three for a 3D one, oriented by the camera. It is hidden by default.

Camera navigation#

The viewer has one camera with three modes; each suits a different domain. Choose the mode from the View > Camera menu, or set cameraMode from Python.

Menu item (View > Camera)

cameraMode

Domain

Drag

Wheel / pinch

Orbit camera (3D)

"orbit"

3D

swing the eye around the center

dolly toward or away from the center

First-person camera (3D)

"fps"

3D

look around in place

dolly along the view direction

Pan / zoom camera (2D)

"pan"

2D

pan in the plane

zoom the orthographic view

Orbit is the default. It is a turntable orbit: the up axis stays fixed, so the horizon never rolls and a hard pitch past vertical eases off instead of flipping the view. Loading a 2D domain switches to pan/zoom automatically, because the orthographic projection a 2D domain uses ignores the orbit dolly and wants the in-plane wheel zoom instead.

Mouse, wheel, and pinch#

  • Left-drag rotates: orbit the center in orbit mode, look around in first-person mode, or pan in 2D pan/zoom mode.

  • Middle- or right-drag pans in any mode.

  • Wheel zooms; what it does depends on the mode (see the table above).

  • Pinch on a trackpad or touchscreen zooms in any mode.

Keyboard#

  • W / A / S / D or the arrow keys move the camera: forward and back, and strafe left and right.

  • Esc reframes the whole domain (fit to scene).

The View > Camera move submenu offers the same nudges as clickable actions, plus fixed-step yaw and pitch rotation and a reset.

From Python#

The camera exposes the same primitives the mouse and wheel drive, so a domain navigates identically from code:

from solvcon import pilot

mgr = pilot.RManager.instance.setUp()
viewer = mgr.add3DWidget()

viewer.updateMesh(mesh)             # show the wireframe
viewer.cameraMode = "orbit"         # orbit a 3D domain (the default)
viewer.fitCameraToScene()           # frame the whole domain

viewer.rotateCamera(40.0, 15.0)     # orbit by a pixel delta
viewer.panCamera(20.0, 0.0)         # pan by a pixel delta
viewer.zoomCamera(3.0)              # zoom by wheel notches
viewer.pinchCamera(1.5)             # zoom by a pinch factor (>1 zooms in)

The pose is readable and settable directly as (x, y, z) tuples through cameraPosition, cameraTarget, and cameraUp, so a view can be saved and restored, or set to an exact framing.

Capturing frames#

  • saveImage(path) renders the current frame offscreen and writes it to an image file.

  • clipImage() copies the current frame to the clipboard.

Both grab the frame deterministically inside the Qt event loop, which is what the pytest screenshot tests rely on.