scene_object3d.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import uuid
  2. from typing import TYPE_CHECKING, Any, List, Optional, Union, cast
  3. import numpy as np
  4. from .. import globals
  5. if TYPE_CHECKING:
  6. from .scene import Scene, SceneObject
  7. class Object3D:
  8. def __init__(self, type: str, *args: Any) -> None:
  9. self.type = type
  10. self.id = str(uuid.uuid4())
  11. self.name: Optional[str] = None
  12. self.scene: 'Scene' = cast('Scene', globals.get_slot().parent)
  13. self.scene.objects[self.id] = self
  14. self.parent: Union[Object3D, SceneObject] = self.scene.stack[-1]
  15. self.args: List = list(args)
  16. self.color: str = '#ffffff'
  17. self.opacity: float = 1.0
  18. self.side_: str = 'front'
  19. self.visible_: bool = True
  20. self.x: float = 0
  21. self.y: float = 0
  22. self.z: float = 0
  23. self.R: List[List[float]] = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
  24. self.sx: float = 1
  25. self.sy: float = 1
  26. self.sz: float = 1
  27. self._create()
  28. def with_name(self, name: str):
  29. self.name = name
  30. self._name()
  31. return self
  32. def send(self) -> None:
  33. self._create()
  34. self._name()
  35. self._material()
  36. self._move()
  37. self._rotate()
  38. self._scale()
  39. self._visible()
  40. def __enter__(self):
  41. self.scene.stack.append(self)
  42. return self
  43. def __exit__(self, *_):
  44. self.scene.stack.pop()
  45. def _create(self) -> None:
  46. self.scene.run_method('create', self.type, self.id, self.parent.id, *self.args)
  47. def _name(self) -> None:
  48. self.scene.run_method('name', self.id, self.name)
  49. def _material(self) -> None:
  50. self.scene.run_method('material', self.id, self.color, self.opacity, self.side_)
  51. def _move(self) -> None:
  52. self.scene.run_method('move', self.id, self.x, self.y, self.z)
  53. def _rotate(self) -> None:
  54. self.scene.run_method('rotate', self.id, self.R)
  55. def _scale(self) -> None:
  56. self.scene.run_method('scale', self.id, self.sx, self.sy, self.sz)
  57. def _visible(self) -> None:
  58. self.scene.run_method('visible', self.id, self.visible_)
  59. def _delete(self) -> None:
  60. self.scene.run_method('delete', self.id)
  61. def material(self, color: str = '#ffffff', opacity: float = 1.0, side: str = 'front'):
  62. if self.color != color or self.opacity != opacity or self.side_ != side:
  63. self.color = color
  64. self.opacity = opacity
  65. self.side_ = side
  66. self._material()
  67. return self
  68. def move(self, x: float = 0.0, y: float = 0.0, z: float = 0.0):
  69. if self.x != x or self.y != y or self.z != z:
  70. self.x = x
  71. self.y = y
  72. self.z = z
  73. self._move()
  74. return self
  75. def rotate(self, omega: float, phi: float, kappa: float):
  76. Rx = np.array([[1, 0, 0], [0, np.cos(omega), -np.sin(omega)], [0, np.sin(omega), np.cos(omega)]])
  77. Ry = np.array([[np.cos(phi), 0, np.sin(phi)], [0, 1, 0], [-np.sin(phi), 0, np.cos(phi)]])
  78. Rz = np.array([[np.cos(kappa), -np.sin(kappa), 0], [np.sin(kappa), np.cos(kappa), 0], [0, 0, 1]])
  79. return self.rotate_R((Rz @ Ry @ Rx).tolist())
  80. def rotate_R(self, R: List[List[float]]):
  81. if self.R != R:
  82. self.R = R
  83. self._rotate()
  84. return self
  85. def scale(self, sx: float = 1.0, sy: Optional[float] = None, sz: Optional[float] = None):
  86. if sy is None:
  87. sy = sx
  88. if sz is None:
  89. sz = sx
  90. if self.sx != sx or self.sy != sy or self.sz != sz:
  91. self.sx = sx
  92. self.sy = sy
  93. self.sz = sz
  94. self._scale()
  95. return self
  96. def visible(self, value: bool = True):
  97. if self.visible_ != value:
  98. self.visible_ = value
  99. self._visible()
  100. return self
  101. def delete(self) -> None:
  102. children = [object for object in self.scene.objects.values() if object.parent == self]
  103. for child in children:
  104. child.delete()
  105. del self.scene.objects[self.id]
  106. self._delete()