Skip to content

Commit ee1cf17

Browse files
committed
Fixed wireframe rendering in pyvista and Better pyvista example
1 parent 561e2ad commit ee1cf17

5 files changed

Lines changed: 112 additions & 97 deletions

File tree

api/pyvista_api.py

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -586,29 +586,8 @@ def gmesh_to_geant4_solid_and_params(gm, length_unit='mm', angle_unit='deg'):
586586
param_string = f"{px}*{length_unit}, {py}*{length_unit}, {pz}*{length_unit}"
587587
return "G4Box", param_string
588588

589-
# Cylinder (pv.Cylinder -> G4Tubs)
590-
# We'll assume direction=(0,0,1) in local coords,
591-
# so height is along Z, radius in XY.
592-
if _is_cylinder_like(mesh):
593-
rx = 0.5 * (xmax - xmin)
594-
ry = 0.5 * (ymax - ymin)
595-
rmax = 0.5 * ((xmax - xmin) + (ymax - ymin)) / 2.0
596-
rmin = 0.0 # solid tube
597-
half_z = 0.5 * (zmax - zmin)
598-
599-
sphi = 0.0
600-
dphi = 360.0
601-
602-
param_string = (
603-
f"{rmin}*{length_unit}, "
604-
f"{rmax}*{length_unit}, "
605-
f"{half_z}*{length_unit}, "
606-
f"{sphi}*{angle_unit}, "
607-
f"{dphi}*{angle_unit}"
608-
)
609-
return "G4Tubs", param_string
610-
611-
# Sphere (pv.Sphere -> G4Sphere)
589+
# Sphere must be checked before cylinder: a sphere also passes _is_cylinder_like
590+
# (both are "round in XY") so we disambiguate first by requiring all three extents equal.
612591
if _is_sphere_like(mesh):
613592
rx = 0.5 * (xmax - xmin)
614593
ry = 0.5 * (ymax - ymin)
@@ -631,6 +610,23 @@ def gmesh_to_geant4_solid_and_params(gm, length_unit='mm', angle_unit='deg'):
631610
)
632611
return "G4Sphere", param_string
633612

613+
# Cylinder (pv.Cylinder -> G4Tubs)
614+
# height along Z, radius in XY.
615+
if _is_cylinder_like(mesh):
616+
rmax = 0.5 * ((xmax - xmin) + (ymax - ymin)) / 2.0
617+
rmin = 0.0
618+
half_z = 0.5 * (zmax - zmin)
619+
sphi = 0.0
620+
dphi = 360.0
621+
param_string = (
622+
f"{rmin}*{length_unit}, "
623+
f"{rmax}*{length_unit}, "
624+
f"{half_z}*{length_unit}, "
625+
f"{sphi}*{angle_unit}, "
626+
f"{dphi}*{angle_unit}"
627+
)
628+
return "G4Tubs", param_string
629+
634630
# Not recognized yet (cones/polycones/etc.)
635631
return None, None
636632

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
11
#!/usr/bin/env python3
22

3-
# gemc api:
43
from gconfiguration import autogeometry
5-
from pyvista_api import GMesh
64
from gvolume import GVolume
7-
8-
# pyvista objects
95
from pyvista_basic_shapes import make_basic_shapes
106

11-
cfg = autogeometry(
12-
"examples",
13-
"simple_flux",
14-
auto_show=False, # don't show at exit
15-
enable_pyvista=True, # turn pyvista on without CLI
16-
use_background_plotter=True # non-blocking window
17-
)
18-
19-
7+
cfg = autogeometry("examples", "pyvista")
208

219
for gm in make_basic_shapes():
22-
gv = GVolume.from_gmesh(gm)
23-
gv.publish(cfg)
10+
gv = GVolume.from_gmesh(gm)
11+
gv.publish(cfg)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
experiment: examples
2+
runno: 1
3+
nthreads: 1
4+
5+
verbosity:
6+
- g4system: 1
7+
- gemc: 1
8+
9+
gsystem:
10+
- name: pyvista
11+
factory: sqlite
12+
13+
phys_list: QBBC
14+
15+
gparticle:
16+
- name: proton
17+
p: 1000
18+
vz: -5
19+
delta_vx: 0.5
20+
delta_vy: 0.5
21+
multiplicity: 5

examples/basic/pyvista/pyvista_basic_shapes.py

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,76 @@
55

66

