molde 0.1.1__py3-none-any.whl → 0.1.3__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.
molde/__init__.py CHANGED
@@ -3,3 +3,4 @@ from pathlib import Path
3
3
  from .colors import Color
4
4
 
5
5
  MOLDE_DIR = Path(__file__).parent
6
+ UI_DIR = MOLDE_DIR / "ui_files/"
molde/__main__.py CHANGED
@@ -5,6 +5,9 @@ from PyQt5 import uic
5
5
  from PyQt5.QtCore import Qt
6
6
  from time import time
7
7
 
8
+ from vtkmodules.vtkFiltersSources import vtkCylinderSource
9
+ from vtkmodules.vtkRenderingCore import vtkPolyDataMapper, vtkActor
10
+
8
11
  from molde import MOLDE_DIR
9
12
  from molde import stylesheets
10
13
  from molde.render_widgets.common_render_widget import CommonRenderWidget
@@ -23,6 +26,14 @@ class Example(QMainWindow):
23
26
  self.render_widget.create_color_bar()
24
27
  self.render_widget.set_info_text("Hola\nque\ntal?")
25
28
 
29
+ cylinder = vtkCylinderSource()
30
+ cylinder.SetResolution(8)
31
+ cylinder_mapper = vtkPolyDataMapper()
32
+ cylinder_mapper.SetInputConnection(cylinder.GetOutputPort())
33
+ cylinder_actor = vtkActor()
34
+ cylinder_actor.SetMapper(cylinder_mapper)
35
+ self.render_widget.add_actors(cylinder_actor)
36
+
26
37
  self.botao1 = QPushButton()
27
38
  self.label = QLabel("Olha o sapooo")
28
39
  self.botao1.setText("Olha a faca")
molde/actors/__init__.py CHANGED
@@ -2,3 +2,4 @@ from .ghost_actor import GhostActor
2
2
  from .lines_actor import LinesActor
3
3
  from .round_points_actor import RoundPointsActor
4
4
  from .square_points_actor import SquarePointsActor
