def earth(pos=[0, 0, 0], r=1, lw=1): '''Build a textured actor representing the Earth. .. hint:: Example: `earth.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/earth.py>`_ .. image:: https://user-images.githubusercontent.com/32848391/51031592-5a448700-159d-11e9-9b66-bee6abb18679.png ''' import os tss = vtk.vtkTexturedSphereSource() tss.SetRadius(r) tss.SetThetaResolution(72) tss.SetPhiResolution(36) earthMapper = vtk.vtkPolyDataMapper() earthMapper.SetInputConnection(tss.GetOutputPort()) earthActor = Actor() #vtk.vtkActor() earthActor.SetMapper(earthMapper) atext = vtk.vtkTexture() pnmReader = vtk.vtkPNMReader() cdir = os.path.dirname(__file__) if cdir == '': cdir = '.' fn = cdir + '/textures/earth.ppm' pnmReader.SetFileName(fn) atext.SetInputConnection(pnmReader.GetOutputPort()) atext.InterpolateOn() earthActor.SetTexture(atext) if not lw: earthActor.SetPosition(pos) return earthActor es = vtk.vtkEarthSource() es.SetRadius(r / .995) earth2Mapper = vtk.vtkPolyDataMapper() earth2Mapper.SetInputConnection(es.GetOutputPort()) earth2Actor = Actor() # vtk.vtkActor() earth2Actor.SetMapper(earth2Mapper) earth2Actor.GetProperty().SetLineWidth(lw) ass = Assembly([earthActor, earth2Actor]) ass.SetPosition(pos) return ass
def Earth(pos=(0, 0, 0), r=1, lw=1): """Build a textured actor representing the Earth. .. hint:: |geodesic| |geodesic.py|_ """ import os tss = vtk.vtkTexturedSphereSource() tss.SetRadius(r) tss.SetThetaResolution(72) tss.SetPhiResolution(36) earthMapper = vtk.vtkPolyDataMapper() earthMapper.SetInputConnection(tss.GetOutputPort()) earthActor = Actor(c="w") earthActor.SetMapper(earthMapper) atext = vtk.vtkTexture() pnmReader = vtk.vtkPNMReader() cdir = os.path.dirname(__file__) if cdir == "": cdir = "." fn = cdir + "/textures/earth.ppm" pnmReader.SetFileName(fn) atext.SetInputConnection(pnmReader.GetOutputPort()) atext.InterpolateOn() earthActor.SetTexture(atext) if not lw: earthActor.SetPosition(pos) return earthActor es = vtk.vtkEarthSource() es.SetRadius(r / 0.995) earth2Mapper = vtk.vtkPolyDataMapper() earth2Mapper.SetInputConnection(es.GetOutputPort()) earth2Actor = Actor() # vtk.vtkActor() earth2Actor.SetMapper(earth2Mapper) earth2Mapper.ScalarVisibilityOff() earth2Actor.GetProperty().SetLineWidth(lw) ass = Assembly([earthActor, earth2Actor]) ass.SetPosition(pos) return ass
def Line(p0, p1=None, c="r", alpha=1, lw=1, dotted=False, res=None): """ Build the line segment between points `p0` and `p1`. If `p0` is a list of points returns the line connecting them. A 2D set of coords can also be passed as p0=[x..], p1=[y..]. :param c: color name, number, or list of [R,G,B] colors. :type c: int, str, list :param float alpha: transparency in range [0,1]. :param lw: line width. :param bool dotted: draw a dotted line :param int res: number of intermediate points in the segment """ # detect if user is passing a 2D ist of points as p0=xlist, p1=ylist: if len(p0) > 3: if not utils.isSequence(p0[0]) and not utils.isSequence(p1[0]) and len(p0)==len(p1): # assume input is 2D xlist, ylist p0 = list(zip(p0, p1)) p1 = None # detect if user is passing a list of points: if utils.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline dim = len((p0[0])) if dim == 2: for i, p in enumerate(p0): ppoints.InsertPoint(i, p[0], p[1], 0) else: ppoints.SetData(numpy_to_vtk(p0, deep=True)) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly = vtk.vtkPolyData() poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) if res: lineSource.SetResolution(res) lineSource.Update() poly = lineSource.GetOutput() actor = Actor(poly, c, alpha) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xF0F0) actor.GetProperty().SetLineStippleRepeatFactor(1) actor.base = np.array(p0) actor.top = np.array(p1) settings.collectable_actors.append(actor) return actor
def cylinder(pos=[0, 0, 0], r=1, height=1, axis=[0, 0, 1], c='teal', wire=0, alpha=1, legend=None, texture=None, 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`. ''' 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.norm(axis) else: axis = utils.norm(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(theta * 57.3) t.RotateZ(phi * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(cyl.GetOutput()) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c, alpha, wire, legend=legend, texture=texture) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) actor.base = base actor.top = top return actor
def delaunay2D(plist, tol=None, c='gold', alpha=0.5, wire=False, bc=None, legend=None, texture=None): ''' Create a mesh from points in the XY plane. [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/delaunay2d.py) ''' pd = vtk.vtkPolyData() vpts = vtk.vtkPoints() vpts.SetData(numpy_to_vtk(plist, deep=True)) pd.SetPoints(vpts) delny = vtk.vtkDelaunay2D() delny.SetInputData(pd) if tol: delny.SetTolerance(tol) delny.Update() return Actor(delny.GetOutput(), c, alpha, wire, bc, legend, texture)
def _loadDolfin_old(filename, exterior='dummy'): import xml.etree.ElementTree as et if filename.endswith(".gz"): import gzip inF = gzip.open(filename, "rb") outF = open("/tmp/filename.xml", "wb") outF.write(inF.read()) outF.close() inF.close() tree = et.parse("/tmp/filename.xml") else: tree = et.parse(filename) coords, connectivity = [], [] for mesh in tree.getroot(): for elem in mesh: for e in elem.findall("vertex"): x = float(e.get("x")) y = float(e.get("y")) ez = e.get("z") if ez is None: coords.append([x, y]) else: z = float(ez) coords.append([x, y, z]) tets = elem.findall("tetrahedron") if not len(tets): tris = elem.findall("triangle") for e in tris: v0 = int(e.get("v0")) v1 = int(e.get("v1")) v2 = int(e.get("v2")) connectivity.append([v0, v1, v2]) else: for e in tets: v0 = int(e.get("v0")) v1 = int(e.get("v1")) v2 = int(e.get("v2")) v3 = int(e.get("v3")) connectivity.append([v0, v1, v2, v3]) poly = utils.buildPolyData(coords, connectivity) return Actor(poly)
def Ellipsoid(pos=(0, 0, 0), axis1=(1, 0, 0), axis2=(0, 2, 0), axis3=(0, 0, 3), c="c", alpha=1, res=24): """ Build a 3D ellipsoid centered at position `pos`. .. note:: `axis1` and `axis2` are only used to define sizes and one azimuth angle. |projectsphere| """ elliSource = vtk.vtkSphereSource() elliSource.SetThetaResolution(res) elliSource.SetPhiResolution(res) elliSource.Update() l1 = np.linalg.norm(axis1) l2 = np.linalg.norm(axis2) l3 = np.linalg.norm(axis3) axis1 = np.array(axis1) / l1 axis2 = np.array(axis2) / l2 axis3 = np.array(axis3) / l3 angle = np.arcsin(np.dot(axis1, axis2)) theta = np.arccos(axis3[2]) phi = np.arctan2(axis3[1], axis3[0]) t = vtk.vtkTransform() t.PostMultiply() t.Scale(l1, l2, l3) t.RotateX(np.rad2deg(angle)) t.RotateY(np.rad2deg(theta)) t.RotateZ(np.rad2deg(phi)) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(elliSource.GetOutput()) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c=c, alpha=alpha) actor.GetProperty().BackfaceCullingOn() actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) actor.base = -np.array(axis1) / 2 + pos actor.top = np.array(axis1) / 2 + pos settings.collectable_actors.append(actor) return actor
def helix(startPoint=[0, 0, 0], endPoint=[1, 0, 0], coils=20, r=None, thickness=None, c='grey', alpha=1, legend=None, texture=None): ''' Build a spring of specified nr of `coils` between `startPoint` and `endPoint`. .. hint:: Example: `aspring.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/aspring.py>`_ .. image:: https://user-images.githubusercontent.com/32848391/36788885-e97e80ae-1c8f-11e8-8b8f-ffc43dad1eb1.gif ''' diff = endPoint - np.array(startPoint) length = np.linalg.norm(diff) if not length: return None if not r: r = length / 20 trange = np.linspace(0, length, num=50 * coils) om = 6.283 * (coils - .5) / length pts = [[r * np.cos(om * t), r * np.sin(om * t), t] for t in trange] pts = [[0, 0, 0]] + pts + [[0, 0, length]] diff = diff / length theta = np.arccos(diff[2]) phi = np.arctan2(diff[1], diff[0]) sp = line(pts).polydata(False) t = vtk.vtkTransform() t.RotateZ(phi * 57.3) t.RotateY(theta * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(sp) tf.SetTransform(t) tf.Update() tuf = vtk.vtkTubeFilter() tuf.SetNumberOfSides(12) tuf.CappingOn() tuf.SetInputData(tf.GetOutput()) if not thickness: thickness = r / 10 tuf.SetRadius(thickness) tuf.Update() poly = tuf.GetOutput() actor = Actor(poly, c, alpha, legend=legend, texture=texture) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(startPoint) actor.base = np.array(startPoint) actor.top = np.array(endPoint) return actor
def helix(startPoint=[0, 0, 0], endPoint=[1, 1, 1], coils=20, r=None, thickness=None, c='grey', alpha=1, legend=None, texture=None): ''' Build a spring of specified nr of coils between startPoint and endPoint. [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/spring.py) [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/gyroscope1.py) [**Example3**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/multiple_pendulum.py) ''' diff = endPoint - np.array(startPoint) length = np.linalg.norm(diff) if not length: return None if not r: r = length / 20 trange = np.linspace(0, length, num=50 * coils) om = 6.283 * (coils - .5) / length pts = [[r * np.cos(om * t), r * np.sin(om * t), t] for t in trange] pts = [[0, 0, 0]] + pts + [[0, 0, length]] diff = diff / length theta = np.arccos(diff[2]) phi = np.arctan2(diff[1], diff[0]) sp = line(pts).polydata(False) t = vtk.vtkTransform() t.RotateZ(phi * 57.3) t.RotateY(theta * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(sp) tf.SetTransform(t) tf.Update() tuf = vtk.vtkTubeFilter() tuf.SetNumberOfSides(12) tuf.CappingOn() tuf.SetInputData(tf.GetOutput()) if not thickness: thickness = r / 10 tuf.SetRadius(thickness) tuf.Update() poly = tuf.GetOutput() actor = Actor(poly, c, alpha, legend=legend, texture=texture) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(startPoint) actor.base = np.array(startPoint) actor.top = np.array(endPoint) return actor
def earth(pos=[0, 0, 0], r=1, lw=1): '''Build a textured actor representing the Earth. [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/earth.py) ''' import os tss = vtk.vtkTexturedSphereSource() tss.SetRadius(r) tss.SetThetaResolution(72) tss.SetPhiResolution(36) earthMapper = vtk.vtkPolyDataMapper() earthMapper.SetInputConnection(tss.GetOutputPort()) earthActor = Actor() #vtk.vtkActor() earthActor.SetMapper(earthMapper) atext = vtk.vtkTexture() pnmReader = vtk.vtkPNMReader() cdir = os.path.dirname(__file__) if cdir == '': cdir = '.' fn = cdir + '/textures/earth.ppm' pnmReader.SetFileName(fn) atext.SetInputConnection(pnmReader.GetOutputPort()) atext.InterpolateOn() earthActor.SetTexture(atext) if not lw: earthActor.SetPosition(pos) return earthActor es = vtk.vtkEarthSource() es.SetRadius(r / .995) earth2Mapper = vtk.vtkPolyDataMapper() earth2Mapper.SetInputConnection(es.GetOutputPort()) earth2Actor = Actor() # vtk.vtkActor() earth2Actor.SetMapper(earth2Mapper) earth2Actor.GetProperty().SetLineWidth(lw) ass = Assembly([earthActor, earth2Actor]) ass.SetPosition(pos) return ass
def Arrow(startPoint, endPoint, s=None, c="r", alpha=1, res=12): """ Build a 3D arrow from `startPoint` to `endPoint` of section size `s`, expressed as the fraction of the window size. .. note:: If ``s=None`` the arrow is scaled proportionally to its length, otherwise it represents the fraction of the window size. |OrientedArrow| """ axis = np.array(endPoint) - np.array(startPoint) length = np.linalg.norm(axis) if length: axis = axis / length theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) arr = vtk.vtkArrowSource() arr.SetShaftResolution(res) arr.SetTipResolution(res) if s: sz = 0.02 arr.SetTipRadius(sz) arr.SetShaftRadius(sz / 1.75) arr.SetTipLength(sz * 15) arr.Update() t = vtk.vtkTransform() t.RotateZ(np.rad2deg(phi)) t.RotateY(np.rad2deg(theta)) t.RotateY(-90) # put it along Z if s: sz = 800.0 * s t.Scale(length, sz, sz) else: t.Scale(length, length, length) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(arr.GetOutput()) tf.SetTransform(t) tf.Update() actor = Actor(tf.GetOutput(), c, alpha) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(startPoint) actor.DragableOff() actor.base = np.array(startPoint) actor.top = np.array(endPoint) settings.collectable_actors.append(actor) return actor
def isosurface(image, c, alpha, wire, bc, legend, texture, smoothing, threshold, connectivity): '''Return a vtkActor isosurface from a vtkImageData object.''' from vtkplotter.actors import Actor if smoothing: print(' gaussian smoothing data with volume_smoothing =', smoothing) smImg = vtk.vtkImageGaussianSmooth() smImg.SetDimensionality(3) smImg.SetInputData(image) smImg.SetStandardDeviations(smoothing, smoothing, smoothing) smImg.Update() image = smImg.GetOutput() scrange = image.GetScalarRange() if not threshold: if scrange[1] > 1e10: threshold = (2*scrange[0]+abs(10*scrange[0]))/3. print("Warning, high scalar range detected:", scrange[1]) print(" setting threshold to:", threshold) else: threshold = (2*scrange[0]+scrange[1])/3. cf = vtk.vtkContourFilter() cf.SetInputData(image) cf.UseScalarTreeOn() cf.ComputeScalarsOff() cf.SetValue(0, threshold) cf.Update() clp = vtk.vtkCleanPolyData() clp.SetInputData(cf.GetOutput()) clp.Update() image = clp.GetOutput() if connectivity: print(' applying connectivity filter, select largest region') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetExtractionModeToLargestRegion() conn.SetInputData(image) conn.Update() image = conn.GetOutput() return Actor(image, c, alpha, wire, bc, legend, texture)
def Arrows(startPoints, endPoints=None, s=None, c="r", alpha=1, res=8): """ Build arrows between two lists of points `startPoints` and `endPoints`. `startPoints` can be also passed in the form ``[[point1, point2], ...]``. """ if endPoints is not None: startPoints = list(zip(startPoints, endPoints)) polyapp = vtk.vtkAppendPolyData() for twopts in startPoints: startPoint, endPoint = twopts axis = np.array(endPoint) - np.array(startPoint) length = np.linalg.norm(axis) if length: axis = axis / length theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) arr = vtk.vtkArrowSource() arr.SetShaftResolution(res) arr.SetTipResolution(res) if s: sz = 0.02 arr.SetTipRadius(sz) arr.SetShaftRadius(sz / 1.75) arr.SetTipLength(sz * 15) t = vtk.vtkTransform() t.Translate(startPoint) t.RotateZ(phi * 57.3) t.RotateY(theta * 57.3) t.RotateY(-90) # put it along Z if s: sz = 800.0 * s t.Scale(length, sz, sz) else: t.Scale(length, length, length) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputConnection(arr.GetOutputPort()) tf.SetTransform(t) polyapp.AddInputConnection(tf.GetOutputPort()) polyapp.Update() actor = Actor(polyapp.GetOutput(), c, alpha) return actor
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 loadNeutral(filename): """Reads a `Neutral` tetrahedral file format. Return an ``Actor(vtkActor)`` object.""" f = open(filename, "r") lines = f.readlines() f.close() ncoords = int(lines[0]) fdolf_coords = [] for i in range(1, ncoords + 1): x, y, z = lines[i].split() fdolf_coords.append([float(x), float(y), float(z)]) ntets = int(lines[ncoords + 1]) idolf_tets = [] for i in range(ncoords + 2, ncoords + ntets + 2): text = lines[i].split() v0, v1, v2, v3 = text[1], text[2], text[3], text[4] idolf_tets.append([int(v0) - 1, int(v1) - 1, int(v2) - 1, int(v3) - 1]) poly = utils.buildPolyData(fdolf_coords, idolf_tets) return Actor(poly)
def geometry(obj, extent=None): """ Apply the ``vtkGeometryFilter``. This is a general-purpose filter to extract geometry (and associated data) from any type of dataset. This filter also may be used to convert any type of data to polygonal type. The conversion process may be less than satisfactory for some 3D datasets. For example, this filter will extract the outer surface of a volume or structured grid dataset. Returns an ``Actor`` object. :param list extent: set a `[xmin,xmax, ymin,ymax, zmin,zmax]` bounding box to clip data. """ from vtkplotter.actors import Actor gf = vtk.vtkGeometryFilter() gf.SetInputData(obj) if extent is not None: gf.SetExtent(extent) gf.Update() return Actor(gf.GetOutput())
def loadGmesh(filename, c='gold', alpha=1, wire=False, bc=None, legend=None): ''' Reads a gmesh file format ''' if not os.path.exists(filename): colors.printc('Error in loadGmesh: Cannot find', filename, c=1) return None f = open(filename, 'r') lines = f.readlines() f.close() nnodes = 0 index_nodes = 0 for i, line in enumerate(lines): if '$Nodes' in line: index_nodes = i + 1 nnodes = int(lines[index_nodes]) break node_coords = [] for i in range(index_nodes + 1, index_nodes + 1 + nnodes): cn = lines[i].split() node_coords.append([float(cn[1]), float(cn[2]), float(cn[3])]) nelements = 0 index_elements = 0 for i, line in enumerate(lines): if '$Elements' in line: index_elements = i + 1 nelements = int(lines[index_elements]) break elements = [] for i in range(index_elements + 1, index_elements + 1 + nelements): ele = lines[i].split() elements.append([int(ele[-3]), int(ele[-2]), int(ele[-1])]) poly = buildPolyData(node_coords, elements, indexOffset=1) return Actor(poly, c, alpha, wire, bc, legend)
def loadOFF(filename): """Read OFF file format.""" f = open(filename, "r") lines = f.readlines() f.close() vertices = [] faces = [] NumberOfVertices = None i = -1 for text in lines: if len(text) == 0: continue if text == '\n': continue if "#" in text: continue if "OFF" in text: continue ts = text.split() n = len(ts) if not NumberOfVertices and n > 1: NumberOfVertices, NumberOfFaces = int(ts[0]), int(ts[1]) continue i += 1 if i < NumberOfVertices and n == 3: x, y, z = float(ts[0]), float(ts[1]), float(ts[2]) vertices.append([x, y, z]) ids = [] if NumberOfVertices <= i < (NumberOfVertices + NumberOfFaces + 1) and n > 2: ids += [int(xx) for xx in ts[1:]] faces.append(ids) return Actor(utils.buildPolyData(vertices, faces))
def grid(pos=[0, 0, 0], normal=[0, 0, 1], sx=1, sy=1, c='g', bc='darkgreen', lw=1, alpha=1, legend=None, resx=10, resy=10): '''Return a grid plane. .. hint:: Example: `brownian2D.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/brownian2D.py>`_ .. image:: https://user-images.githubusercontent.com/32848391/50738948-73ce8300-11d9-11e9-8ef6-fc4f64c4a9ce.gif ''' ps = vtk.vtkPlaneSource() ps.SetResolution(resx, resy) ps.Update() poly0 = ps.GetOutput() t0 = vtk.vtkTransform() t0.Scale(sx, sy, 1) tf0 = vtk.vtkTransformPolyDataFilter() tf0.SetInputData(poly0) tf0.SetTransform(t0) tf0.Update() poly = tf0.GetOutput() axis = np.array(normal) / np.linalg.norm(normal) theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) t = vtk.vtkTransform() t.PostMultiply() t.RotateY(theta * 57.3) t.RotateZ(phi * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(poly) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c=c, bc=bc, alpha=alpha, legend=legend) actor.GetProperty().SetRepresentationToWireframe() actor.GetProperty().SetLineWidth(lw) actor.SetPosition(pos) actor.PickableOff() return actor
def loadPCD(filename): """Return ``vtkActor`` from `Point Cloud` file format. Return an ``Actor(vtkActor)`` object.""" f = open(filename, "r") lines = f.readlines() f.close() start = False pts = [] N, expN = 0, 0 for text in lines: if start: if N >= expN: break l = text.split() pts.append([float(l[0]), float(l[1]), float(l[2])]) N += 1 if not start and "POINTS" in text: expN = int(text.split()[1]) if not start and "DATA ascii" in text: start = True if expN != N: colors.printc("~!? Mismatch in pcd file", expN, len(pts), c="red") poly = utils.buildPolyData(pts) return Actor(poly).pointSize(4)
def loadDolfin(filename, exterior=False): """Reads a `Fenics/Dolfin` file format. Return an ``Actor(vtkActor)`` object.""" import dolfin if filename.lower().endswith('.xdmf'): f = dolfin.XDMFFile(filename) m = dolfin.Mesh() f.read(m) else: m = dolfin.Mesh(filename) bm = dolfin.BoundaryMesh(m, "exterior") if exterior: poly = utils.buildPolyData(bm.coordinates(), bm.cells(), fast=True) else: polyb = utils.buildPolyData(bm.coordinates(), bm.cells(), fast=True) polym = utils.buildPolyData(m.coordinates(), m.cells(), fast=True) app = vtk.vtkAppendPolyData() app.AddInputData(polym) app.AddInputData(polyb) app.Update() poly = app.GetOutput() return Actor(poly)
def Grid(pos=(0, 0, 0), normal=(0, 0, 1), sx=1, sy=1, c="g", bc="darkgreen", lw=1, alpha=1, resx=10, resy=10): """Return a grid plane. .. hint:: |brownian2D| |brownian2D.py|_ """ ps = vtk.vtkPlaneSource() ps.SetResolution(resx, resy) ps.Update() poly0 = ps.GetOutput() t0 = vtk.vtkTransform() t0.Scale(sx, sy, 1) tf0 = vtk.vtkTransformPolyDataFilter() tf0.SetInputData(poly0) tf0.SetTransform(t0) tf0.Update() poly = tf0.GetOutput() axis = np.array(normal) / np.linalg.norm(normal) theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) t = vtk.vtkTransform() t.PostMultiply() t.RotateY(theta * 57.3) t.RotateZ(phi * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(poly) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c=c, bc=bc, alpha=alpha) actor.GetProperty().SetRepresentationToWireframe() actor.GetProperty().SetLineWidth(lw) actor.SetPosition(pos) actor.PickableOff() return actor
def line(p0, p1=None, lw=1, c='r', alpha=1, dotted=False, legend=None): ''' Build the line segment between points `p0` and `p1`. If `p0` is a list of points returns the line connecting them. :param lw: line width. :param c: color name, number, or list of [R,G,B] colors. :type c: int, str, list :param float alpha: transparency in range [0,1]. :param bool dotted: draw a dotted line ''' # detect if user is passing a list of points: if utils.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline dim = len((p0[0])) if dim == 2: for i in range(len(p0)): p = p0[i] ppoints.InsertPoint(i, p[0], p[1], 0) else: ppoints.SetData(numpy_to_vtk(p0, deep=True)) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly = vtk.vtkPolyData() poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) lineSource.Update() poly = lineSource.GetOutput() actor = Actor(poly, c, alpha, legend=legend) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xf0f0) actor.GetProperty().SetLineStippleRepeatFactor(1) actor.base = np.array(p0) actor.top = np.array(p1) return actor
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
def line(p0, p1=None, lw=1, dotted=False, c='r', alpha=1, legend=None): ''' Build the line segment between points p0 and p1. If p0 is a list of points returns the line connecting them. ''' # detect if user is passing a list of points: if utils.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline dim = len((p0[0])) if dim == 2: for i in range(len(p0)): p = p0[i] ppoints.InsertPoint(i, p[0], p[1], 0) else: ppoints.SetData(numpy_to_vtk(p0, deep=True)) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly = vtk.vtkPolyData() poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) lineSource.Update() poly = lineSource.GetOutput() actor = Actor(poly, c, alpha, legend=legend) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xf0f0) actor.GetProperty().SetLineStippleRepeatFactor(1) actor.base = np.array(p0) actor.top = np.array(p1) return actor
def Spheres(centers, r=1, c="r", alpha=1, res=8): """ Build a (possibly large) set of spheres at `centers` of radius `r`. Either `c` or `r` can be a list of RGB colors or radii. .. hint:: |manyspheres| |manyspheres.py|_ """ cisseq = False if utils.isSequence(c): cisseq = True if cisseq: if len(centers) > len(c): colors.printc("~times Mismatch in Spheres() colors", len(centers), len(c), c=1) exit() if len(centers) != len(c): colors.printc("~lightningWarning: mismatch in Spheres() colors", len(centers), len(c)) risseq = False if utils.isSequence(r): risseq = True if risseq: if len(centers) > len(r): colors.printc("times Mismatch in Spheres() radius", len(centers), len(r), c=1) exit() if len(centers) != len(r): colors.printc("~lightning Warning: mismatch in Spheres() radius", len(centers), len(r)) if cisseq and risseq: colors.printc("~noentry Limitation: c and r cannot be both sequences.", c=1) exit() src = vtk.vtkSphereSource() if not risseq: src.SetRadius(r) src.SetPhiResolution(res) src.SetThetaResolution(2 * res) src.Update() psrc = vtk.vtkPointSource() psrc.SetNumberOfPoints(len(centers)) psrc.Update() pd = psrc.GetOutput() vpts = pd.GetPoints() glyph = vtk.vtkGlyph3D() glyph.SetSourceConnection(src.GetOutputPort()) if cisseq: glyph.SetColorModeToColorByScalar() ucols = vtk.vtkUnsignedCharArray() ucols.SetNumberOfComponents(3) ucols.SetName("colors") for i, p in enumerate(centers): vpts.SetPoint(i, p) cx, cy, cz = colors.getColor(c[i]) ucols.InsertNextTuple3(cx * 255, cy * 255, cz * 255) pd.GetPointData().SetScalars(ucols) glyph.ScalingOff() elif risseq: glyph.SetScaleModeToScaleByScalar() urads = vtk.vtkFloatArray() urads.SetName("scales") for i, p in enumerate(centers): vpts.SetPoint(i, p) urads.InsertNextValue(r[i]) pd.GetPointData().SetScalars(urads) else: for i, p in enumerate(centers): vpts.SetPoint(i, p) glyph.SetInputData(pd) glyph.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(glyph.GetOutput()) actor = Actor() actor.SetMapper(mapper) actor.GetProperty().SetInterpolationToPhong() actor.GetProperty().SetOpacity(alpha) if cisseq: mapper.ScalarVisibilityOn() else: mapper.ScalarVisibilityOff() actor.GetProperty().SetColor(colors.getColor(c)) settings.collectable_actors.append(actor) return actor
def Points(plist, r=5, c="gray", alpha=1): """ Build a point ``Actor`` for a list of points. :param float r: point radius. :param c: color name, number, or list of [R,G,B] colors of same length as plist. :type c: int, str, list :param float alpha: transparency in range [0,1]. .. hint:: |lorenz| |lorenz.py|_ """ 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) exit() 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 n = len(plist) if n == 0: return None elif n == 3: # assume plist is in the format [all_x, all_y, all_z] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], plist[2])) elif n == 2: # assume plist is in the format [all_x, all_y, 0] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], [0] * len(plist[0]))) if utils.isSequence(c) and len(c) > 3: actor = _colorPoints(plist, c, r, alpha) settings.collectable_actors.append(actor) return actor ################ n = len(plist) # refresh sourcePoints = vtk.vtkPoints() sourceVertices = vtk.vtkCellArray() is3d = len(plist[0]) > 2 if is3d: # its faster for pt in plist: aid = sourcePoints.InsertNextPoint(pt) sourceVertices.InsertNextCell(1) sourceVertices.InsertCellPoint(aid) else: for pt in plist: aid = sourcePoints.InsertNextPoint(pt[0], pt[1], 0) sourceVertices.InsertNextCell(1) sourceVertices.InsertCellPoint(aid) pd = vtk.vtkPolyData() pd.SetPoints(sourcePoints) pd.SetVerts(sourceVertices) if n == 1: # passing just one point pd.GetPoints().SetPoint(0, [0, 0, 0]) else: pd.GetPoints().SetData(numpy_to_vtk(plist, deep=True)) actor = Actor(pd, c, alpha) actor.GetProperty().SetPointSize(r) if n == 1: actor.SetPosition(plist[0]) settings.collectable_actors.append(actor) return actor
def Ribbon(line1, line2, c="m", alpha=1, res=(200, 5)): """Connect two lines to generate the surface inbetween. .. hint:: |ribbon| |ribbon.py|_ """ if isinstance(line1, Actor): line1 = line1.coordinates() if isinstance(line2, Actor): line2 = line2.coordinates() ppoints1 = vtk.vtkPoints() # Generate the polyline1 ppoints1.SetData(numpy_to_vtk(line1, deep=True)) lines1 = vtk.vtkCellArray() lines1.InsertNextCell(len(line1)) for i in range(len(line1)): lines1.InsertCellPoint(i) poly1 = vtk.vtkPolyData() poly1.SetPoints(ppoints1) poly1.SetLines(lines1) ppoints2 = vtk.vtkPoints() # Generate the polyline2 ppoints2.SetData(numpy_to_vtk(line2, deep=True)) lines2 = vtk.vtkCellArray() lines2.InsertNextCell(len(line2)) for i in range(len(line2)): lines2.InsertCellPoint(i) poly2 = vtk.vtkPolyData() poly2.SetPoints(ppoints2) poly2.SetLines(lines2) # build the lines lines1 = vtk.vtkCellArray() lines1.InsertNextCell(poly1.GetNumberOfPoints()) for i in range(poly1.GetNumberOfPoints()): lines1.InsertCellPoint(i) polygon1 = vtk.vtkPolyData() polygon1.SetPoints(ppoints1) polygon1.SetLines(lines1) lines2 = vtk.vtkCellArray() lines2.InsertNextCell(poly2.GetNumberOfPoints()) for i in range(poly2.GetNumberOfPoints()): lines2.InsertCellPoint(i) polygon2 = vtk.vtkPolyData() polygon2.SetPoints(ppoints2) polygon2.SetLines(lines2) mergedPolyData = vtk.vtkAppendPolyData() mergedPolyData.AddInputData(polygon1) mergedPolyData.AddInputData(polygon2) mergedPolyData.Update() rsf = vtk.vtkRuledSurfaceFilter() rsf.CloseSurfaceOff() rsf.SetRuledModeToResample() rsf.SetResolution(res[0], res[1]) rsf.SetInputData(mergedPolyData.GetOutput()) rsf.Update() actor = Actor(rsf.GetOutput(), c=c, alpha=alpha) settings.collectable_actors.append(actor) return actor
def Tube(points, r=1, c="r", alpha=1, res=12): """Build a tube along the line defined by a set of points. :param r: constant radius or list of radii. :type r: float, list :param c: constant color or list of colors for each point. :type c: float, list .. hint:: |ribbon.py|_ |tube.py|_ |ribbon| |tube| """ ppoints = vtk.vtkPoints() # Generate the polyline ppoints.SetData(numpy_to_vtk(points, deep=True)) lines = vtk.vtkCellArray() lines.InsertNextCell(len(points)) for i in range(len(points)): lines.InsertCellPoint(i) polyln = vtk.vtkPolyData() polyln.SetPoints(ppoints) polyln.SetLines(lines) tuf = vtk.vtkTubeFilter() tuf.CappingOn() tuf.SetNumberOfSides(res) tuf.SetInputData(polyln) if utils.isSequence(r): arr = numpy_to_vtk(np.ascontiguousarray(r), deep=True) arr.SetName("TubeRadius") polyln.GetPointData().AddArray(arr) polyln.GetPointData().SetActiveScalars("TubeRadius") tuf.SetVaryRadiusToVaryRadiusByAbsoluteScalar() else: tuf.SetRadius(r) usingColScals = False if utils.isSequence(c) and len(c) != 3: usingColScals = True cc = vtk.vtkUnsignedCharArray() cc.SetName("TubeColors") cc.SetNumberOfComponents(3) cc.SetNumberOfTuples(len(c)) for i, ic in enumerate(c): r, g, b = colors.getColor(ic) cc.InsertTuple3(i, int(255 * r), int(255 * g), int(255 * b)) polyln.GetPointData().AddArray(cc) c = None tuf.Update() polytu = tuf.GetOutput() actor = Actor(polytu, c=c, alpha=alpha, computeNormals=0) actor.phong() if usingColScals: actor.mapper.SetScalarModeToUsePointFieldData() actor.mapper.ScalarVisibilityOn() actor.mapper.SelectColorArray("TubeColors") actor.mapper.Modified() actor.base = np.array(points[0]) actor.top = np.array(points[-1]) settings.collectable_actors.append(actor) return actor
def Glyph(actor, glyphObj, orientationArray="", scaleByVectorSize=False, c=None, alpha=1): """ At each vertex of a mesh, another mesh - a `'glyph'` - is shown with various orientation options and coloring. Color can be specfied as a colormap which maps the size of the orientation vectors in `orientationArray`. :param orientationArray: list of vectors, ``vtkAbstractArray`` or the name of an already existing points array. :type orientationArray: list, str, vtkAbstractArray :param bool scaleByVectorSize: glyph mesh is scaled by the size of the vectors. .. hint:: |glyphs.py|_ |glyphs_arrows.py|_ |glyphs| |glyphs_arrows| """ cmap = None # user passing a color map to map orientationArray sizes if c in list(colors._mapscales.cmap_d.keys()): cmap = c c = None # user is passing an array of point colors if utils.isSequence(c) and len(c) > 3: ucols = vtk.vtkUnsignedCharArray() ucols.SetNumberOfComponents(3) ucols.SetName("glyphRGB") for col in c: cl = colors.getColor(col) ucols.InsertNextTuple3(cl[0] * 255, cl[1] * 255, cl[2] * 255) actor.polydata().GetPointData().SetScalars(ucols) c = None if isinstance(glyphObj, Actor): glyphObj = glyphObj.clean().polydata() gly = vtk.vtkGlyph3D() gly.SetInputData(actor.polydata()) gly.SetSourceData(glyphObj) gly.SetColorModeToColorByScalar() if orientationArray != "": gly.OrientOn() gly.SetScaleFactor(1) if scaleByVectorSize: gly.SetScaleModeToScaleByVector() else: gly.SetScaleModeToDataScalingOff() if orientationArray == "normals" or orientationArray == "Normals": gly.SetVectorModeToUseNormal() elif isinstance(orientationArray, vtk.vtkAbstractArray): actor.GetMapper().GetInput().GetPointData().AddArray( orientationArray) actor.GetMapper().GetInput().GetPointData().SetActiveVectors( "glyph_vectors") gly.SetInputArrayToProcess(0, 0, 0, 0, "glyph_vectors") gly.SetVectorModeToUseVector() elif utils.isSequence(orientationArray): # passing a list actor.addPointVectors(orientationArray, "glyph_vectors") gly.SetInputArrayToProcess(0, 0, 0, 0, "glyph_vectors") else: # passing a name gly.SetInputArrayToProcess(0, 0, 0, 0, orientationArray) gly.SetVectorModeToUseVector() if cmap: gly.SetColorModeToColorByVector() else: gly.SetColorModeToColorByScalar() gly.Update() pd = gly.GetOutput() actor = Actor(pd, c, alpha) if cmap: lut = vtk.vtkLookupTable() lut.SetNumberOfTableValues(512) lut.Build() for i in range(512): r, g, b = colors.colorMap(i, cmap, 0, 512) lut.SetTableValue(i, r, g, b, 1) actor.mapper.SetLookupTable(lut) actor.mapper.ScalarVisibilityOn() actor.mapper.SetScalarModeToUsePointData() rng = pd.GetPointData().GetScalars().GetRange() actor.mapper.SetScalarRange(rng[0], rng[1]) actor.GetProperty().SetInterpolationToFlat() settings.collectable_actors.append(actor) return actor