浏览代码

remove NumPy dependency from ui.scene

Falko Schindler 1 年之前
父节点
当前提交
96da04ccf3
共有 3 个文件被更改,包括 27 次插入8 次删除
  1. 14 7
      nicegui/elements/scene_object3d.py
  2. 2 1
      nicegui/helpers.py
  3. 11 0
      tests/test_scene.py

+ 14 - 7
nicegui/elements/scene_object3d.py

@@ -1,8 +1,7 @@
+import math
 import uuid
 import uuid
 from typing import TYPE_CHECKING, Any, List, Optional, Union, cast
 from typing import TYPE_CHECKING, Any, List, Optional, Union, cast
 
 
-import numpy as np
-
 from .. import globals
 from .. import globals
 
 
 if TYPE_CHECKING:
 if TYPE_CHECKING:
@@ -93,11 +92,19 @@ class Object3D:
             self._move()
             self._move()
         return self
         return self
 
 
-    def rotate(self, omega: float, phi: float, kappa: float):
-        Rx = np.array([[1, 0, 0], [0, np.cos(omega), -np.sin(omega)], [0, np.sin(omega), np.cos(omega)]])
-        Ry = np.array([[np.cos(phi), 0, np.sin(phi)], [0, 1, 0], [-np.sin(phi), 0, np.cos(phi)]])
-        Rz = np.array([[np.cos(kappa), -np.sin(kappa), 0], [np.sin(kappa), np.cos(kappa), 0], [0, 0, 1]])
-        return self.rotate_R((Rz @ Ry @ Rx).tolist())
+    @staticmethod
+    def rotation_matrix_from_euler(r_x: float, r_y: float, r_z: float) -> List[List[float]]:
+        sx, cx = math.sin(r_x), math.cos(r_x)
+        sy, cy = math.sin(r_y), math.cos(r_y)
+        sz, cz = math.sin(r_z), math.cos(r_z)
+        return [
+            [cz * cy, -sz * cx + cz * sy * sx, sz * sx + cz * sy * cx],
+            [sz * cy, cz * cx + sz * sy * sx, -cz * sx + sz * sy * cx],
+            [-sy, cy * sx, cy * cx],
+        ]
+
+    def rotate(self, r_x: float, r_y: float, r_z: float) -> None:
+        return self.rotate_R(self.rotation_matrix_from_euler(r_x, r_y, r_z))
 
 
     def rotate_R(self, R: List[List[float]]):
     def rotate_R(self, R: List[List[float]]):
         if self.R != R:
         if self.R != R:

+ 2 - 1
nicegui/helpers.py

@@ -2,6 +2,7 @@ import asyncio
 import functools
 import functools
 import hashlib
 import hashlib
 import inspect
 import inspect
+import math
 import mimetypes
 import mimetypes
 import socket
 import socket
 import sys
 import sys
@@ -10,7 +11,7 @@ import time
 import webbrowser
 import webbrowser
 from contextlib import nullcontext
 from contextlib import nullcontext
 from pathlib import Path
 from pathlib import Path
-from typing import TYPE_CHECKING, Any, Awaitable, Callable, Generator, Optional, Tuple, Union
+from typing import TYPE_CHECKING, Any, Awaitable, Callable, Generator, List, Optional, Tuple, Union
 
 
 from fastapi import Request
 from fastapi import Request
 from fastapi.responses import StreamingResponse
 from fastapi.responses import StreamingResponse

+ 11 - 0
tests/test_scene.py

@@ -1,6 +1,8 @@
+import numpy as np
 from selenium.common.exceptions import JavascriptException
 from selenium.common.exceptions import JavascriptException
 
 
 from nicegui import ui
 from nicegui import ui
+from nicegui.elements.scene_object3d import Object3D
 
 
 from .screen import Screen
 from .screen import Screen
 
 
@@ -101,3 +103,12 @@ def test_create_dynamically(screen: Screen):
     screen.open('/')
     screen.open('/')
     screen.click('Create')
     screen.click('Create')
     assert screen.find_by_tag('canvas')
     assert screen.find_by_tag('canvas')
+
+
+def test_rotation_matrix_from_euler():
+    omega, phi, kappa = 0.1, 0.2, 0.3
+    Rx = np.array([[1, 0, 0], [0, np.cos(omega), -np.sin(omega)], [0, np.sin(omega), np.cos(omega)]])
+    Ry = np.array([[np.cos(phi), 0, np.sin(phi)], [0, 1, 0], [-np.sin(phi), 0, np.cos(phi)]])
+    Rz = np.array([[np.cos(kappa), -np.sin(kappa), 0], [np.sin(kappa), np.cos(kappa), 0], [0, 0, 1]])
+    R = Rz @ Ry @ Rx
+    assert np.allclose(Object3D.rotation_matrix_from_euler(omega, phi, kappa), R)