1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """VTK reference frames and vectors for the MBDyn post processing.
23 Until now, the main class used is L{ReferenceFrame} for representing
24 the orientation matrix of the nodes and reference frames. The L{Vector}
25 class could also been used for representing velocities as a future
26 development and it will certainly be a based to represent
27 angular velocities as well.
28 """
29 import vtk
30 import numpy as N
31
32
34 """Return the norm of a 3x1 array"""
35 res = N.sqrt(N.dot(array.transpose(), array))
36 return res[0][0]
37
39 """Fill the C{rmat} rotation matrix from an angle
40 and axis of rotation"""
41 qaxis = N.sin(angle/2) * axis
42 w = N.cos(angle/2)
43 x = qaxis[0]
44 y = qaxis[1]
45 z = qaxis[2]
46
47 xx2 = 2*x*x
48 yy2 = 2*y*y
49 zz2 = 2*z*z
50 xy2 = 2*x*y
51 wz2 = 2*w*z
52 zx2 = 2*z*x
53 wy2 = 2*w*y
54 yz2 = 2*y*z
55 wx2 = 2*w*x
56
57 rmat[0, 0] = 1. - yy2 - zz2
58 rmat[0, 1] = xy2 - wz2
59 rmat[0, 2] = zx2 + wy2
60 rmat[1, 0] = xy2 + wz2
61 rmat[1, 1] = 1. - xx2 - zz2
62 rmat[1, 2] = yz2 - wx2
63 rmat[2, 0] = zx2 - wy2
64 rmat[2, 1] = yz2 + wx2
65 rmat[2, 2] = 1. - xx2 - yy2
66 return rmat
67
68
70 """The common class for a VTK object in MBDyn. It should
71 be moved to the L{mbdyn.interface.common} module.
72 """
73
75 self.name = name
76 self.scale_factor = 1.
77
79 """Set a scale factor on the object"""
80 self.scale_factor = scale_factor
81
82
84 """Description of an arrow mapper.
85 """
86
88 VTKCommon.__init__(self, name)
89 self.radius = 1.
90 self.radius_ratio = 2.
91 self.length_ratio = 0.2
92
93 self.initial_orientation = N.array([ [0.],
94 [1.],
95 [0.] ])
96 self.initial_orientation_t = self.initial_orientation.transpose()
97 self.initial_orientation_r = self.initial_orientation.reshape(3)
98 self.source = {
99 "cone" : vtk.vtkConeSource(),
100 "cyl" : vtk.vtkCylinderSource()
101 }
102 self.transfo = {}
103 polydata = vtk.vtkAppendPolyData()
104 for key in ["cone", "cyl"]:
105 self.transfo[key] = vtk.vtkTransform()
106 vfilter = vtk.vtkTransformPolyDataFilter()
107 vfilter.SetInput(self.source[key].GetOutput())
108 vfilter.SetTransform(self.transfo[key])
109 polydata.AddInput(vfilter.GetOutput())
110
111
112
113
114
115
116 self.mapper = vtk.vtkPolyDataMapper()
117 self.mapper.SetInput(polydata.GetOutput())
118
119 self.set_scale_factor(1.)
120 self.set_norm(30.)
121 self.set_resolution(20)
122
124 """Update the arrow radius"""
125 self.scale_factor = scale_factor
126 self.set_radius(self.scale_factor)
127
129 """Set the radius ratio between the cone
130 and the cylinder"""
131 self.radius_ratio = radius_ratio
132 self.set_radius(self.radius)
133
135 """Set the arrow radius"""
136 self.radius = radius
137 self.source["cyl"].SetRadius(radius)
138 self.source["cone"].SetRadius(radius * self.radius_ratio)
139
141 """Set the cylinder and cone resolution"""
142 for key in ["cyl", "cone"]:
143 self.source[key].SetResolution(resolution)
144
146 """Set the norm of the arrow"""
147 height = norm
148 cone_height = height * self.length_ratio
149 cyl_height = height - cone_height
150 self.source["cyl"].SetHeight(cyl_height)
151 self.source["cone"].SetHeight(cone_height)
152
153 self.transfo["cyl"].Identity()
154
155
156 self.transfo["cyl"].Translate(0., cyl_height/2., 0.)
157
158 self.transfo["cone"].Identity()
159
160 self.transfo["cone"].RotateZ(90.)
161
162
163
164 self.transfo["cone"].Translate(cyl_height + cone_height/2., 0., 0.)
165
167 """The rotation matrix is got according to the
168 initial orientation of the C{polydata}.
169 """
170 rotation_matrix = N.eye(3)
171 angle = N.arccos(N.dot(self.initial_orientation_t,
172 current_orientation)[0][0])
173 if angle == N.pi:
174 rotation_matrix[1, 1] = -1
175 else:
176 axis = N.cross(self.initial_orientation_r,
177 current_orientation.reshape(3))
178 norm = get_norm(axis.reshape(3, 1))
179 if norm != 0.:
180 axis = axis/norm
181 fill_rotation_matrix(rotation_matrix, angle, axis)
182 return rotation_matrix
183
184
186 """Description of a vector as a VTK actor"""
187
189 self.actor = vtk.vtkActor()
190 self.transfo_mat = vtk.vtkMatrix4x4()
191 self.transfo_mat.SetElement(3, 3, 1.)
192 self.actor.SetUserMatrix(self.transfo_mat)
193
194 self.text = vtk.vtkVectorText()
195 self.text.SetText("Origin")
196 text_mapper = vtk.vtkPolyDataMapper()
197 text_mapper.SetInputConnection(self.text.GetOutputPort())
198 self.text_actor = vtk.vtkFollower()
199 self.text_actor.SetMapper(text_mapper)
200
201
202
203 self.arrow = None
204 self.position = N.zeros((3, 1))
205 self.rotation_matrix = N.zeros((3, 3))
206 self.value = N.zeros((3, 1))
207
208 self.set_arrow(Arrow())
209
210 self.set_value(N.array([ [0.],
211 [30.],
212 [0.] ]))
213
214
216 """Set the arrow mapper for the vector"""
217 self.arrow = arrow
218 self.actor.SetMapper(arrow.mapper)
219
221 """Set the position of the vector"""
222 self.define(pos_array, self.rotation_matrix)
223
225 """Set the rotation (or orientation) matrix
226 of the vector"""
227 self.define(self.position, rotation_matrix)
228
229 - def define(self, position_array, rotation_matrix):
230 """A vector is defined by an position and a rotation
231 matrix in the VTK world"""
232 self.position = position_array
233 self.rotation_matrix = rotation_matrix
234 for jdx in range(3):
235 for idx in range(3):
236 self.transfo_mat.SetElement(idx, jdx,
237 rotation_matrix[idx, jdx])
238 for idx in range(3):
239 self.transfo_mat.SetElement(idx, 3,
240 position_array[idx][0])
241
242
244 """Set the vector value"""
245 self.value = array.copy()
246 array_norm = get_norm(array)
247 normalized_array = array.copy() / array_norm
248 self.arrow.set_norm(array_norm)
249 self.set_rotation_matrix_from(normalized_array)
250
252 """Set the rotation matrix of a vector from a normalized array
253 that represent only its current rotation."""
254 rotmatrix = self.arrow.get_rotation_matrix(normalized_array)
255 self.set_rotation_matrix(rotmatrix)
256
258 """Set the color by using RGB values coming from
259 the U{GIMP<http://www.gimp.org/>}."""
260 self.actor.GetProperty().SetColor(rval/255.,
261 gval/255.,
262 bval/255.)
263
264
266 """The top class of every axe.
267 """
268
273
275 """Display the axe according to its orientation matrix"""
276 current_orientation = N.asarray(orientation_matrix * \
277 self.direction)
278 self.set_rotation_matrix_from(current_orientation)
279
280
281 -class XAxe(CommonAxe):
282 """The M{x} axe, set as red.
283 """
284
291
292
293 -class YAxe(CommonAxe):
294 """The M{y} axe, set as green.
295 """
296
303
304
305 -class ZAxe(CommonAxe):
306 """The M{z} axe, set as blue.
307 """
308
310 direction = N.matrix([ [0.],
311 [0.],
312 [1.] ])
313 CommonAxe.__init__(self, direction)
314 self.set_color(21., 115., 232.)
315
316
317
319 """A VTK reference frame able to represent
320 a MBDyn rotation (or orientation matrix).
321 """
322
331
333 """Display the reference frame from the MBDyn orientation
334 matrix"""
335 self.orientation_matrix = orientation_matrix
336 for axe in self.axes:
337 axe.display_from(orientation_matrix)
338
340 """Scale the reference frame"""
341 for axe in self.axes:
342 axe.arrow.set_scale_factor(scale_factor)
343
345 """Set the norm for each vector axe"""
346 for axe in self.axes:
347 axe.arrow.set_norm(norm)
348
350 """Add the reference frame into the VTK area (or renderer)"""
351 for axe in self.axes:
352 vtk_renderer.AddActor(axe.actor)
353
355 """Remove the reference frame from the VTK area (or renderer)"""
356 for axe in self.axes:
357 vtk_renderer.RemoveActor(axe.actor)
358
360 """Set the position of the reference frame"""
361 for axe in self.axes:
362 axe.set_position(array)
363
365 """Set the arrow mapper for every axe"""
366 for axe in self.axes:
367 axe.set_arrow(arrow)
368