def Cylinder( pos=(0, 0, 0), r=1, height=1, axis=(0, 0, 1), c="teal", alpha=1, res=24): """ Build a cylinder of specified height and radius `r`, centered at `pos`. If `pos` is a list of 2 Points, e.g. `pos=[v1,v2]`, build a cylinder with base centered at `v1` and top at `v2`. |Cylinder| """ if utils.isSequence(pos[0]): # assume user is passing pos=[base, top] base = np.array(pos[0]) top = np.array(pos[1]) pos = (base + top) / 2 height = np.linalg.norm(top - base) axis = top - base axis = utils.versor(axis) else: axis = utils.versor(axis) base = pos - axis * height / 2 top = pos + axis * height / 2 cyl = vtk.vtkCylinderSource() cyl.SetResolution(res) cyl.SetRadius(r) cyl.SetHeight(height) cyl.Update() theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) t = vtk.vtkTransform() t.PostMultiply() t.RotateX(90) # put it along Z t.RotateY(np.rad2deg(theta)) t.RotateZ(np.rad2deg(phi)) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(cyl.GetOutput()) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c, alpha) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) actor.base = base + pos actor.top = top + pos settings.collectable_actors.append(actor) return actor
def rotate(self, angle, axis=(1, 0, 0), axis_point=(0, 0, 0), rad=False): """Rotate around an arbitrary `axis` passing through `axis_point`.""" if rad: anglerad = angle else: anglerad = np.deg2rad(angle) axis = utils.versor(axis) a = np.cos(anglerad / 2) b, c, d = -axis * np.sin(anglerad / 2) aa, bb, cc, dd = a * a, b * b, c * c, d * d bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d R = np.array([ [aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)], [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)], [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc], ]) rv = np.dot(R, self.GetPosition() - np.array(axis_point)) + axis_point if rad: angle *= 180.0 / np.pi # this vtk method only rotates in the origin of the object: self.RotateWXYZ(angle, axis[0], axis[1], axis[2]) self.SetPosition(rv) if self.trail: self.updateTrail() if self.shadow: self.addShadow(self.shadowX, self.shadowY, self.shadowZ, self.shadow.GetProperty().GetColor(), self.shadow.GetProperty().GetOpacity()) return self
def slicePlane(self, origin=(0, 0, 0), normal=(1, 1, 1)): """Extract the slice along a given plane position and normal. |slicePlane| |slicePlane.py|_ """ reslice = vtk.vtkImageReslice() reslice.SetInputData(self._imagedata) reslice.SetOutputDimensionality(2) newaxis = utils.versor(normal) pos = np.array(origin) initaxis = (0, 0, 1) crossvec = np.cross(initaxis, newaxis) angle = np.arccos(np.dot(initaxis, newaxis)) T = vtk.vtkTransform() T.PostMultiply() T.RotateWXYZ(np.rad2deg(angle), crossvec) T.Translate(pos) M = T.GetMatrix() reslice.SetResliceAxes(M) reslice.SetInterpolationModeToLinear() reslice.Update() vslice = vtk.vtkImageDataGeometryFilter() vslice.SetInputData(reslice.GetOutput()) vslice.Update() msh = Mesh(vslice.GetOutput()) msh.SetOrientation(T.GetOrientation()) msh.SetPosition(pos) return msh
def orientation(self, newaxis=None, rotation=0, rad=False): """ Set/Get object orientation. :param rotation: If != 0 rotate object around newaxis. :param rad: set to True if angle is in radians. |gyroscope2| |gyroscope2.py|_ """ if rad: rotation *= 180.0 / np.pi if self.top is None or self.base is None: initaxis = (0, 0, 1) else: initaxis = utils.versor(self.top - self.base) if newaxis is None: return initaxis newaxis = utils.versor(newaxis) pos = np.array(self.GetPosition()) crossvec = np.cross(initaxis, newaxis) angle = np.arccos(np.dot(initaxis, newaxis)) T = vtk.vtkTransform() T.PostMultiply() T.Translate(-pos) if rotation: T.RotateWXYZ(rotation, initaxis) T.RotateWXYZ(np.rad2deg(angle), crossvec) T.Translate(pos) self.SetUserTransform(T) if self.trail: self.updateTrail() if self.shadow: self.addShadow(self.shadowX, self.shadowY, self.shadowZ, self.shadow.GetProperty().GetColor(), self.shadow.GetProperty().GetOpacity()) return self
def Cone(pos=(0, 0, 0), r=1, height=3, axis=(0, 0, 1), c="dg", alpha=1, res=48): """ Build a cone of specified radius `r` and `height`, centered at `pos`. |Cone| """ con = vtk.vtkConeSource() con.SetResolution(res) con.SetRadius(r) con.SetHeight(height) con.SetDirection(axis) con.Update() actor = Actor(con.GetOutput(), c, alpha) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) v = utils.versor(axis) * height / 2 actor.base = pos - v actor.top = pos + v settings.collectable_actors.append(actor) return actor