ansys-pyensight-core 0.10.12__py3-none-any.whl → 0.10.13__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.
Potentially problematic release.
This version of ansys-pyensight-core might be problematic. Click here for more details.
- ansys/pyensight/core/dockerlauncher.py +50 -0
- ansys/pyensight/core/launcher.py +4 -1
- ansys/pyensight/core/locallauncher.py +56 -0
- ansys/pyensight/core/utils/omniverse.py +11 -1
- ansys/pyensight/core/utils/omniverse_dsg_server.py +26 -14
- ansys/pyensight/core/utils/views.py +21 -138
- {ansys_pyensight_core-0.10.12.dist-info → ansys_pyensight_core-0.10.13.dist-info}/METADATA +1 -1
- {ansys_pyensight_core-0.10.12.dist-info → ansys_pyensight_core-0.10.13.dist-info}/RECORD +10 -10
- {ansys_pyensight_core-0.10.12.dist-info → ansys_pyensight_core-0.10.13.dist-info}/WHEEL +0 -0
- {ansys_pyensight_core-0.10.12.dist-info → ansys_pyensight_core-0.10.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -539,6 +539,9 @@ class DockerLauncher(Launcher):
|
|
|
539
539
|
# http port
|
|
540
540
|
wss_cmd += " --http_port " + str(self._service_host_port["http"][1])
|
|
541
541
|
# vnc port
|
|
542
|
+
if int(self._ansys_version) > 252:
|
|
543
|
+
wss_cmd += " --separate_loops"
|
|
544
|
+
wss_cmd += f" --security_token {self._secret_key}"
|
|
542
545
|
wss_cmd += " --client_port 1999"
|
|
543
546
|
# optional PIM instance header
|
|
544
547
|
if self._pim_instance is not None:
|
|
@@ -598,11 +601,58 @@ class DockerLauncher(Launcher):
|
|
|
598
601
|
|
|
599
602
|
return session
|
|
600
603
|
|
|
604
|
+
def close(self, session):
|
|
605
|
+
"""Shut down the launched EnSight session.
|
|
606
|
+
|
|
607
|
+
This method closes all associated sessions and then stops the
|
|
608
|
+
launched EnSight instance.
|
|
609
|
+
|
|
610
|
+
Parameters
|
|
611
|
+
----------
|
|
612
|
+
session : ``pyensight.Session``
|
|
613
|
+
Session to close.
|
|
614
|
+
|
|
615
|
+
Raises
|
|
616
|
+
------
|
|
617
|
+
RuntimeError
|
|
618
|
+
If the session was not launched by this launcher.
|
|
619
|
+
|
|
620
|
+
"""
|
|
621
|
+
if self._enshell:
|
|
622
|
+
if self._enshell.is_connected(): # pragma: no cover
|
|
623
|
+
logging.debug("Killing WSS\n")
|
|
624
|
+
command = 'pkill -f "websocketserver.py"'
|
|
625
|
+
kill_env_vars = None
|
|
626
|
+
container_env_str = ""
|
|
627
|
+
if self._pim_instance is not None:
|
|
628
|
+
container_env = self._get_container_env()
|
|
629
|
+
for i in container_env.items():
|
|
630
|
+
container_env_str += f"{i[0]}={i[1]}\n"
|
|
631
|
+
if container_env_str: # pragma: no cover
|
|
632
|
+
kill_env_vars = container_env_str # pragma: no cover
|
|
633
|
+
ret = self._enshell.start_other(command, extra_env=kill_env_vars)
|
|
634
|
+
if ret[0] != 0: # pragma: no cover
|
|
635
|
+
pass
|
|
636
|
+
return super().close(session)
|
|
637
|
+
|
|
601
638
|
def stop(self) -> None:
|
|
602
639
|
"""Release any additional resources allocated during launching."""
|
|
603
640
|
if self._enshell:
|
|
604
641
|
if self._enshell.is_connected(): # pragma: no cover
|
|
605
642
|
try:
|
|
643
|
+
logging.debug("Killing WSS\n")
|
|
644
|
+
command = 'pkill -f "websocketserver.py"'
|
|
645
|
+
kill_env_vars = None
|
|
646
|
+
container_env_str = ""
|
|
647
|
+
if self._pim_instance is not None:
|
|
648
|
+
container_env = self._get_container_env()
|
|
649
|
+
for i in container_env.items():
|
|
650
|
+
container_env_str += f"{i[0]}={i[1]}\n"
|
|
651
|
+
if container_env_str: # pragma: no cover
|
|
652
|
+
kill_env_vars = container_env_str # pragma: no cover
|
|
653
|
+
ret = self._enshell.start_other(command, extra_env=kill_env_vars)
|
|
654
|
+
if ret[0] != 0: # pragma: no cover
|
|
655
|
+
pass
|
|
606
656
|
logging.debug("Stopping EnShell.\n")
|
|
607
657
|
self._enshell.stop_server()
|
|
608
658
|
except Exception: # pragma: no cover
|
ansys/pyensight/core/launcher.py
CHANGED
|
@@ -186,7 +186,10 @@ class Launcher:
|
|
|
186
186
|
url = f"http://{session.hostname}:{session.html_port}/v1/stop"
|
|
187
187
|
if session.secret_key: # pragma: no cover
|
|
188
188
|
url += f"?security_token={session.secret_key}"
|
|
189
|
-
|
|
189
|
+
try:
|
|
190
|
+
_ = requests.get(url)
|
|
191
|
+
except requests.exceptions.ConnectionError:
|
|
192
|
+
pass
|
|
190
193
|
|
|
191
194
|
# Stop the launcher instance
|
|
192
195
|
self.stop()
|
|
@@ -24,6 +24,7 @@ import ansys.pyensight.core as pyensight
|
|
|
24
24
|
from ansys.pyensight.core.common import find_unused_ports
|
|
25
25
|
from ansys.pyensight.core.launcher import Launcher
|
|
26
26
|
import ansys.pyensight.core.session
|
|
27
|
+
import psutil
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class LocalLauncher(Launcher):
|
|
@@ -283,6 +284,9 @@ class LocalLauncher(Launcher):
|
|
|
283
284
|
cmd.extend(["--grpc_port", str(self._ports[0])])
|
|
284
285
|
# EnVision sessions
|
|
285
286
|
cmd.extend(["--local_session", "envision", "5"])
|
|
287
|
+
if int(version) > 252:
|
|
288
|
+
cmd.append("--separate_loops")
|
|
289
|
+
cmd.append(["--security_token", self._secret_key])
|
|
286
290
|
# websocket port
|
|
287
291
|
cmd.append(str(self._ports[3]))
|
|
288
292
|
logging.debug(f"Starting WSS: {cmd}\n")
|
|
@@ -322,6 +326,38 @@ class LocalLauncher(Launcher):
|
|
|
322
326
|
self.launch_webui(version, popen_common)
|
|
323
327
|
return session
|
|
324
328
|
|
|
329
|
+
@staticmethod
|
|
330
|
+
def _kill_process_unix(pid):
|
|
331
|
+
external_kill = ["kill", "-9", str(pid)]
|
|
332
|
+
process = psutil.Popen(external_kill, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
|
333
|
+
process.wait()
|
|
334
|
+
|
|
335
|
+
@staticmethod
|
|
336
|
+
def _kill_process_windows(pid):
|
|
337
|
+
external_kill = ["taskkill", "/F", "/PID", str(pid)]
|
|
338
|
+
process = psutil.Popen(external_kill, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
|
339
|
+
process.wait()
|
|
340
|
+
|
|
341
|
+
def _kill_process_by_pid(self, pid):
|
|
342
|
+
if self._is_windows():
|
|
343
|
+
self._kill_process_windows(pid)
|
|
344
|
+
else:
|
|
345
|
+
self._kill_process_unix(pid)
|
|
346
|
+
|
|
347
|
+
def _kill_process_tree(self, pid):
|
|
348
|
+
try:
|
|
349
|
+
parent = psutil.Process(pid)
|
|
350
|
+
for child in parent.children(recursive=True):
|
|
351
|
+
try:
|
|
352
|
+
self._kill_process_by_pid(child.pid)
|
|
353
|
+
child.kill()
|
|
354
|
+
except (psutil.AccessDenied, psutil.ZombieProcess, OSError, psutil.NoSuchProcess):
|
|
355
|
+
continue
|
|
356
|
+
self._kill_process_by_pid(parent.pid)
|
|
357
|
+
parent.kill()
|
|
358
|
+
except (psutil.AccessDenied, psutil.ZombieProcess, OSError, psutil.NoSuchProcess):
|
|
359
|
+
pass
|
|
360
|
+
|
|
325
361
|
def stop(self) -> None:
|
|
326
362
|
"""Release any additional resources allocated during launching."""
|
|
327
363
|
maximum_wait_secs = 120.0
|
|
@@ -340,6 +376,26 @@ class LocalLauncher(Launcher):
|
|
|
340
376
|
raise
|
|
341
377
|
raise RuntimeError(f"Unable to remove {self.session_directory} in {maximum_wait_secs}s")
|
|
342
378
|
|
|
379
|
+
def close(self, session):
|
|
380
|
+
"""Shut down the launched EnSight session.
|
|
381
|
+
|
|
382
|
+
This method closes all associated sessions and then stops the
|
|
383
|
+
launched EnSight instance.
|
|
384
|
+
|
|
385
|
+
Parameters
|
|
386
|
+
----------
|
|
387
|
+
session : ``pyensight.Session``
|
|
388
|
+
Session to close.
|
|
389
|
+
|
|
390
|
+
Raises
|
|
391
|
+
------
|
|
392
|
+
RuntimeError
|
|
393
|
+
If the session was not launched by this launcher.
|
|
394
|
+
|
|
395
|
+
"""
|
|
396
|
+
self._kill_process_tree(self._websocketserver_pid)
|
|
397
|
+
return super().close(session)
|
|
398
|
+
|
|
343
399
|
@staticmethod
|
|
344
400
|
def get_cei_install_directory(ansys_installation: Optional[str]) -> str:
|
|
345
401
|
"""Get the Ansys distribution CEI directory to use.
|
|
@@ -272,7 +272,17 @@ def find_app(ansys_installation: Optional[str] = None) -> Optional[str]:
|
|
|
272
272
|
if os.path.exists(local_tp):
|
|
273
273
|
dirs_to_check.append(local_tp)
|
|
274
274
|
# Dev Folder
|
|
275
|
-
|
|
275
|
+
omni_platform_dir = "linux-x86_64"
|
|
276
|
+
if sys.platform.startswith("win"):
|
|
277
|
+
omni_platform_dir = "windows-x86_64"
|
|
278
|
+
local_dev_omni = os.path.join(
|
|
279
|
+
ansys_installation,
|
|
280
|
+
"omni_build",
|
|
281
|
+
"kit-app-template",
|
|
282
|
+
"_build",
|
|
283
|
+
omni_platform_dir,
|
|
284
|
+
"release",
|
|
285
|
+
)
|
|
276
286
|
if os.path.exists(local_dev_omni):
|
|
277
287
|
dirs_to_check.append(local_dev_omni)
|
|
278
288
|
if "PYENSIGHT_ANSYS_INSTALLATION" in os.environ:
|
|
@@ -38,7 +38,7 @@ import numpy
|
|
|
38
38
|
import png
|
|
39
39
|
|
|
40
40
|
try:
|
|
41
|
-
from pxr import Gf, Sdf, Usd, UsdGeom, UsdLux, UsdShade
|
|
41
|
+
from pxr import Gf, Kind, Sdf, Usd, UsdGeom, UsdLux, UsdShade
|
|
42
42
|
except ModuleNotFoundError:
|
|
43
43
|
if sys.version_info.minor >= 14:
|
|
44
44
|
warnings.warn("USD Export not supported for Python >= 3.14")
|
|
@@ -77,6 +77,7 @@ class OmniverseWrapper(object):
|
|
|
77
77
|
self.destination = destination
|
|
78
78
|
|
|
79
79
|
self._line_width = line_width
|
|
80
|
+
self._centroid: Optional[list] = None
|
|
80
81
|
# Record the files per timestep, per mesh type. {part_name: {"surfaces": [], "lines": [], "points": []} }
|
|
81
82
|
self._time_files: dict = {}
|
|
82
83
|
|
|
@@ -307,8 +308,7 @@ class OmniverseWrapper(object):
|
|
|
307
308
|
|
|
308
309
|
part_prim = stage.OverridePrim(part_path)
|
|
309
310
|
|
|
310
|
-
surfaces_prim =
|
|
311
|
-
surfaces_prim.AddXformOp(UsdGeom.XformOp.TypeTransform, UsdGeom.XformOp.PrecisionDouble)
|
|
311
|
+
surfaces_prim = self.create_xform_node(stage, part_path + "/surfaces")
|
|
312
312
|
mesh = UsdGeom.Mesh.Define(stage, str(surfaces_prim.GetPath()) + "/Mesh")
|
|
313
313
|
mesh.CreateDoubleSidedAttr().Set(True)
|
|
314
314
|
pt_attr = mesh.CreatePointsAttr()
|
|
@@ -483,9 +483,8 @@ class OmniverseWrapper(object):
|
|
|
483
483
|
|
|
484
484
|
part_prim = stage.OverridePrim(part_path)
|
|
485
485
|
|
|
486
|
-
lines_prim =
|
|
486
|
+
lines_prim = self.create_xform_node(stage, part_path + "/lines")
|
|
487
487
|
|
|
488
|
-
lines_prim.AddXformOp(UsdGeom.XformOp.TypeTransform, UsdGeom.XformOp.PrecisionDouble)
|
|
489
488
|
lines = UsdGeom.BasisCurves.Define(stage, str(lines_prim.GetPath()) + "/Lines")
|
|
490
489
|
lines.CreateDoubleSidedAttr().Set(True)
|
|
491
490
|
pt_attr = lines.CreatePointsAttr()
|
|
@@ -790,9 +789,20 @@ class OmniverseWrapper(object):
|
|
|
790
789
|
shutil.rmtree(uriPath, ignore_errors=True, onerror=None)
|
|
791
790
|
shutil.copytree(f"{tempdir}/scratch/Textures", uriPath)
|
|
792
791
|
|
|
792
|
+
def create_xform_node(self, stage, name):
|
|
793
|
+
xform_node = UsdGeom.Xform.Define(stage, name)
|
|
794
|
+
xform_node.AddTranslateOp().Set((0, 0, 0))
|
|
795
|
+
xform_node.AddRotateXYZOp().Set((0, 0, 0))
|
|
796
|
+
xform_node.AddScaleOp().Set((1, 1, 1))
|
|
797
|
+
if self._centroid is not None:
|
|
798
|
+
xform_api = UsdGeom.XformCommonAPI(xform_node.GetPrim())
|
|
799
|
+
xform_api.SetPivot(Gf.Vec3f(self._centroid) * self._units_per_meter)
|
|
800
|
+
return xform_node
|
|
801
|
+
|
|
793
802
|
def create_dsg_root(self):
|
|
794
803
|
root_name = "/Root"
|
|
795
|
-
|
|
804
|
+
self.create_xform_node(self._stage, root_name)
|
|
805
|
+
|
|
796
806
|
# Define the defaultPrim as the /Root prim
|
|
797
807
|
root_prim = self._stage.GetPrimAtPath(root_name)
|
|
798
808
|
self._stage.SetDefaultPrim(root_prim)
|
|
@@ -863,22 +873,18 @@ class OmniverseWrapper(object):
|
|
|
863
873
|
path = parent_prim.GetPath().AppendChild(self.clean_name(name))
|
|
864
874
|
group_prim = UsdGeom.Xform.Get(self._stage, path)
|
|
865
875
|
if not group_prim:
|
|
866
|
-
group_prim =
|
|
867
|
-
|
|
868
|
-
matrix_op = group_prim.AddXformOp(
|
|
869
|
-
UsdGeom.XformOp.TypeTransform, UsdGeom.XformOp.PrecisionDouble
|
|
870
|
-
)
|
|
871
|
-
matrix_op.Set(Gf.Matrix4d(*matrix).GetTranspose())
|
|
876
|
+
group_prim = self.create_xform_node(self._stage, path)
|
|
877
|
+
|
|
872
878
|
# Map kinds
|
|
873
|
-
"""
|
|
874
879
|
kind = Kind.Tokens.group
|
|
875
880
|
if obj_type == "ENS_CASE":
|
|
876
881
|
kind = Kind.Tokens.assembly
|
|
877
882
|
elif obj_type == "ENS_PART":
|
|
878
883
|
kind = Kind.Tokens.component
|
|
879
884
|
Usd.ModelAPI(group_prim).SetKind(kind)
|
|
885
|
+
group_prim.GetPrim().SetDisplayName(name)
|
|
880
886
|
logging.info(f"Created group:'{name}' {str(obj_type)}")
|
|
881
|
-
|
|
887
|
+
|
|
882
888
|
return group_prim
|
|
883
889
|
|
|
884
890
|
def uploadMaterial(self):
|
|
@@ -932,6 +938,12 @@ class OmniverseUpdateHandler(UpdateHandler):
|
|
|
932
938
|
matrix = group.matrix4x4
|
|
933
939
|
# Is this a "case" group (it will contain part of the camera view in the matrix)
|
|
934
940
|
if obj_type == "ENS_CASE":
|
|
941
|
+
if self.session.scene_bounds is not None:
|
|
942
|
+
midx = (self.session.scene_bounds[3] + self.session.scene_bounds[0]) * 0.5
|
|
943
|
+
midy = (self.session.scene_bounds[4] + self.session.scene_bounds[1]) * 0.5
|
|
944
|
+
midz = (self.session.scene_bounds[5] + self.session.scene_bounds[2]) * 0.5
|
|
945
|
+
self._omni._centroid = [midx, midy, midz]
|
|
946
|
+
|
|
935
947
|
if not self.session.vrmode and not self._case_xform_applied_to_camera:
|
|
936
948
|
# if in camera mode, we need to update the camera matrix so we can
|
|
937
949
|
# use the identity matrix on this group. The camera should have been
|
|
@@ -107,7 +107,6 @@ class _Simba:
|
|
|
107
107
|
# if the vport is in orthographic mode. If not, it is defined as the
|
|
108
108
|
# inverge of the tangent of half of the field of view
|
|
109
109
|
parallel_scale = parallel_scale
|
|
110
|
-
clipping_range = vport.ZCLIPLIMITS
|
|
111
110
|
return {
|
|
112
111
|
"orthographic": not vport.PERSPECTIVE,
|
|
113
112
|
"view_up": view_up,
|
|
@@ -120,8 +119,6 @@ class _Simba:
|
|
|
120
119
|
"reset_parallel_scale": self._original_parallel_scale,
|
|
121
120
|
"reset_view_up": self._original_view_up,
|
|
122
121
|
"reset_view_angle": self._original_view_angle,
|
|
123
|
-
"near_plane": clipping_range[0],
|
|
124
|
-
"far_plane": clipping_range[1],
|
|
125
122
|
}
|
|
126
123
|
|
|
127
124
|
@staticmethod
|
|
@@ -161,44 +158,6 @@ class _Simba:
|
|
|
161
158
|
z = 0.25 * s
|
|
162
159
|
return np.array([x, y, z, w])
|
|
163
160
|
|
|
164
|
-
def compute_model_rotation_quaternion(self, camera_position, focal_point, view_up):
|
|
165
|
-
"""Compute the quaternion from the input camera."""
|
|
166
|
-
forward = self.normalize(np.array(focal_point) - np.array(camera_position))
|
|
167
|
-
right = self.normalize(np.cross(forward, view_up))
|
|
168
|
-
true_up = np.cross(right, forward)
|
|
169
|
-
camera_rotation = np.vstack([right, true_up, -forward]).T
|
|
170
|
-
model_rotation = camera_rotation.T
|
|
171
|
-
quat = self.rotation_matrix_to_quaternion(model_rotation)
|
|
172
|
-
return quat
|
|
173
|
-
|
|
174
|
-
@staticmethod
|
|
175
|
-
def quaternion_multiply(q1, q2):
|
|
176
|
-
x1, y1, z1, w1 = q1
|
|
177
|
-
x2, y2, z2, w2 = q2
|
|
178
|
-
w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
|
|
179
|
-
x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
|
|
180
|
-
y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2
|
|
181
|
-
z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2
|
|
182
|
-
return np.array([x, y, z, w])
|
|
183
|
-
|
|
184
|
-
def quaternion_to_euler(self, q):
|
|
185
|
-
q = self.normalize(q)
|
|
186
|
-
x, y, z, w = q
|
|
187
|
-
sinr_cosp = 2 * (w * x + y * z)
|
|
188
|
-
cosr_cosp = 1 - 2 * (x * x + y * y)
|
|
189
|
-
roll = np.arctan2(sinr_cosp, cosr_cosp)
|
|
190
|
-
|
|
191
|
-
sinp = 2 * (w * y - z * x)
|
|
192
|
-
if abs(sinp) >= 1:
|
|
193
|
-
pitch = np.pi / 2 * np.sign(sinp)
|
|
194
|
-
else:
|
|
195
|
-
pitch = np.arcsin(sinp)
|
|
196
|
-
siny_cosp = 2 * (w * z + x * y)
|
|
197
|
-
cosy_cosp = 1 - 2 * (y * y + z * z)
|
|
198
|
-
yaw = np.arctan2(siny_cosp, cosy_cosp)
|
|
199
|
-
|
|
200
|
-
return np.degrees([roll, pitch, yaw])
|
|
201
|
-
|
|
202
161
|
def compute_camera_from_ensight_opengl(self):
|
|
203
162
|
"""Simulate a rotating camera using the current quaternion."""
|
|
204
163
|
if isinstance(self.ensight, ModuleType):
|
|
@@ -211,45 +170,6 @@ class _Simba:
|
|
|
211
170
|
parallel_scale = 1 / data[9]
|
|
212
171
|
return camera_position, focal_point, self.views._normalize_vector(view_up), parallel_scale
|
|
213
172
|
|
|
214
|
-
def get_camera_axes(self):
|
|
215
|
-
"""
|
|
216
|
-
Returns the camera's local axes: right, up, and forward vectors.
|
|
217
|
-
These are useful for applying transformations in view space.
|
|
218
|
-
|
|
219
|
-
Parameters:
|
|
220
|
-
camera (dict): A dictionary with keys 'position', 'focal_point', and 'view_up'.
|
|
221
|
-
|
|
222
|
-
Returns:
|
|
223
|
-
right (np.ndarray): Right vector (X axis in view space).
|
|
224
|
-
up (np.ndarray): Up vector (Y axis in view space).
|
|
225
|
-
forw ard (np.ndarray): Forward vector (Z axis in view space, pointing from position to focal point).
|
|
226
|
-
"""
|
|
227
|
-
camera = self.get_camera()
|
|
228
|
-
position = np.array(camera["position"])
|
|
229
|
-
focal_point = np.array(camera["focal_point"])
|
|
230
|
-
view_up = np.array(camera["view_up"])
|
|
231
|
-
|
|
232
|
-
# Forward vector: from camera position to focal point
|
|
233
|
-
forward = focal_point - position
|
|
234
|
-
forward /= np.linalg.norm(forward)
|
|
235
|
-
|
|
236
|
-
# Right vector: cross product of forward and view_up
|
|
237
|
-
right = np.cross(forward, view_up)
|
|
238
|
-
right /= np.linalg.norm(right)
|
|
239
|
-
|
|
240
|
-
# Recompute up vector to ensure orthogonality
|
|
241
|
-
up = np.cross(right, forward)
|
|
242
|
-
up /= np.linalg.norm(up)
|
|
243
|
-
|
|
244
|
-
return right, up, forward
|
|
245
|
-
|
|
246
|
-
def _arbitrary_orthogonal(self, v):
|
|
247
|
-
if abs(v[0]) < abs(v[1]) and abs(v[0]) < abs(v[2]):
|
|
248
|
-
return self.normalize(np.array(self.views._cross_product(v.tolist(), [1, 0, 0])))
|
|
249
|
-
elif abs(v[1]) < abs(v[2]):
|
|
250
|
-
return self.normalize(np.array(self.views._cross_product(v.tolist(), [0, 1, 0])))
|
|
251
|
-
return self.normalize(np.array(self.views._cross_product(v.tolist(), [0, 0, 1])))
|
|
252
|
-
|
|
253
173
|
def set_camera(
|
|
254
174
|
self,
|
|
255
175
|
orthographic,
|
|
@@ -257,75 +177,38 @@ class _Simba:
|
|
|
257
177
|
position=None,
|
|
258
178
|
focal_point=None,
|
|
259
179
|
view_angle=None,
|
|
260
|
-
pan=None,
|
|
261
|
-
mousex=None,
|
|
262
|
-
mousey=None,
|
|
263
|
-
invert_y=False,
|
|
264
180
|
):
|
|
265
181
|
"""Set the EnSight camera settings from the VTK input."""
|
|
266
182
|
self.ensight.view_transf.function("global")
|
|
267
183
|
perspective = "OFF" if orthographic else "ON"
|
|
268
|
-
|
|
269
|
-
self.ensight.view.perspective(perspective)
|
|
184
|
+
self.ensight.view.perspective(perspective)
|
|
270
185
|
vport = self.ensight.objs.core.VPORTS[0]
|
|
271
|
-
|
|
272
|
-
vport.PERSPECTIVEANGLE = view_angle / 2
|
|
186
|
+
vport.PERSPECTIVEANGLE = view_angle / 2
|
|
273
187
|
if view_up and position and focal_point:
|
|
274
|
-
# Compute relative rotation
|
|
275
|
-
q_current = self.normalize(np.array(vport.ROTATION.copy()))
|
|
276
|
-
q_target = self.normalize(
|
|
277
|
-
self.compute_model_rotation_quaternion(position, focal_point, view_up)
|
|
278
|
-
)
|
|
279
|
-
q_relative = self.quaternion_multiply(
|
|
280
|
-
q_target, np.array([-q_current[0], -q_current[1], -q_current[2], q_current[3]])
|
|
281
|
-
)
|
|
282
|
-
angles = self.quaternion_to_euler(q_relative)
|
|
283
|
-
self.ensight.view_transf.rotate(*angles)
|
|
284
|
-
# Decompose eventual translation from rotation
|
|
285
188
|
current_camera = self.get_camera()
|
|
286
189
|
center = vport.TRANSFORMCENTER.copy()
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
190
|
+
if isinstance(self.ensight, ModuleType):
|
|
191
|
+
data = self.ensight.objs.core.VPORTS[0].simba_set_camera_helper(
|
|
192
|
+
position,
|
|
193
|
+
focal_point,
|
|
194
|
+
view_up,
|
|
290
195
|
current_camera["position"],
|
|
291
196
|
current_camera["focal_point"],
|
|
292
197
|
current_camera["view_up"],
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
up1n = np.cross(right1, dir1)
|
|
308
|
-
# Now that orthonormal basis have been computed for the
|
|
309
|
-
# old and new camera, one can compute the rotation matrix
|
|
310
|
-
# that takes the old camera to the new one
|
|
311
|
-
A = np.stack([right0, up0n, dir0], axis=1)
|
|
312
|
-
B = np.stack([right1, up1n, dir1], axis=1)
|
|
313
|
-
R = B @ A.T
|
|
314
|
-
# Compute the rotated only vector from the old camera
|
|
315
|
-
# to the new camera direction
|
|
316
|
-
rotatedDistance = R @ (pos0 - center) + center
|
|
317
|
-
# Compute the view matrix for the rotated camera axes
|
|
318
|
-
rotated_focal = focal0 + (rotatedDistance - pos0)
|
|
319
|
-
rotated_dir = self.normalize(rotated_focal - rotatedDistance)
|
|
320
|
-
rotated_right = np.cross(rotated_dir, up0)
|
|
321
|
-
if np.linalg.norm(rotated_right) <= 1e-6:
|
|
322
|
-
rotated_right = self._arbitrary_orthogonal(rotated_dir)
|
|
323
|
-
rotated_up = np.cross(rotated_right, rotated_dir)
|
|
324
|
-
# Compute the world coordinates translation and move it to
|
|
325
|
-
# view space
|
|
326
|
-
offset = pos1 - rotatedDistance
|
|
327
|
-
translation = -np.stack([rotated_right, rotated_up, rotated_dir]) @ offset
|
|
328
|
-
self.ensight.view_transf.translate(translation[0], translation[1], 0)
|
|
198
|
+
center,
|
|
199
|
+
vport.ROTATION.copy(),
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
current_position = current_camera["position"]
|
|
203
|
+
current_fp = current_camera["focal_point"]
|
|
204
|
+
current_up = current_camera["view_up"]
|
|
205
|
+
cmd = "ensight.objs.core.VPORTS[0].simba_set_camera_helper("
|
|
206
|
+
cmd += f"{position}, {focal_point}, {view_up}, {current_position}, "
|
|
207
|
+
cmd += f"{current_fp}, {current_up}, {center}, "
|
|
208
|
+
cmd += f"{vport.ROTATION.copy()})"
|
|
209
|
+
data = self.ensight._session.cmd(cmd)
|
|
210
|
+
self.ensight.view_transf.rotate(data[3], data[4], data[5])
|
|
211
|
+
self.ensight.view_transf.translate(data[0], data[1], 0)
|
|
329
212
|
|
|
330
213
|
self.render()
|
|
331
214
|
return self.get_camera()
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
ansys/pyensight/core/__init__.py,sha256=BCfpDonS2OZRM2O6wjcyOYhLSgdy9hMQRl6G-_9Bvkg,845
|
|
2
2
|
ansys/pyensight/core/common.py,sha256=GhDxSoSscT9ObyTyEcuP0zeKKVJOpWVVYG0SwEby7CA,7575
|
|
3
3
|
ansys/pyensight/core/deep_pixel_view.html,sha256=6u4mGOuzJiPze8N8pIKJsEGPv5y6-zb38m9IfrarATE,3510
|
|
4
|
-
ansys/pyensight/core/dockerlauncher.py,sha256=
|
|
4
|
+
ansys/pyensight/core/dockerlauncher.py,sha256=iemgGEotlZjpX_tCvnAdLKRDNLaDuGKeYWihiqUSDNY,30523
|
|
5
5
|
ansys/pyensight/core/dvs.py,sha256=zRhizBkIUCk09BaR-7BxkC6EkIEjG7rU5vznh45QOzA,32018
|
|
6
6
|
ansys/pyensight/core/enscontext.py,sha256=GSKkjZt1QEPyHEQ59EEBgKGMik9vjCdR9coR4uX7fEw,12141
|
|
7
7
|
ansys/pyensight/core/enshell_grpc.py,sha256=OPK84J44kwjbAYQM4acb9zd-abYYkMNculKaWZeVDIk,17123
|
|
8
8
|
ansys/pyensight/core/ensight_grpc.py,sha256=IitEgMzBJTyTgQff0sXPvGkVnC2E9qRKw-HXCF-mVvA,29713
|
|
9
9
|
ansys/pyensight/core/ensobj.py,sha256=uDtM2KHcAwd4hu5pcUYWbSD729ApHGIvuqZhEq8PxTI,18558
|
|
10
10
|
ansys/pyensight/core/launch_ensight.py,sha256=iZJM6GdpzGRDLzrv1V2QZ5veIOpNSB5xPpJUFY7rBuo,10254
|
|
11
|
-
ansys/pyensight/core/launcher.py,sha256=
|
|
11
|
+
ansys/pyensight/core/launcher.py,sha256=_AH0Lr_kTFM6c5DYxEXp1pfrbYmoHWHajxnHgq_0CBo,13229
|
|
12
12
|
ansys/pyensight/core/libuserd.py,sha256=P6j-mgT6kDYiuRRDKEepJvZusBYa5jo4AQIwK__9R6Q,76020
|
|
13
13
|
ansys/pyensight/core/listobj.py,sha256=Trw87IxIMXtmUd1DzywRmMzORU704AG4scX4fqYmO6M,9340
|
|
14
|
-
ansys/pyensight/core/locallauncher.py,sha256=
|
|
14
|
+
ansys/pyensight/core/locallauncher.py,sha256=uv6B1gojx7FmT5e4RZQe2knKzChr0Ooh-Wr06QRbsoA,19146
|
|
15
15
|
ansys/pyensight/core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
ansys/pyensight/core/renderable.py,sha256=KidVTVCZ4hKYq54pP9KoJ8OCxeWBXNUJYyKSwMZ2Sls,36362
|
|
17
17
|
ansys/pyensight/core/session.py,sha256=6iIzw_PPpJ0ry9jwLfNdm5e5x_ppzamYv7BS1rtNZDw,74455
|
|
@@ -20,18 +20,18 @@ ansys/pyensight/core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
20
20
|
ansys/pyensight/core/utils/adr.py,sha256=XslZhlwcrSGzOlnhzprOv3ju_ppxxsWBjCnQL5KiNms,3570
|
|
21
21
|
ansys/pyensight/core/utils/dsg_server.py,sha256=2jCPhOplPrlDaQNSKSk9qo7bEgfcrhx0rHS_cqW2zAY,47003
|
|
22
22
|
ansys/pyensight/core/utils/export.py,sha256=GC0NbVl0_CXvUUfkbJl49yjTsP_58bJZyjE95q6ATUo,22604
|
|
23
|
-
ansys/pyensight/core/utils/omniverse.py,sha256=
|
|
23
|
+
ansys/pyensight/core/utils/omniverse.py,sha256=YhBrlnMcRmmf64jBNm6bV5x-Ej2VIjZOExwzmNHo1Ng,25007
|
|
24
24
|
ansys/pyensight/core/utils/omniverse_cli.py,sha256=ujoBbBGMYsYUn83nrk2dFkOd7kn7-6cs7ljBmmSXodw,20578
|
|
25
|
-
ansys/pyensight/core/utils/omniverse_dsg_server.py,sha256=
|
|
25
|
+
ansys/pyensight/core/utils/omniverse_dsg_server.py,sha256=75fGWqwVMLoACox08mwwWDA4pSTTqyjACVKhkeTRQ3Y,45994
|
|
26
26
|
ansys/pyensight/core/utils/omniverse_glb_server.py,sha256=dx2cfR036d3DY6meooNfLZOQpOMaiaLKqBjztpew2_Q,32167
|
|
27
27
|
ansys/pyensight/core/utils/parts.py,sha256=222XFRCjLgH7hho-cK9JrGCg3-KlTf54KIgc7y50sTE,52173
|
|
28
28
|
ansys/pyensight/core/utils/query.py,sha256=OXKDbf1sOTX0sUvtKcp64LhVl-BcrEsE43w8uMxLOYI,19828
|
|
29
29
|
ansys/pyensight/core/utils/readers.py,sha256=_IluAWz8mmoe5SM3hAewHIqlhtKMfEqrUJoQOlJ4U4I,12138
|
|
30
30
|
ansys/pyensight/core/utils/support.py,sha256=QI3z9ex7zJxjFbkCPba9DWqWgPFIThORqr0nvRfVjuc,4089
|
|
31
31
|
ansys/pyensight/core/utils/variables.py,sha256=ZUiJdDIeRcowrnLXaJQqGwA0RbrfXhc1s4o4v9A4PiY,95133
|
|
32
|
-
ansys/pyensight/core/utils/views.py,sha256=
|
|
32
|
+
ansys/pyensight/core/utils/views.py,sha256=vyO5w5Z1PFlz26FpXjXYDZyGFv2rUTGHJS5ovJvorvc,24675
|
|
33
33
|
ansys/pyensight/core/utils/resources/Materials/000_sky.exr,sha256=xAR1gFd2uxPZDnvgfegdhEhRaqKtZldQDiR_-1rHKO0,8819933
|
|
34
|
-
ansys_pyensight_core-0.10.
|
|
35
|
-
ansys_pyensight_core-0.10.
|
|
36
|
-
ansys_pyensight_core-0.10.
|
|
37
|
-
ansys_pyensight_core-0.10.
|
|
34
|
+
ansys_pyensight_core-0.10.13.dist-info/licenses/LICENSE,sha256=K6LiJHOa9IbWFelXmXNRzFr3zG45SOGZIN7vdLdURGU,1097
|
|
35
|
+
ansys_pyensight_core-0.10.13.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
36
|
+
ansys_pyensight_core-0.10.13.dist-info/METADATA,sha256=3Aa_Lyq0xtTJ15BAlpI1Y8S_wPxZKSvsRHtHszlJQlU,12201
|
|
37
|
+
ansys_pyensight_core-0.10.13.dist-info/RECORD,,
|
|
File without changes
|
{ansys_pyensight_core-0.10.12.dist-info → ansys_pyensight_core-0.10.13.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|