def addCellScalars(self, scalars, name): """addCellScalars is OBSOLETE: use addCellArray.""" colors.printc( "WARNING - addCellScalars is OBSOLETE: use addCellArray.", c='y', box='-') return self.addCellArray(scalars, name)
def pca(points, pvalue=.95, c='c', alpha=0.5, pcaAxes=False, legend=None): ''' Show the oriented PCA ellipsoid that contains fraction pvalue of points. axes = True, show the 3 PCA semi axes Extra info is stored in actor.sphericity, actor.va, actor.vb, actor.vc (sphericity = 1 for a perfect sphere) ''' try: from scipy.stats import f except: vc.printc("Error in ellipsoid(): scipy not installed. Skip.",1) return None if isinstance(points, vtk.vtkActor): points=vu.coordinates(points) if len(points) == 0: return None P = np.array(points, ndmin=2, dtype=float) cov = np.cov(P, rowvar=0) # covariance matrix U, s, R = np.linalg.svd(cov) # singular value decomposition p, n = s.size, P.shape[0] fppf = f.ppf(pvalue, p, n-p)*(n-1)*p*(n+1)/n/(n-p) # f % point function ua,ub,uc = np.sqrt(s*fppf)*2 # semi-axes (largest first) center = np.mean(P, axis=0) # centroid of the hyperellipsoid sphericity = ( ((ua-ub)/(ua+ub))**2 + ((ua-uc)/(ua+uc))**2 + ((ub-uc)/(ub+uc))**2 )/3. *4. elliSource = vtk.vtkSphereSource() elliSource.SetThetaResolution(48) elliSource.SetPhiResolution(48) matri = vtk.vtkMatrix4x4() matri.DeepCopy((R[0][0] *ua, R[1][0] *ub, R[2][0] *uc, center[0], R[0][1] *ua, R[1][1] *ub, R[2][1] *uc, center[1], R[0][2] *ua, R[1][2] *ub, R[2][2] *uc, center[2], 0,0,0,1)) vtra = vtk.vtkTransform() vtra.SetMatrix(matri) ftra = vtk.vtkTransformFilter() ftra.SetTransform(vtra) ftra.SetInputConnection(elliSource.GetOutputPort()) ftra.Update() actor_elli = vu.makeActor(ftra.GetOutput(), c, alpha, legend=legend) actor_elli.GetProperty().BackfaceCullingOn() actor_elli.GetProperty().SetInterpolationToPhong() if pcaAxes: axs = [] for ax in ([1,0,0], [0,1,0], [0,0,1]): l = vtk.vtkLineSource() l.SetPoint1([0,0,0]) l.SetPoint2(ax) l.Update() t = vtk.vtkTransformFilter() t.SetTransform(vtra) vu.setInput(t, l.GetOutput()) t.Update() axs.append(vu.makeActor(t.GetOutput(), c, alpha)) finact = vu.makeAssembly([actor_elli]+axs, legend=legend) else : finact = actor_elli setattr(finact, 'sphericity', sphericity) setattr(finact, 'va', ua) setattr(finact, 'vb', ub) setattr(finact, 'vc', uc) return finact
def _colorPoints(plist, cols, r, alpha, legend): n = len(plist) if n > len(cols): colors.printc("Mismatch in colorPoints()", n, len(cols), c=1) exit() if n != len(cols): colors.printc("Warning: mismatch in colorPoints()", n, len(cols)) src = vtk.vtkPointSource() src.SetNumberOfPoints(n) src.Update() vertexFilter = vtk.vtkVertexGlyphFilter() vertexFilter.SetInputData(src.GetOutput()) vertexFilter.Update() pd = vertexFilter.GetOutput() ucols = vtk.vtkUnsignedCharArray() ucols.SetNumberOfComponents(3) ucols.SetName("RGB") for i, p in enumerate(plist): c = np.array(colors.getColor(cols[i])) * 255 ucols.InsertNextTuple3(c[0], c[1], c[2]) pd.GetPoints().SetData(numpy_to_vtk(plist, deep=True)) pd.GetPointData().SetScalars(ucols) mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(pd) mapper.ScalarVisibilityOn() actor = Actor() #vtk.vtkActor() actor.SetMapper(mapper) actor.GetProperty().SetInterpolationToFlat() actor.GetProperty().SetOpacity(alpha) actor.GetProperty().SetPointSize(r) return actor
def booleanOperation(actor1, actor2, operation='plus', c=None, alpha=1, wire=False, bc=None, edges=False, legend=None, texture=None): '''Volumetric union, intersection and subtraction of surfaces''' try: bf = vtk.vtkBooleanOperationPolyDataFilter() except AttributeError: vc.printc('Boolean operation only possible for vtk version >= 8', 'r') return None poly1 = vu.polydata(actor1, True) poly2 = vu.polydata(actor2, True) if operation.lower() == 'plus': bf.SetOperationToUnion() elif operation.lower() == 'intersect': bf.SetOperationToIntersection() elif operation.lower() == 'minus': bf.SetOperationToDifference() bf.ReorientDifferenceCellsOn() if vu.vtkMV: bf.SetInputData(0, poly1) bf.SetInputData(1, poly2) else: bf.SetInputConnection(0, poly1.GetProducerPort()) bf.SetInputConnection(1, poly2.GetProducerPort()) bf.Update() actor = vu.makeActor(bf.GetOutput(), c, alpha, wire, bc, edges, legend, texture) return actor
def move(self, u=None, deltas=None): """Move mesh according to solution `u` or from calculated vertex displacements `deltas`. """ if u is None: u = self.u if deltas is None: if self.u_values is not None: deltas = self.u_values else: deltas = _compute_uvalues(u, self.mesh) self.u_values = deltas if hasattr(self.mesh, "coordinates"): coords = self.mesh.coordinates() else: coords = self.mesh.geometry.points if coords.shape != deltas.shape: printc("ERROR: Try to move mesh with wrong solution type shape:", coords.shape, 'vs', deltas.shape, c=1) printc("Mesh is not moved. Try mode='color' in plot().", c=1) return movedpts = coords + deltas if movedpts.shape[1] == 2: #2d movedpts = np.c_[movedpts, np.zeros(movedpts.shape[0])] self.polydata(False).GetPoints().SetData( numpy_to_vtk(np.ascontiguousarray(movedpts))) self._polydata.GetPoints().Modified()
def addPointVectors(self, vectors, name): """addPointVectors is OBSOLETE: use addPointArray.""" colors.printc( "WARNING - addPointVectors is OBSOLETE: use addPointArray.", c='y', box='-') return self.addPointArray(vectors, name)
def procrustes(sources, rigid=False, legend=None): ''' Return an Assembly of aligned source actors with the vtkProcrustesAlignmentFilter class. Assembly is normalized in space. Takes N set of points and aligns them in a least-squares sense to their mutual mean. The algorithm is iterated until convergence, as the mean must be recomputed after each alignment. ''' group = vtk.vtkMultiBlockDataGroupFilter() for source in sources: if sources[0].N() != source.N(): vc.printc('Procrustes error in align():' , c=1) vc.printc(' sources have different nr of points', c=1) exit(0) group.AddInputData(source.polydata()) procrustes = vtk.vtkProcrustesAlignmentFilter() procrustes.StartFromCentroidOn() procrustes.SetInputConnection(group.GetOutputPort()) if rigid: procrustes.GetLandmarkTransform().SetModeToRigidBody() procrustes.Update() acts = [] for i in range(len(sources)): poly = procrustes.GetOutput().GetBlock(i) actor = Actor(poly) actor.SetProperty(sources[i].GetProperty()) acts.append(actor) assem = Assembly(acts, legend=legend) assem.info['transform'] = procrustes.GetLandmarkTransform() return assem
def tips(): from vtkplotter import colors msg = "--------------------------------------------------------------\n" msg += "|Press: i to print info about selected object |\n" msg += "| m to minimise opacity of selected mesh |\n" msg += "| ., to reduce/increase opacity |\n" msg += "| / to maximize opacity |\n" msg += "| w/s to toggle wireframe/solid style |\n" msg += "| p/P to change point size of vertices |\n" msg += "| l/L to change edge line width |\n" msg += "| x to toggle mesh visibility |\n" msg += "| X to pop up a cutter widget tool |\n" msg += "| 1-3 to change mesh color |\n" msg += "| 4 to change background color |\n" msg += "| 0-9 to change axes style (use keypad) |\n" msg += "| k/K to show point/cell scalars as color |\n" msg += "| n to show surface mesh normals |\n" msg += "| a to toggle interaction to Actor Mode |\n" msg += "| j to toggle interaction to Joystick Mode |\n" msg += "| C to print current camera info |\n" msg += "| S to save a screenshot |\n" msg += "| q to return control to python script |\n" msg += "| Esc to close the rendering window |\n" msg += "| F1 to abort execution and exit python |\n" msg += "|------ |\n" msg += "|Mouse: Left-click to rotate scene / pick actors |\n" msg += "| Middle-click to pan scene |\n" msg += "| Right-click to zoom scene in or out |\n" msg += "| Cntrl-click to rotate scene perpendicularly |\n" msg += "|------ |\n" msg += "|Check out documentation at: https://vtkplotter.embl.es |\n" msg += "--------------------------------------------------------------\n" colors.printc(msg, dim=1)
def addButton( fnc, states=("On", "Off"), c=("w", "w"), bc=("dg", "dr"), pos=[20, 40], size=24, font="arial", bold=False, italic=False, alpha=1, angle=0, ): vp = settings.plotter_instance if not vp.renderer: colors.printc( "~timesError: Use addButton() after rendering the scene.", c=1) return bu = vtkio.Button(fnc, states, c, bc, pos, size, font, bold, italic, alpha, angle) vp.renderer.AddActor2D(bu.actor) vp.window.Render() vp.buttons.append(bu) return bu
def loadImageData(filename, spacing=()): """Read and return a ``vtkImageData`` object from file. Use ``load`` instead. E.g. `img = load('myfile.tif').imagedata()` """ if ".tif" in filename.lower(): reader = vtk.vtkTIFFReader() elif ".slc" in filename.lower(): reader = vtk.vtkSLCReader() if not reader.CanReadFile(filename): colors.printc("~prohibited Sorry bad slc file " + filename, c=1) return None elif ".vti" in filename.lower(): reader = vtk.vtkXMLImageDataReader() elif ".mhd" in filename.lower(): reader = vtk.vtkMetaImageReader() elif ".dem" in filename.lower(): reader = vtk.vtkDEMReader() elif ".nii" in filename.lower(): reader = vtk.vtkNIFTIImageReader() elif ".nrrd" in filename.lower(): reader = vtk.vtkNrrdReader() if not reader.CanReadFile(filename): colors.printc("~prohibited Sorry bad nrrd file " + filename, c=1) return None reader.SetFileName(filename) reader.Update() image = reader.GetOutput() if len(spacing) == 3: image.SetSpacing(spacing[0], spacing[1], spacing[2]) return image
def loadFile(filename, c, alpha, wire, bc, edges, legend, texture, smoothing, threshold, connectivity, scaling): '''Load a file of various formats.''' fl = filename.lower() if legend is True: legend = os.path.basename(filename) if fl.endswith('.xml') or fl.endswith( '.xml.gz'): # Fenics tetrahedral file actor = loadDolfin(filename, c, alpha, wire, bc, edges, legend) elif fl.endswith('.neutral') or fl.endswith( '.neu'): # neutral tetrahedral file actor = loadNeutral(filename, c, alpha, wire, bc, edges, legend) elif fl.endswith('.gmsh'): # gmesh file actor = loadGmesh(filename, c, alpha, wire, bc, edges, legend) elif fl.endswith('.pcd'): # PCL point-cloud format actor = loadPCD(filename, c, alpha, legend) elif fl.endswith('.3ds'): # PCL point-cloud format actor = load3DS(filename, legend) elif fl.endswith('.tif') or fl.endswith('.slc'): # tiff stack or slc img = loadImageData(filename) actor = vu.makeIsosurface(img, c, alpha, wire, bc, edges, legend, texture, smoothing, threshold, connectivity, scaling) elif fl.endswith('.png') or fl.endswith('.jpg') or fl.endswith('.jpeg'): actor = load2Dimage(filename, alpha) else: poly = loadPolyData(filename) if not poly: vc.printc('Unable to load', filename, c=1) return None actor = vu.makeActor(poly, c, alpha, wire, bc, edges, legend, texture) if fl.endswith('.txt') or fl.endswith('.xyz'): actor.GetProperty().SetPointSize(4) setattr(actor, 'filename', filename) return actor
def print(self, txt='', counts=None): if counts: self._update(counts) else: self._update(self._counts + self.step) if self.bar != self._oldbar: self._oldbar = self.bar eraser = [' '] * self._lentxt + ['\b'] * self._lentxt eraser = ''.join(eraser) if self.ETA: vel = self._counts / (time.time() - self.clock0) remt = (self.stop - self._counts) / vel if remt > 60: mins = int(remt / 60) secs = remt - 60 * mins mins = str(mins) + 'm' secs = str(int(secs)) + 's ' else: mins = '' secs = str(int(remt)) + 's ' vel = str(round(vel, 1)) eta = 'ETA: ' + mins + secs + '(' + vel + ' it/s) ' else: eta = '' txt = eta + str(txt) s = self.bar + ' ' + eraser + txt + '\r' if self.color: vc.printc(s, c=self.color, end='') else: sys.stdout.write(s) sys.stdout.flush() if self.percent == 100: print('') self._lentxt = len(txt)
def _colorPoints(plist, cols, r, alpha): n = len(plist) if n > len(cols): colors.printc("~times Error: mismatch in colorPoints()", n, len(cols), c=1) raise RuntimeError() if n != len(cols): colors.printc("~lightning Warning: mismatch in colorPoints()", n, len(cols)) src = vtk.vtkPointSource() src.SetNumberOfPoints(n) src.Update() vgf = vtk.vtkVertexGlyphFilter() vgf.SetInputData(src.GetOutput()) vgf.Update() pd = vgf.GetOutput() ucols = vtk.vtkUnsignedCharArray() ucols.SetNumberOfComponents(3) ucols.SetName("pointsRGB") for i in range(len(plist)): c = np.array(colors.getColor(cols[i])) * 255 ucols.InsertNextTuple3(c[0], c[1], c[2]) pd.GetPoints().SetData(numpy_to_vtk(plist, deep=True)) pd.GetPointData().SetScalars(ucols) actor = Actor(pd, c, alpha) actor.mapper.ScalarVisibilityOn() actor.GetProperty().SetInterpolationToFlat() actor.GetProperty().SetPointSize(r) settings.collectable_actors.append(actor) return actor
def addCellScalars(self, scalars, name): """ Add cell scalars and assign it a name. """ data = self.inputdata() if isinstance(scalars, str): scalars = vtk_to_numpy(data.GetPointData().GetArray(scalars)) if len(scalars) != data.GetNumberOfCells(): colors.printc( "addCellScalars() Error: Number of scalars != nr. of cells", len(scalars), data.GetNumberOfCells(), c=1) raise RuntimeError() arr = numpy_to_vtk(np.ascontiguousarray(scalars), deep=True) arr.SetName(name) data.GetCellData().AddArray(arr) data.GetCellData().SetActiveScalars(name) if hasattr(self._mapper, 'SetArrayName'): self._mapper.SetArrayName(name) if settings.autoResetScalarRange: self._mapper.SetScalarRange(np.min(scalars), np.max(scalars)) self._mapper.SetScalarModeToUseCellData() self._mapper.ScalarVisibilityOn() return self
def addPointScalars(self, scalars, name): """ Add point scalars and assign it a name. |mesh_coloring| |mesh_coloring.py|_ """ data = self.inputdata() if len(scalars) != data.GetNumberOfPoints(): colors.printc( '~times addPointScalars(): Number of scalars != nr. of points', len(scalars), data.GetNumberOfPoints(), c=1) raise RuntimeError() arr = numpy_to_vtk(np.ascontiguousarray(scalars), deep=True) arr.SetName(name) data.GetPointData().AddArray(arr) data.GetPointData().SetActiveScalars(name) if hasattr(self._mapper, 'SetArrayName'): self._mapper.SetArrayName(name) if settings.autoResetScalarRange: self._mapper.SetScalarRange(np.min(scalars), np.max(scalars)) self._mapper.SetScalarModeToUsePointData() self._mapper.ScalarVisibilityOn() return self
def lighting(self, style='', ambient=None, diffuse=None, specular=None, specularPower=None, specularColor=None, enabled=True): """ Set the ambient, diffuse, specular and specularPower lighting constants. :param str,int style: preset style, can be `[metallic, plastic, shiny, glossy, ambient]` :param float ambient: ambient fraction of emission [0-1] :param float diffuse: emission of diffused light in fraction [0-1] :param float specular: fraction of reflected light [0-1] :param float specularPower: precision of reflection [1-100] :param color specularColor: color that is being reflected by the surface :param bool enabled: enable/disable all surface light emission |wikiphong| |specular| |specular.py|_ """ pr = self.GetProperty() if style: if hasattr(pr, "GetColor"): # could be Volume c = pr.GetColor() else: c = (1, 1, 0.99) mpr = self._mapper if hasattr(mpr, 'GetScalarVisibility') and mpr.GetScalarVisibility(): c = (1, 1, 0.99) if style == 'metallic': pars = [0.1, 0.3, 1.0, 10, c] elif style == 'plastic': pars = [0.3, 0.4, 0.3, 5, c] elif style == 'shiny': pars = [0.2, 0.6, 0.8, 50, c] elif style == 'glossy': pars = [0.1, 0.7, 0.9, 90, (1, 1, 0.99)] elif style == 'ambient': pars = [1.0, 0.0, 0.0, 0, (1, 1, 1)] elif style == 'default': pars = [0.1, 1.0, 0.05, 5, c] else: colors.printc("Error in lighting(): Available styles are", c=1) colors.printc( " [default, metallic, plastic, shiny, glossy, ambient]", c=1) raise RuntimeError() pr.SetAmbient(pars[0]) pr.SetDiffuse(pars[1]) pr.SetSpecular(pars[2]) pr.SetSpecularPower(pars[3]) if hasattr(pr, "GetColor"): pr.SetSpecularColor(pars[4]) if ambient is not None: pr.SetAmbient(ambient) if diffuse is not None: pr.SetDiffuse(diffuse) if specular is not None: pr.SetSpecular(specular) if specularPower is not None: pr.SetSpecularPower(specularPower) if specularColor is not None: pr.SetSpecularColor(colors.getColor(specularColor)) if not enabled: pr.LightingOff() return self
def addIcon(iconActor, pos=3, size=0.08): vp = settings.plotter_instance if not vp.renderer: colors.printc( "~lightningWarning: Use addIcon() after first rendering the scene.", c=3) save_int = vp.interactive vp.show(interactive=0) vp.interactive = save_int widget = vtk.vtkOrientationMarkerWidget() widget.SetOrientationMarker(iconActor) widget.SetInteractor(vp.interactor) if utils.isSequence(pos): widget.SetViewport(pos[0] - size, pos[1] - size, pos[0] + size, pos[1] + size) else: if pos < 2: widget.SetViewport(0, 1 - 2 * size, size * 2, 1) elif pos == 2: widget.SetViewport(1 - 2 * size, 1 - 2 * size, 1, 1) elif pos == 3: widget.SetViewport(0, 0, size * 2, size * 2) elif pos == 4: widget.SetViewport(1 - 2 * size, 0, 1, size * 2) widget.EnabledOn() widget.InteractiveOff() vp.widgets.append(widget) if iconActor in vp.actors: vp.actors.remove(iconActor) return widget
def screenshot(filename="screenshot.png"): """ Save a screenshot of the current rendering window. """ if not settings.plotter_instance or not settings.plotter_instance.window: colors.printc( '~bomb screenshot(): Rendering window is not present, skip.', c=1) return w2if = vtk.vtkWindowToImageFilter() w2if.SetInput(settings.plotter_instance.window) s = settings.screeshotScale w2if.SetScale(s, s) if settings.screenshotTransparentBackground: w2if.SetInputBufferTypeToRGBA() w2if.ReadFrontBufferOff() # read from the back buffer w2if.Update() if filename.endswith('.png'): writer = vtk.vtkPNGWriter() writer.SetFileName(filename) writer.SetInputConnection(w2if.GetOutputPort()) writer.Write() elif filename.endswith('.jpg'): writer = vtk.vtkJPEGWriter() writer.SetFileName(filename) writer.SetInputConnection(w2if.GetOutputPort()) writer.Write() elif filename.endswith('.svg'): writer = vtk.vtkGL2PSExporter() #writer.SetFileFormatToPDF() #writer.SetFileFormatToTeX() writer.SetFileFormatToSVG() writer.CompressOff() writer.SetInput(settings.plotter_instance.window) writer.SetFilePrefix(filename.split('.')[0]) writer.Write()
def _loadFile(filename, c, alpha, wire, bc, legend, texture, smoothing, threshold, connectivity): fl = filename.lower() if legend is True: legend = os.path.basename(filename) if fl.endswith('.xml') or fl.endswith( '.xml.gz'): # Fenics tetrahedral file actor = loadDolfin(filename, c, alpha, wire, bc, legend) elif fl.endswith('.neutral') or fl.endswith( '.neu'): # neutral tetrahedral file actor = loadNeutral(filename, c, alpha, wire, bc, legend) elif fl.endswith('.gmsh'): # gmesh file actor = loadGmesh(filename, c, alpha, wire, bc, legend) elif fl.endswith('.pcd'): # PCL point-cloud format actor = loadPCD(filename, c, alpha, legend) elif fl.endswith('.3ds'): # PCL point-cloud format actor = load3DS(filename, legend) elif fl.endswith('.tif') or fl.endswith('.slc') or fl.endswith('.vti'): # tiff stack or slc or vti img = loadImageData(filename) actor = isosurface(img, c, alpha, wire, bc, legend, texture, smoothing, threshold, connectivity) elif fl.endswith('.png') or fl.endswith('.jpg') or fl.endswith('.jpeg'): actor = load2Dimage(filename, alpha) else: poly = loadPolyData(filename) if not poly: colors.printc('Unable to load', filename, c=1) return None actor = Actor(poly, c, alpha, wire, bc, legend, texture) if fl.endswith('.txt') or fl.endswith('.xyz'): actor.GetProperty().SetPointSize(4) actor.filename = filename return actor
def booleanOperation(actor1, actor2, operation='plus', c=None, alpha=1, wire=False, bc=None, legend=None, texture=None): '''Volumetric union, intersection and subtraction of surfaces. [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/boolean.py) ''' try: bf = vtk.vtkBooleanOperationPolyDataFilter() except AttributeError: vc.printc('Boolean operation only possible for vtk version >= 8', c='r') return None poly1 = actor1.polydata(True) poly2 = actor2.polydata(True) if operation.lower() == 'plus': bf.SetOperationToUnion() elif operation.lower() == 'intersect': bf.SetOperationToIntersection() elif operation.lower() == 'minus': bf.SetOperationToDifference() bf.ReorientDifferenceCellsOn() bf.SetInputData(0, poly1) bf.SetInputData(1, poly2) bf.Update() actor = Actor(bf.GetOutput(), c, alpha, wire, bc, legend, texture) return actor
def move(self, act=None, pt=(0, 0, 0), t=None, duration=None, style='linear'): """Smoothly change the position of a specific object to a new point in space.""" if self.bookingMode: acts, t, duration, rng = self._parse(act, t, duration) if len(acts) != 1: printc('Error in move(), can move only one object.', c=1) cpos = acts[0].pos() pt = np.array(pt) dv = (pt - cpos) / len(rng) for j, tt in enumerate(rng): i = j + 1 if 'quad' in style: x = i / len(rng) y = x * x #print(x,y) self.events.append( (tt, self.move, acts, cpos + dv * i * y)) else: self.events.append((tt, self.move, acts, cpos + dv * i)) else: self._performers[0].pos(self._inputvalues) return self
def linInterpolate(x, rangeX, rangeY): """ Interpolate linearly variable x in rangeX onto rangeY. If x is a vector the linear weight is the distance to two the rangeX vectors. E.g. if x runs in rangeX=[x0,x1] and I want it to run in rangeY=[y0,y1] then y = linInterpolate(x, rangeX, rangeY) will interpolate x onto rangeY. |linInterpolate| |linInterpolate.py|_ """ if isSequence(x): x = np.array(x) x0, x1 = np.array(rangeX) y0, y1 = np.array(rangeY) if len(np.unique([x.shape, x0.shape, x1.shape, y1.shape])) > 1: colors.printc( "Error in linInterpolate(): mismatch in input shapes.", c=1) raise RuntimeError() dx = x1 - x0 dxn = np.linalg.norm(dx) if not dxn: return y0 s = np.linalg.norm(x - x0) / dxn t = np.linalg.norm(x - x1) / dxn st = s + t out = y0 * (t / st) + y1 * (s / st) else: #faster x0 = rangeX[0] dx = rangeX[1] - x0 if not dx: return rangeY[0] s = (x - x0) / dx out = rangeY[0] * (1 - s) + rangeY[1] * s return out
def meshErode(self, act=None, corner=6, t=None, duration=None): """Erode a mesh by removing cells that are close to one of the 8 corners of the bounding box. """ if self.bookingMode: acts, t, duration, rng = self._parse(act, t, duration) if len(acts) != 1: printc('Error in meshErode(), can erode only one object.', c=1) diag = acts[0].diagonalSize() x0, x1, y0, y1, z0, z1 = acts[0].GetBounds() corners = [(x0, y0, z0), (x1, y0, z0), (x1, y1, z0), (x0, y1, z0), (x0, y0, z1), (x1, y0, z1), (x1, y1, z1), (x0, y1, z1)] pcl = acts[0].closestPoint(corners[corner]) dmin = np.linalg.norm(pcl - corners[corner]) for tt in rng: d = linInterpolate(tt, [t, t + duration], [dmin, diag * 1.01]) if d > 0: ids = acts[0].closestPoint(corners[corner], radius=d, returnIds=True) if len(ids) <= acts[0].N(): self.events.append((tt, self.meshErode, acts, ids)) else: self._performers[0].deletePoints(self._inputvalues) return self
def tips(): from vtkplotter import colors msg = "|Press: i to print info about selected object |\n" msg += "| m to minimise opacity of selected mesh |\n" msg += "| ., to reduce/increase opacity |\n" msg += "| / to maximize opacity |\n" msg += "| w/s to toggle wireframe/solid style |\n" msg += "| p/P to change point size of vertices |\n" msg += "| l/L to change edge line width |\n" msg += "| x to toggle mesh visibility |\n" msg += "| X to pop up a cutter widget tool |\n" msg += "| 1-3 to change mesh color |\n" msg += "| 4 to change background color |\n" msg += "| k/K to show point/cell scalars as color |\n" msg += "| n to show surface mesh normals |\n" msg += "| a to toggle interaction to Actor Mode |\n" msg += "| j to toggle interaction to Joystick Mode |\n" msg += "| C to print current camera info |\n" msg += "| S to save a screenshot |\n" msg += "| q/e to continue/close the rendering window |\n" msg += "| Esc to exit program |\n" msg += '| |\n' msg += "|Mouse: Left-click to rotate scene / pick actors |\n" msg += "| Middle-click to pan scene |\n" msg += "| Right-click to zoom scene in or out |" colors.printc(msg, dim=1)
def mirror(self, axis="x"): """ Mirror flip along one of the cartesian axes. .. note:: ``axis='n'``, will flip only mesh normals. |mirror| |mirror.py|_ """ img = self.imagedata() ff = vtk.vtkImageFlip() ff.SetInputData(img) if axis.lower() == "x": ff.SetFilteredAxis(0) elif axis.lower() == "y": ff.SetFilteredAxis(1) elif axis.lower() == "z": ff.SetFilteredAxis(2) else: colors.printc( "~times Error in mirror(): mirror must be set to x, y, z or n.", c=1) raise RuntimeError() ff.Update() return self._update(ff.GetOutput())
def smoothMLS1D(actor, f=0.2, showNLines=0): ''' Smooth actor or points with a Moving Least Squares variant. The list actor.variances contain the residue calculated for each point. Input actor's polydata is modified. f, smoothing factor - typical range s [0,2] showNLines, build an actor showing the fitting line for N random points ''' coords = vu.coordinates(actor) ncoords = len(coords) Ncp = int(ncoords * f / 10) nshow = int(ncoords) if showNLines: ndiv = int(nshow / showNLines) if Ncp < 3: vc.printc('Please choose a higher fraction than ' + str(f), 1) Ncp = 3 poly = vu.polydata(actor, True) vpts = poly.GetPoints() locator = vtk.vtkPointLocator() locator.SetDataSet(poly) locator.BuildLocator() vtklist = vtk.vtkIdList() variances, newline, acts = [], [], [] for i, p in enumerate(coords): locator.FindClosestNPoints(Ncp, p, vtklist) points = [] for j in range(vtklist.GetNumberOfIds()): trgp = [0, 0, 0] vpts.GetPoint(vtklist.GetId(j), trgp) points.append(trgp) if len(points) < 2: continue points = np.array(points) pointsmean = points.mean(axis=0) # plane center uu, dd, vv = np.linalg.svd(points - pointsmean) newp = np.dot(p - pointsmean, vv[0]) * vv[0] + pointsmean variances.append(dd[1] + dd[2]) newline.append(newp) if showNLines and not i % ndiv: fline = fitLine(points, lw=4, alpha=1) # fitting plane iapts = vs.points(points) # blue points acts += [fline, iapts] for i in range(ncoords): vpts.SetPoint(i, newline[i]) if showNLines: apts = vs.points(newline, c='r 0.6', r=2) ass = vu.makeAssembly([apts] + acts) return ass #NB: a demo actor is returned setattr(actor, 'variances', np.array(variances)) return actor #NB: original actor is modified
def addPointArray(self, input_array, name): """ Add point array and assign it a name. |mesh_coloring| |mesh_coloring.py|_ """ data = self.inputdata() if isinstance(input_array, vtk.vtkDataArray): data.GetPointData().AddArray(input_array) input_array.SetName(name) data.GetPointData().SetActiveScalars(name) self._mapper.ScalarVisibilityOn() self._mapper.SetScalarRange(input_array.GetRange()) if hasattr(self._mapper, 'SetArrayName'): self._mapper.SetArrayName(name) self._mapper.SetScalarModeToUsePointData() return self if len(input_array) != data.GetNumberOfPoints(): colors.printc( 'Error in addPointArray(): Number of inputs != nr. of points', len(input_array), data.GetNumberOfPoints(), c=1) raise RuntimeError() nparr = np.ascontiguousarray(input_array) if len(nparr.shape) == 1: # scalars varr = numpy_to_vtk(nparr, deep=True) varr.SetName(name) data.GetPointData().AddArray(varr) data.GetPointData().SetActiveScalars(name) self._mapper.SetScalarModeToUsePointData() if hasattr(self._mapper, 'ScalarVisibilityOn'): # could be volume mapper self._mapper.ScalarVisibilityOn() self._mapper.SetScalarRange(varr.GetRange()) elif len(nparr.shape) == 2: # vectors or higher dim ntuples varr = vtk.vtkFloatArray() varr.SetNumberOfComponents(nparr.shape[1]) varr.SetName(name) for v in nparr: varr.InsertNextTuple(v) data.GetPointData().AddArray(varr) if nparr.shape[1] == 3: data.GetPointData().SetActiveVectors(name) else: colors.printc('Error in addPointArray(): cannot deal with shape:', nparr.shape, c=1) return self if hasattr(self._mapper, 'SetArrayName'): self._mapper.SetArrayName(name) self._mapper.SetScalarModeToUsePointData() return self
def loadNeutral(filename, c, alpha, wire, bc, edges, legend): '''Reads a Neutral tetrahedral file format''' if not os.path.exists(filename): vc.printc(('Error in loadNeutral: Cannot find', filename), c=1) return None coords, connectivity = convertNeutral2Xml(filename) poly = buildPolyData(coords, connectivity, indexOffset=0) return vu.makeActor(poly, c, alpha, wire, bc, edges, legend)
def loadNeutral(filename, c='gold', alpha=1, wire=False, bc=None, legend=None): '''Reads a Neutral tetrahedral file format''' if not os.path.exists(filename): colors.printc('Error in loadNeutral: Cannot find', filename, c=1) return None coords, connectivity = convertNeutral2Xml(filename) poly = buildPolyData(coords, connectivity, indexOffset=0) return Actor(poly, c, alpha, wire, bc, legend)
def slicer2d(volume, size=(900, 900), bg=(0.6, 0.6, 0.7), zoom=1.3): """Create a 2D window with a single balck a nd white slice of a Volume, wich can be oriented arbitrarily in space. """ img = volume.imagedata() ren1 = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren1) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) im = vtk.vtkImageResliceMapper() im.SetInputData(img) im.SliceFacesCameraOn() im.SliceAtFocalPointOn() im.BorderOn() ip = vtk.vtkImageProperty() ip.SetInterpolationTypeToLinear() ia = vtk.vtkImageSlice() ia.SetMapper(im) ia.SetProperty(ip) ren1.AddViewProp(ia) ren1.SetBackground(bg) renWin.SetSize(size) iren = vtk.vtkRenderWindowInteractor() style = vtk.vtkInteractorStyleImage() style.SetInteractionModeToImage3D() iren.SetInteractorStyle(style) renWin.SetInteractor(iren) renWin.Render() cam1 = ren1.GetActiveCamera() cam1.ParallelProjectionOn() ren1.ResetCameraClippingRange() cam1.Zoom(zoom) renWin.Render() printc("Slicer2D tool", invert=1, c="m") printc( """Press SHIFT+Left mouse to rotate the camera for oblique slicing SHIFT+Middle mouse to slice perpendicularly through the image Left mouse and Drag to modify luminosity and contrast X to Reset to sagittal view Y to Reset to coronal view Z to Reset to axial view R to Reset the Window/Levels Q to Quit.""", c="m", ) iren.Start() return iren