5
+ from .common_symbols_actor import CommonSymbolsActorFixedSize, CommonSymbolsActorVariableSize
@@ -0,0 +1,164 @@
1
+ from dataclasses import dataclass
2
+
3
+ from molde import Color
4
+ from molde.utils import transform_polydata
5
+ from vtkmodules.vtkCommonCore import (
6
+ vtkDoubleArray,
7
+ vtkIntArray,
8
+ vtkPoints,
9
+ vtkUnsignedCharArray,
10
+ )
11
+ from vtkmodules.vtkCommonDataModel import vtkPolyData
12
+ from vtkmodules.vtkRenderingCore import vtkActor, vtkDistanceToCamera, vtkGlyph3DMapper, vtkRenderer
13
+
14
+ Triple = tuple[float, float, float]
15
+
16
+
17
+ @dataclass
18
+ class Symbol:
19
+ shape_name: str
20
+ position: Triple
21
+ orientation: Triple
22
+ color: Color
23
+ scale: float
24
+
25
+
26
+ class CommonSymbolsActor(vtkActor):
27
+ def __init__(self, *args, **kwargs):
28
+ self._shapes: dict[str, vtkPolyData] = dict()
29
+ self._symbols: list[Symbol] = list()
30
+
31
+ def register_shape(
32
+ self,
33
+ name: str,
34
+ shape: vtkPolyData,
35
+ position: Triple = (0, 0, 0),
36
+ rotation: Triple = (0, 0, 0),
37
+ scale: Triple = (1, 1, 1),
38
+ ):
39
+ self._shapes[name] = transform_polydata(
40
+ shape,
41
+ position,
42
+ rotation,
43
+ scale,
44
+ )
45
+
46
+ def add_symbol(
47
+ self,
48
+ shape_name: str,
49
+ position: Triple,
50
+ orientation: Triple,
51
+ color: Triple,
52
+ scale: float = 1,
53
+ ):
54
+ symbol = Symbol(
55
+ shape_name,
56
+ position,
57
+ orientation,
58
+ color,
59
+ scale,
60
+ )
61
+ self._symbols.append(symbol)
62
+
63
+ def clear_shapes(self):
64
+ self._shapes.clear()
65
+
66
+ def clear_symbols(self):
67
+ self._symbols.clear()
68
+
69
+ def clear_all(self):
70
+ self.clear_shapes()
71
+ self.clear_symbols()
72
+
73
+ def common_build(self):
74
+ self.data = vtkPolyData()
75
+ points = vtkPoints()
76
+
77
+ self.mapper: vtkGlyph3DMapper = vtkGlyph3DMapper()
78
+ self.SetMapper(self.mapper)
79
+
80
+ sources = vtkIntArray()
81
+ sources.SetName("sources")
82
+
83
+ rotations = vtkDoubleArray()
84
+ rotations.SetNumberOfComponents(3)
85
+ rotations.SetName("rotations")
86
+
87
+ scales = vtkDoubleArray()
88
+ scales.SetName("scales")
89
+
90
+ colors = vtkUnsignedCharArray()
91
+ colors.SetNumberOfComponents(3)
92
+ colors.SetName("colors")
93
+
94
+ shape_name_to_index = dict()
95
+ for index, (name, shape) in enumerate(self._shapes.items()):
96
+ shape_name_to_index[name] = index
97
+ self.mapper.SetSourceData(index, shape)
98
+
99
+ for symbol in self._symbols:
100
+ points.InsertNextPoint(symbol.position)
101
+ rotations.InsertNextTuple(symbol.orientation)
102
+ colors.InsertNextTuple(symbol.color.to_rgb())
103
+ scales.InsertNextValue(symbol.scale)
104
+ sources.InsertNextValue(shape_name_to_index[symbol.shape_name])
105
+
106
+ self.data.SetPoints(points)
107
+ self.data.GetPointData().AddArray(sources)
108
+ self.data.GetPointData().AddArray(rotations)
109
+ self.data.GetPointData().AddArray(scales)
110
+ self.data.GetPointData().SetScalars(colors)
111
+
112
+ def set_zbuffer_offsets(self, factor: float, units: float):
113
+ """
114
+ This functions is usefull to make a object appear in front of the others.
115
+ If the object should never be hidden, the parameters should be set to
116
+ factor = 1 and offset = -66000.
117
+ """
118
+ self.mapper.SetResolveCoincidentTopologyToPolygonOffset()
119
+ self.mapper.SetRelativeCoincidentTopologyLineOffsetParameters(factor, units)
120
+ self.mapper.SetRelativeCoincidentTopologyPolygonOffsetParameters(factor, units)
121
+ self.mapper.SetRelativeCoincidentTopologyPointOffsetParameter(units)
122
+ self.mapper.Update()
123
+
124
+
125
+ class CommonSymbolsActorFixedSize(CommonSymbolsActor):
126
+ def build(self):
127
+ self.common_build()
128
+
129
+ self.mapper.SetInputData(self.data)
130
+ self.mapper.SetSourceIndexArray("sources")
131
+ self.mapper.SetOrientationArray("rotations")
132
+ self.mapper.SetScaleArray("scales")
133
+ self.mapper.SourceIndexingOn()
134
+ self.mapper.ScalarVisibilityOn()
135
+ self.mapper.SetScaleModeToScaleByMagnitude()
136
+ self.mapper.SetScalarModeToUsePointData()
137
+ self.mapper.SetOrientationModeToDirection()
138
+ self.mapper.Update()
139
+
140
+
141
+ class CommonSymbolsActorVariableSize(CommonSymbolsActor):
142
+ def __init__(self, renderer: vtkRenderer):
143
+ super().__init__()
144
+ self.renderer = renderer
145
+
146
+ def build(self):
147
+ self.common_build()
148
+
149
+ distance_to_camera = vtkDistanceToCamera()
150
+ distance_to_camera.SetInputData(self.data)
151
+ distance_to_camera.SetScreenSize(40)
152
+ distance_to_camera.SetRenderer(self.renderer)
153
+
154
+ self.mapper.SetInputConnection(distance_to_camera.GetOutputPort())
155
+ self.mapper.SetSourceIndexArray("sources")
156
+ self.mapper.SetOrientationArray("rotations")
157
+ self.mapper.SetScaleArray("DistanceToCamera")
158
+ self.mapper.SourceIndexingOn()
159
+ self.mapper.ScalarVisibilityOn()
160
+ self.mapper.SetScaleModeToScaleByMagnitude()
161
+ self.mapper.SetScalarModeToUsePointData()
162
+ self.mapper.SetOrientationModeToDirection()
163
+
164
+ self.mapper.Update()
@@ -22,6 +22,7 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
22
22
  self.is_rotating = False