77
def make_basic_shapes():
8-
gmeshes = []
9-
10-
# cube is the root, shifted -1 in x and rotated a bit
11-
cube_mesh = pv.Cube(
12-
x_length=2.0,
13-
y_length=1.0,
14-
z_length=4.0,
15-
)
16-
17-
# add material
18-
cube_gm = GMesh(
19-
name="cube",
20-
mesh=cube_mesh,
21-
material="G4_AIR",
22-
color="lightblue",
23-
opacity=0.4,
24-
position=(-1.0, 0.0, 0.0), # translation in world frame
25-
rotation=(0.0, 0.0, 10.0), # rotate cube 30° around Z
26-
)
27-
gmeshes.append(cube_gm)
28-
29-
# cylinder is defined at its own local origin (0,0,0), unrotated locally
30-
cyl_mesh = pv.Cylinder(
31-
radius=0.5,
32-
height=1.0,
33-
resolution=64,
34-
)
35-
36-
cyl_gm = GMesh(
37-
name="cylinder",
38-
mesh=cyl_mesh,
39-
mother="cube", # inside
40-
material="G4_WATER",
41-
color="lightgreen",
42-
position=(0.0, 0.2, 0.0), # 1 unit along mother's +Y
43-
rotation=(0.0, 10.0, 0.0), # rotate 10° around mother's Y
44-
)
45-
gmeshes.append(cyl_gm)
46-
47-
return gmeshes
8+
gmeshes = []
9+
10+
# --- Box: world-like container, slightly transparent ---
11+
box_mesh = pv.Cube(x_length=4.0, y_length=4.0, z_length=6.0)
12+
box_gm = GMesh(
13+
name="box",
14+
mesh=box_mesh,
15+
material="G4_AIR",
16+
color="ghostwhite",
17+
opacity=0.15,
18+
position=(0.0, 0.0, 0.0),
19+
rotation=(0.0, 0.0, 0.0),
20+
)
21+
gmeshes.append(box_gm)
22+
23+
# --- Cylinder: solid, inside the box ---
24+
cyl_mesh = pv.Cylinder(radius=0.6, height=2.0, resolution=64, direction=(0, 0, 1))
25+
cyl_gm = GMesh(
26+
name="cylinder",
27+
mesh=cyl_mesh,
28+
mother="box",
29+
material="G4_WATER",
30+
color="steelblue",
31+
opacity=1.0,
32+
position=(0.0, 0.0, -1.5),
33+
rotation=(0.0, 0.0, 0.0),
34+
)
35+
gmeshes.append(cyl_gm)
36+
37+
# --- Sphere: inside the box, demonstrates G4Sphere ---
38+
sphere_mesh = pv.Sphere(radius=0.7, theta_resolution=32, phi_resolution=32)
39+
sphere_gm = GMesh(
40+
name="sphere",
41+
mesh=sphere_mesh,
42+
mother="box",
43+
material="G4_Pb",
44+
color="tomato",
45+
opacity=0.85,
46+
position=(0.0, 0.0, 1.2),
47+
rotation=(0.0, 0.0, 0.0),
48+
)
49+
gmeshes.append(sphere_gm)
50+
51+
# --- Small rotated box: demonstrates rotation parameter ---
52+
rotbox_mesh = pv.Cube(x_length=1.2, y_length=0.4, z_length=1.2)
53+
rotbox_gm = GMesh(
54+
name="rotated_box",
55+
mesh=rotbox_mesh,
56+
mother="box",
57+
material="G4_Al",
58+
color="gold",
59+
opacity=0.9,
60+
position=(0.8, 0.8, 0.0),
61+
rotation=(0.0, 0.0, 35.0), # 35 degrees around Z
62+
)
63+
gmeshes.append(rotbox_gm)
64+
65+
return gmeshes
4866

4967

5068
if __name__ == "__main__":
69+
gmeshes = make_basic_shapes()
70+
pvmeshes = pvmeshes_from_gmeshes(gmeshes)
5171

52-
gmeshes = make_basic_shapes()
53-
pvmeshes = pvmeshes_from_gmeshes(gmeshes)
54-
55-
p = pv.Plotter()
56-
57-
# add world-space meshes
58-
for mesh, color, opacity in pvmeshes:
59-
p.add_mesh(mesh,
60-
color=color,
61-
opacity=opacity,
62-
show_edges=True)
63-
64-
# visual reference axes at world origin
65-
p.add_axes_at_origin(xlabel="X", ylabel="Y", zlabel="Z")
66-
p.show_axes()
67-
68-
set_yz_view_x_into_screen(p, distance=10.0)
72+
p = pv.Plotter()
6973

70-
p.show()
74+
for mesh, color, opacity in pvmeshes:
75+
p.add_mesh(mesh, color=color, opacity=opacity, show_edges=True)
7176

77+
p.add_axes_at_origin(xlabel="X", ylabel="Y", zlabel="Z")
78+
p.show_axes()
79+
set_yz_view_x_into_screen(p, distance=10.0)
80+
p.show()

releases/0.2.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,6 @@ Both x86_64 and ARM64 platforms are supported.
9696
- Adjusted system_template to provide simpler geometry and methane target material
9797
- Adjusted simple_flux target material to G4_lH2
9898
- Added handling of style=2 in pyvista: using cloud
99-
- Fixed wirefr
99+
- Fixed wireframe rendering in pyvista
100+
- Better pyvista example
100101
- Various code cleanups

0 commit comments

Comments
 (0)