23
23
  self.is_panning = False
24
24
 
25
+ self.mid_button_click_position = (0, 0)
25
26
  # cor = center of rotation
26
27
  self.cor_actor = self._make_default_cor_actor()
27
28
  self._create_observers()
@@ -41,9 +42,7 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
41
42
  self.AddObserver("MouseWheelForwardEvent", self._mouse_wheel_forward_event)
42
43
  self.AddObserver("MouseWheelBackwardEvent", self._mouse_wheel_backward_event)
43
44
  self.AddObserver("MiddleButtonPressEvent", self._click_mid_button_press_event)
44
- self.AddObserver(
45
- "MiddleButtonReleaseEvent", self._click_mid_button_release_event
46
- )
45
+ self.AddObserver("MiddleButtonReleaseEvent", self._click_mid_button_release_event)
47
46
 
48
47
  def _left_button_press_event(self, obj, event):
49
48
  # Implemented to stop the superclass movement
@@ -84,9 +83,7 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
84
83
  distance_factor = np.sqrt(dx**2 + dy**2 + dz**2)
85
84
 
86
85
  self.cor_actor.SetPosition(self.center_of_rotation)
87
- self.cor_actor.SetScale(
88
- (distance_factor / 3.5, distance_factor / 3.5, distance_factor / 3.5)
89
- )
86
+ self.cor_actor.SetScale((distance_factor / 3.5, distance_factor / 3.5, distance_factor / 3.5))
90
87
  renderer.AddActor(self.cor_actor)
91
88
 
92
89
  def _right_button_release_event(self, obj, event):
@@ -100,18 +97,36 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
100
97
  def _click_mid_button_press_event(self, obj, event):
101
98
  self.is_mid_clicked = True
102
99
  self.is_panning = True
103
- int_pos = self.GetInteractor().GetEventPosition()
104
- self.FindPokedRenderer(int_pos[0], int_pos[1])
100
+ cursor = self.GetInteractor().GetEventPosition()
101
+ self.mid_button_click_position = cursor
102
+ self.FindPokedRenderer(cursor[0], cursor[1])
105
103
 
106
104
  def _click_mid_button_release_event(self, obj, event):
107
105
  self.is_mid_clicked = False
108
106
  self.is_panning = False
109
107
 
110
108
  def _mouse_move_event(self, obj, event):
111
- if self.is_rotating:
109
+ zoom = self.is_mid_clicked and self.GetInteractor().GetControlKey()
110
+
111
+ if zoom and not self.is_zooming:
112
+ self.is_zooming = True
113
+
114
+ if not zoom:
115
+ self.is_zooming = False
116
+
117
+ if self.is_zooming:
118
+ # Implementation based on this link
119
+ # https://github.com/Kitware/VTK/blob/4c4cd48244eaf1a74e0b096aae773c5498f7a782/Interaction/Style/vtkInteractorStyleTrackballCamera.cxx#L352
120
+ y0 = self.GetInteractor().GetLastEventPosition()[1]
121
+ y1 = self.GetInteractor().GetEventPosition()[1]
122
+ dyf = 10 * (y1 - y0) / self.GetCurrentRenderer().GetCenter()[1]
123
+ factor = 1.1 ** dyf
124
+ self.dolly_on_point(factor, *self.mid_button_click_position)
125
+
126
+ elif self.is_rotating:
112
127
  self.rotate()
113
128
 
114
- if self.is_panning:
129
+ elif self.is_panning:
115
130
  self.Pan()
116
131
 
117
132
  self.OnMouseMove()
@@ -156,9 +171,7 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
156
171
  return
157
172
 
158
173
  rwi = self.GetInteractor()
159
- delta_mouse = np.array(rwi.GetEventPosition()) - np.array(
160
- rwi.GetLastEventPosition()
161
- )
174
+ delta_mouse = np.array(rwi.GetEventPosition()) - np.array(rwi.GetLastEventPosition())
162
175
  size = np.array(renderer.GetRenderWindow().GetSize())
163
176
  motion_factor = 10
164
177
  elevation_azimuth = -20 / size
@@ -214,29 +227,17 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
214
227
  camera.Modified()
215
228
 
216
229
  def dolly(self, factor):
217
- renderer = self.GetDefaultRenderer() or self.GetCurrentRenderer()
218
- camera = renderer.GetActiveCamera()
219
230
  cursor = self.GetInteractor().GetEventPosition()
231
+ self.dolly_on_point(factor, *cursor)
220
232
 
221
- if factor <= 0:
222
- return
223
-
224
- cam_up = np.array(camera.GetViewUp())
225
- cam_in = np.array(camera.GetDirectionOfProjection())
226
- cam_side = np.cross(cam_in, cam_up)
227
-
228
- displacements = self.get_dolly_displacements(
229
- factor,
230
- cursor,
231
- camera,
232
- renderer,
233
- )
233
+ def dolly_on_point(self, factor, x, y):
234
+ renderer = self.GetDefaultRenderer() or self.GetCurrentRenderer()
235
+ camera = renderer.GetActiveCamera()
234
236
 
235
- camera_position = np.array(camera.GetPosition())
236
- focal_point = np.array(camera.GetFocalPoint())
237
- rotated_displacements = cam_side * displacements[0] + cam_up * displacements[1]
238
- camera.SetPosition(camera_position + rotated_displacements)
239
- camera.SetFocalPoint(focal_point + rotated_displacements)
237
+ view_center = np.array(renderer.GetSize()) / 2
238
+ distance_to_center = (x, y) - view_center
239
+ dx, dy = distance_to_center * (1 - 1 / factor)
240
+ self.move_viewport(dx, dy)
240
241
 
241
242
  if camera.GetParallelProjection():
242
243
  camera.SetParallelScale(camera.GetParallelScale() / factor)
@@ -250,19 +251,34 @@ class ArcballCameraInteractorStyle(vtkInteractorStyleTrackballCamera):
250
251
 
251
252
  self.GetInteractor().Render()
252
253
 
253
- def get_dolly_displacements(self, factor, cursor, camera, renderer):
254
- cursor = np.array(cursor)
255
- view_center = np.array(renderer.GetSize()) / 2
256
- cursor_to_center = cursor - view_center
254
+ def move_viewport(self, dx, dy):
255
+ """
256
+ Moves the viewport in view coordinates by some amount of pixels.
257
+
258
+ Further explanations on this link:
259
+ https://github.com/open-pulse/OpenPulse/blob/5f7bd4719527383b2d3ea078e5f29f214f35128d/doc/code_explanation/move_viewport.pdf
260
+ """
261
+
262
+ renderer = self.GetDefaultRenderer() or self.GetCurrentRenderer()
263
+ camera = renderer.GetActiveCamera()
264
+ width, heigth = renderer.GetSize()
257
265
 
258
266
  if camera.GetParallelProjection():
259
267
  view_height = 2 * camera.GetParallelScale()
260
268
  else:
261
269
  correction = camera.GetDistance()
262
270
  view_height = 2 * correction * np.tan(0.5 * camera.GetViewAngle() / 57.296)
271
+ scale = view_height / heigth
272
+
273
+ focal_point = np.array(camera.GetFocalPoint())
274
+ camera_position = np.array(camera.GetPosition())
275
+ camera_up = np.array(camera.GetViewUp())
276
+ camera_in = np.array(camera.GetDirectionOfProjection())
277
+ camera_right = np.cross(camera_in, camera_up)
263
278
 
264
- scale = view_height / renderer.GetSize()[1]
265
- return cursor_to_center * scale * (1 - 1 / factor)
279
+ camera_displacement = scale * (camera_right * dx + camera_up * dy)
280
+ camera.SetPosition(camera_position + camera_displacement)
281
+ camera.SetFocalPoint(focal_point + camera_displacement)
266
282
 
267
283
  def _make_default_cor_actor(self):
268
284
  actor = RoundPointsActor([(0, 0, 0)])