コード例 #1
0
def lines(plist0,
          plist1=None,
          lw=1,
          c='r',
          alpha=1,
          dotted=False,
          legend=None):
    '''
    Build the line segments between two lists of points `plist0` and `plist1`.
    `plist0` can be also passed in the form ``[[point1, point2], ...]``.

    .. hint:: Example: `fitspheres2.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/fitspheres2.py>`_
    '''
    if plist1 is not None:
        plist0 = list(zip(plist0, plist1))

    polylns = vtk.vtkAppendPolyData()
    for twopts in plist0:
        lineSource = vtk.vtkLineSource()
        lineSource.SetPoint1(twopts[0])
        lineSource.SetPoint2(twopts[1])
        polylns.AddInputConnection(lineSource.GetOutputPort())
    polylns.Update()

    actor = Actor(polylns.GetOutput(), c, alpha, legend=legend)
    actor.GetProperty().SetLineWidth(lw)
    if dotted:
        actor.GetProperty().SetLineStipplePattern(0xf0f0)
        actor.GetProperty().SetLineStippleRepeatFactor(1)
    return actor
コード例 #2
0
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
コード例 #3
0
 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
コード例 #4
0
def Lines(plist0, plist1=None, lw=1, c="r", alpha=1, dotted=False):
    """
    Build the line segments between two lists of points `plist0` and `plist1`.
    `plist0` can be also passed in the form ``[[point1, point2], ...]``.

    |lines|

    .. hint:: |fitspheres2.py|_
    """
    if plist1 is not None:
        plist0 = list(zip(plist0, plist1))

    polylns = vtk.vtkAppendPolyData()
    for twopts in plist0:
        lineSource = vtk.vtkLineSource()
        lineSource.SetPoint1(twopts[0])
        lineSource.SetPoint2(twopts[1])
        polylns.AddInputConnection(lineSource.GetOutputPort())
    polylns.Update()

    actor = Actor(polylns.GetOutput(), c, alpha)
    actor.GetProperty().SetLineWidth(lw)
    if dotted:
        actor.GetProperty().SetLineStipplePattern(0xF0F0)
        actor.GetProperty().SetLineStippleRepeatFactor(1)
    return actor
コード例 #5
0
def disc(pos=[0, 0, 0],
         normal=[0, 0, 1],
         r1=0.5,
         r2=1,
         c='coral',
         bc='darkgreen',
         lw=1,
         alpha=1,
         legend=None,
         texture=None,
         res=12):
    '''
    Build a 2D disc of internal radius `r1` and outer radius `r2`,
    oriented perpendicular to `normal`.
    '''
    ps = vtk.vtkDiskSource()
    ps.SetInnerRadius(r1)
    ps.SetOuterRadius(r2)
    ps.SetRadialResolution(res)
    ps.SetCircumferentialResolution(res * 6)  # ~2pi
    ps.Update()

    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(ps.GetOutput())
    tf.SetTransform(t)
    tf.Update()

    pd = tf.GetOutput()
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputData(pd)

    actor = Actor()  # vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.getColor(c))
    # check if color string contains a float, in this case ignore alpha
    al = colors._getAlpha(c)
    if al:
        alpha = al
    actor.GetProperty().SetOpacity(alpha)
    actor.GetProperty().SetLineWidth(lw)
    actor.GetProperty().SetInterpolationToFlat()
    if bc:  # defines a specific color for the backface
        backProp = vtk.vtkProperty()
        backProp.SetDiffuseColor(colors.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    if texture:
        actor.texture(texture)
    actor.SetPosition(pos)
    return actor
コード例 #6
0
def Disc(
    pos=(0, 0, 0),
    normal=(0, 0, 1),
    r1=0.5,
    r2=1,
    c="coral",
    bc="darkgreen",
    lw=1,
    alpha=1,
    res=12,
    resphi=None,
):
    """
    Build a 2D disc of internal radius `r1` and outer radius `r2`,
    oriented perpendicular to `normal`.

    |Disk|
    """
    ps = vtk.vtkDiskSource()
    ps.SetInnerRadius(r1)
    ps.SetOuterRadius(r2)
    ps.SetRadialResolution(res)
    if not resphi:
        resphi = 6 * res
    ps.SetCircumferentialResolution(resphi)
    ps.Update()

    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(np.rad2deg(theta))
    t.RotateZ(np.rad2deg(phi))
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(ps.GetOutput())
    tf.SetTransform(t)
    tf.Update()

    pd = tf.GetOutput()
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputData(pd)

    actor = Actor()  # vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.getColor(c))
    actor.GetProperty().SetOpacity(alpha)
    actor.GetProperty().SetLineWidth(lw)
    actor.GetProperty().SetInterpolationToFlat()
    if bc:  # defines a specific color for the backface
        backProp = vtk.vtkProperty()
        backProp.SetDiffuseColor(colors.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    actor.SetPosition(pos)
    settings.collectable_actors.append(actor)
    return actor
コード例 #7
0
def polygon(pos=[0, 0, 0],
            normal=[0, 0, 1],
            nsides=6,
            r=1,
            c='coral',
            bc='darkgreen',
            lw=1,
            alpha=1,
            legend=None,
            texture=None,
            followcam=False,
            camera=None):
    '''
    Build a 2D polygon of `nsides` of radius `r` oriented as `normal`.

    If ``followcam=True`` the polygon will always reorient itself to current camera.
    '''
    ps = vtk.vtkRegularPolygonSource()
    ps.SetNumberOfSides(nsides)
    ps.SetRadius(r)
    ps.SetNormal(-np.array(normal))
    ps.Update()

    tf = vtk.vtkTriangleFilter()
    tf.SetInputConnection(ps.GetOutputPort())
    tf.Update()

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(tf.GetOutputPort())
    if followcam:  # follow cam
        actor = vtk.vtkFollower()
        actor.SetCamera(camera)
        if not camera:
            colors.printc('Warning: vtkCamera does not yet exist for polygon',
                          c=5)
    else:
        actor = Actor()  # vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.getColor(c))
    # check if color string contains a float, in this case ignore alpha
    al = colors._getAlpha(c)
    if al:
        alpha = al
    actor.GetProperty().SetOpacity(alpha)
    actor.GetProperty().SetLineWidth(lw)
    actor.GetProperty().SetInterpolationToFlat()
    if bc:  # defines a specific color for the backface
        backProp = vtk.vtkProperty()
        backProp.SetDiffuseColor(colors.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    if texture:
        actor.texture(texture)
    actor.SetPosition(pos)
    return actor
コード例 #8
0
def Line(p0, p1=None, lw=1, c="r", alpha=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 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 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
コード例 #9
0
def Polygon(pos=(0, 0, 0),
            normal=(0, 0, 1),
            nsides=6,
            r=1,
            c="coral",
            bc="darkgreen",
            lw=1,
            alpha=1,
            followcam=False):
    """
    Build a 2D polygon of `nsides` of radius `r` oriented as `normal`.

    :param followcam: if `True` the text will auto-orient itself to the active camera.
        A ``vtkCamera`` object can also be passed.
    :type followcam: bool, vtkCamera  
    
    |Polygon|
    """
    ps = vtk.vtkRegularPolygonSource()
    ps.SetNumberOfSides(nsides)
    ps.SetRadius(r)
    ps.SetNormal(-np.array(normal))
    ps.Update()

    tf = vtk.vtkTriangleFilter()
    tf.SetInputConnection(ps.GetOutputPort())
    tf.Update()

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(tf.GetOutputPort())
    if followcam:
        import vtkplotter.plotter as plt

        actor = vtk.vtkFollower()
        if isinstance(followcam, vtk.vtkCamera):
            actor.SetCamera(followcam)
        else:
            actor.SetCamera(plt._plotter_instance.camera)
    else:
        actor = Actor()

    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.getColor(c))
    actor.GetProperty().SetOpacity(alpha)
    actor.GetProperty().SetLineWidth(lw)
    actor.GetProperty().SetInterpolationToFlat()
    if bc:  # defines a specific color for the backface
        backProp = vtk.vtkProperty()
        backProp.SetDiffuseColor(colors.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    actor.SetPosition(pos)
    return actor
コード例 #10
0
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
コード例 #11
0
def tube(points, r=1, c='r', alpha=1, legend=None, res=12):
    '''Build a tube of radius `r` along line defined by a set of points.
    
    .. hint:: Example: `ribbon.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/ribbon.py>`_

        .. image:: https://user-images.githubusercontent.com/32848391/50738851-be9bcb00-11d8-11e9-80ee-bd73c1c29c06.jpg    
    '''
    ppoints = vtk.vtkPoints()  # Generate the polyline
    ppoints.SetData(numpy_to_vtk(points, deep=True))
    lines = vtk.vtkCellArray()  # Create the polyline.
    lines.InsertNextCell(len(points))
    for i in range(len(points)):
        lines.InsertCellPoint(i)
    poly = vtk.vtkPolyData()
    poly.SetPoints(ppoints)
    poly.SetLines(lines)

    tuf = vtk.vtkTubeFilter()
    tuf.SetNumberOfSides(res)
    tuf.SetInputData(poly)
    tuf.SetRadius(r)
    tuf.CappingOn()
    tuf.Update()
    poly = tuf.GetOutput()
    actor = Actor(poly, c, alpha, legend=legend)
    actor.GetProperty().SetInterpolationToPhong()
    actor.base = np.array(points[0])
    actor.top = np.array(points[-1])
    return actor
コード例 #12
0
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 = utils.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
コード例 #13
0
ファイル: shapes.py プロジェクト: m-albert/vtkplotter
def Torus(pos=(0, 0, 0), r=1, thickness=0.1, axis=(0, 0, 1), c="khaki", alpha=1, res=30):
    """
    Build a torus of specified outer radius `r` internal radius `thickness`, centered at `pos`.

    .. hint:: |gas| |gas.py|_
    """
    rs = vtk.vtkParametricTorus()
    rs.SetRingRadius(r)
    rs.SetCrossSectionRadius(thickness)
    pfs = vtk.vtkParametricFunctionSource()
    pfs.SetParametricFunction(rs)
    pfs.SetUResolution(res * 3)
    pfs.SetVResolution(res)
    pfs.Update()

    nax = np.linalg.norm(axis)
    if nax:
        axis = np.array(axis) / nax
    theta = np.arccos(axis[2])
    phi = np.arctan2(axis[1], axis[0])
    t = vtk.vtkTransform()
    t.PostMultiply()
    t.RotateY(np.rad2deg(theta))
    t.RotateZ(np.rad2deg(phi))
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(pfs.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = Actor(pd, c, alpha)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    settings.collectable_actors.append(actor)
    return actor
コード例 #14
0
def cone(pos=[0, 0, 0],
         r=1,
         height=1,
         axis=[0, 0, 1],
         c='dg',
         alpha=1,
         legend=None,
         texture=None,
         res=48):
    '''
    Build a cone of specified radius `r` and `height`, centered at `pos`.
    '''
    con = vtk.vtkConeSource()
    con.SetResolution(res)
    con.SetRadius(r)
    con.SetHeight(height)
    con.SetDirection(axis)
    con.Update()
    actor = Actor(con.GetOutput(), c, alpha, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    v = utils.norm(axis) * height / 2
    actor.base = pos - v
    actor.top = pos + v
    return actor
コード例 #15
0
ファイル: shapes.py プロジェクト: charliekind/vtkplotter
def tube(points, r=1, c='r', alpha=1, legend=None, res=12):
    '''Build a tube of radius r along line defined py points.'''

    ppoints = vtk.vtkPoints()  # Generate the polyline
    ppoints.SetData(numpy_to_vtk(points, deep=True))
    lines = vtk.vtkCellArray()  # Create the polyline.
    lines.InsertNextCell(len(points))
    for i in range(len(points)):
        lines.InsertCellPoint(i)
    poly = vtk.vtkPolyData()
    poly.SetPoints(ppoints)
    poly.SetLines(lines)

    tuf = vtk.vtkTubeFilter()
    tuf.SetNumberOfSides(res)
    tuf.SetInputData(poly)
    tuf.SetRadius(r)
    tuf.CappingOn()
    tuf.Update()
    poly = tuf.GetOutput()
    actor = Actor(poly, c, alpha, legend=legend)
    actor.GetProperty().SetInterpolationToPhong()
    actor.base = np.array(points[0])
    actor.top = np.array(points[-1])
    return actor
コード例 #16
0
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
コード例 #17
0
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(np.rad2deg(theta))
    t.RotateZ(np.rad2deg(phi))
    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)
    settings.collectable_actors.append(actor)
    return actor
コード例 #18
0
def ellipsoid(pos=[0, 0, 0],
              axis1=[1, 0, 0],
              axis2=[0, 2, 0],
              axis3=[0, 0, 3],
              c='c',
              alpha=1,
              legend=None,
              texture=None,
              res=24):
    """
    Build a 3D ellipsoid centered at position `pos`.
    
    .. note:: `axis1` and `axis2` are only used to define sizes and one azimuth angle.
    """
    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(angle * 57.3)
    t.RotateY(theta * 57.3)
    t.RotateZ(phi * 57.3)
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(elliSource.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = Actor(pd, c=c, alpha=alpha, legend=legend, texture=texture)
    actor.GetProperty().BackfaceCullingOn()
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    return actor
コード例 #19
0
ファイル: shapes.py プロジェクト: charliekind/vtkplotter
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.

    [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/gyroscope1.py)    
    [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/turing.py)    
    '''

    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
コード例 #20
0
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
コード例 #21
0
def Lines(startPoints,
          endPoints=None,
          scale=1,
          lw=1,
          c=None,
          alpha=1,
          dotted=False):
    """
    Build the line segments between two lists of points `startPoints` and `endPoints`.
    `startPoints` can be also passed in the form ``[[point1, point2], ...]``.

    :param float scale: apply a rescaling factor to the length

    |lines|

    .. hint:: |fitspheres2.py|_
    """
    if endPoints is not None:
        startPoints = list(zip(startPoints, endPoints))

    polylns = vtk.vtkAppendPolyData()
    for twopts in startPoints:
        lineSource = vtk.vtkLineSource()
        lineSource.SetPoint1(twopts[0])

        if scale != 1:
            vers = (np.array(twopts[1]) - twopts[0]) * scale
            pt2 = np.array(twopts[0]) + vers
        else:
            pt2 = twopts[1]

        lineSource.SetPoint2(pt2)
        polylns.AddInputConnection(lineSource.GetOutputPort())
    polylns.Update()

    actor = Actor(polylns.GetOutput(), c, alpha)
    actor.GetProperty().SetLineWidth(lw)
    if dotted:
        actor.GetProperty().SetLineStipplePattern(0xF0F0)
        actor.GetProperty().SetLineStippleRepeatFactor(1)

    settings.collectable_actors.append(actor)
    return actor
コード例 #22
0
def spline(points, smooth=0.5, degree=2,
           s=2, c='b', alpha=1., nodes=False, legend=None, res=20):
    '''
    Return a vtkActor for a spline that doesnt necessarly pass exactly throught all points.

    Options:

        smooth, smoothing factor:
                0 = interpolate points exactly, 
                1 = average point positions

        degree = degree of the spline (1<degree<5)

        nodes = True shows also original the points 

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/tutorial.py)

    ![rspline](https://user-images.githubusercontent.com/32848391/35976041-15781de8-0cdf-11e8-997f-aeb725bc33cc.png)
    '''
    try:
        from scipy.interpolate import splprep, splev
    except ImportError:
        vc.printc('Warning: ..scipy not installed, using vtkCardinalSpline instead.', c=5)
        return _vtkspline(points, s, c, alpha, nodes, legend, res)

    Nout = len(points)*res  # Number of points on the spline
    points = np.array(points)

    minx, miny, minz = np.min(points, axis=0)
    maxx, maxy, maxz = np.max(points, axis=0)
    maxb = max(maxx-minx, maxy-miny, maxz-minz)
    smooth *= maxb/2  # must be in absolute units

    x, y, z = points[:, 0], points[:, 1], points[:, 2]
    tckp, _ = splprep([x, y, z], task=0, s=smooth, k=degree)  # find the knots
    # evaluate spline, including interpolated points:
    xnew, ynew, znew = splev(np.linspace(0, 1, Nout), tckp)

    ppoints = vtk.vtkPoints()  # Generate the polyline for the spline
    profileData = vtk.vtkPolyData()
    ppoints.SetData(numpy_to_vtk( list(zip(xnew, ynew, znew)), deep=True))
    lines = vtk.vtkCellArray()  # Create the polyline
    lines.InsertNextCell(Nout)
    for i in range(Nout):
        lines.InsertCellPoint(i)
    profileData.SetPoints(ppoints)
    profileData.SetLines(lines)
    actline = Actor(profileData, c=c, alpha=alpha, legend=legend)
    actline.GetProperty().SetLineWidth(s)
    if nodes:
        actnodes = vs.points(points, r=5, c=c, alpha=alpha)
        ass = Assembly([actline, actnodes], legend=legend)
        return ass
    else:
        return actline
コード例 #23
0
def arrow(startPoint,
          endPoint,
          c='r',
          s=None,
          alpha=1,
          legend=None,
          texture=None,
          res=12,
          rwSize=(800, 800)):
    '''
    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.
    '''
    axis = np.array(endPoint) - np.array(startPoint)
    length = np.linalg.norm(axis)
    if not length:
        return None
    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(phi * 57.3)
    t.RotateY(theta * 57.3)
    t.RotateY(-90)  # put it along Z
    if s:
        w, h = rwSize
        sz = (w + h) / 2 * 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, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(startPoint)
    actor.DragableOff()
    actor.PickableOff()
    actor.base = np.array(startPoint)
    actor.top = np.array(endPoint)
    return actor
コード例 #24
0
    def _buildactor(d):
        vertices = d['points']
        cells = None
        lines = None
        keys = d.keys()
        if 'cells' in keys:
            cells = d['cells']
        if 'lines' in keys:
            lines = d['lines']

        poly = utils.buildPolyData(vertices, cells, lines)
        act = Actor(poly)
        loadcommon(act, d)

        act.mapper.ScalarVisibilityOff()
        if 'celldata' in keys:
            for csc, cscname in d['celldata']:
                act.addCellScalars(csc, cscname)
                if not 'normal' in cscname.lower():
                    act.scalars(cscname)  # activate
        if 'pointdata' in keys:
            for psc, pscname in d['pointdata']:
                act.addPointScalars(psc, pscname)
                if not 'normal' in pscname.lower():
                    act.scalars(pscname)  # activate

        prp = act.GetProperty()
        if 'specular' in keys: prp.SetSpecular(d['specular'])
        if 'specularpower' in keys: prp.SetSpecularPower(d['specularpower'])
        if 'specularcolor' in keys: prp.SetSpecularColor(d['specularcolor'])
        if 'shading' in keys: prp.SetInterpolation(d['shading'])
        if 'alpha' in keys: prp.SetOpacity(d['alpha'])
        if 'opacity' in keys: prp.SetOpacity(d['opacity'])  # synomym
        if 'pointsize' in keys and d['pointsize']:
            prp.SetPointSize(d['pointsize'])
        if 'texture' in keys and d['texture']: act.texture(d['texture'])
        if 'linewidth' in keys and d['linewidth']:
            act.lineWidth(d['linewidth'])
        if 'linecolor' in keys and d['linecolor']:
            act.lineColor(d['linecolor'])
        if 'representation' in keys: prp.SetRepresentation(d['representation'])
        if 'color' in keys and d['color']: act.color(d['color'])
        if 'backColor' in keys and d['backColor']:
            act.backColor(d['backColor'])

        if 'activedata' in keys and d['activedata'] is not None:
            act.mapper.ScalarVisibilityOn()
            if d['activedata'][0] == 'celldata':
                poly.GetCellData().SetActiveScalars(d['activedata'][1])
            if d['activedata'][0] == 'pointdata':
                poly.GetPointData().SetActiveScalars(d['activedata'][1])

        return act
コード例 #25
0
def hyperboloid(pos=[0, 0, 0],
                a2=1,
                value=0.5,
                height=1,
                axis=[0, 0, 1],
                c='magenta',
                alpha=1,
                legend=None,
                texture=None,
                res=100):
    '''
    Build a hyperboloid of specified aperture `a2` and `height`, centered at `pos`.
    
    Full volumetric expression is:
        :math:`F(x,y,z)=a_0x^2+a_1y^2+a_2z^2+a_3xy+a_4yz+a_5xz+ a_6x+a_7y+a_8z+a_9`

    .. hint:: Example: `mesh_bands.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/mesh_bands.py>`_

        .. image:: https://user-images.githubusercontent.com/32848391/51211548-26a78b00-1916-11e9-9306-67b677d1be3a.png
    '''
    q = vtk.vtkQuadric()
    q.SetCoefficients(2, 2, -1 / a2, 0, 0, 0, 0, 0, 0, 0)
    # F(x,y,z) = a0*x^2 + a1*y^2 + a2*z^2
    #         + a3*x*y + a4*y*z + a5*x*z
    #         + a6*x   + a7*y   + a8*z  +a9
    sample = vtk.vtkSampleFunction()
    sample.SetSampleDimensions(res, res, res)
    sample.SetImplicitFunction(q)

    contours = vtk.vtkContourFilter()
    contours.SetInputConnection(sample.GetOutputPort())
    contours.GenerateValues(1, value, value)
    contours.Update()

    axis = np.array(axis) / np.linalg.norm(axis)
    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)
    t.Scale(1, 1, height)
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(contours.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = Actor(pd, c=c, alpha=alpha, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.GetMapper().ScalarVisibilityOff()
    actor.SetPosition(pos)
    return actor
コード例 #26
0
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|_
    """
    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 utils.isSequence(c[0]) and len(c[0]) == 3:
        return _colorPoints(plist, c, r, alpha)

    n = len(plist)  # refresh

    sourcePoints = vtk.vtkPoints()
    sourceVertices = vtk.vtkCellArray()
    is3d = len(plist[0]) > 2
    if is3d:
        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])
    return actor
コード例 #27
0
ファイル: shapes.py プロジェクト: charliekind/vtkplotter
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
コード例 #28
0
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
コード例 #29
0
def paraboloid(pos=[0, 0, 0],
               r=1,
               height=1,
               axis=[0, 0, 1],
               c='cyan',
               alpha=1,
               legend=None,
               texture=None,
               res=100):
    '''
    Build a paraboloid of specified height and radius `r`, centered at `pos`.
    
    .. note::
        Full volumetric expression is:
            :math:`F(x,y,z)=a_0x^2+a_1y^2+a_2z^2+a_3xy+a_4yz+a_5xz+ a_6x+a_7y+a_8z+a_9`
    
        .. image:: https://user-images.githubusercontent.com/32848391/51211547-260ef480-1916-11e9-95f6-4a677e37e355.png
    '''
    quadric = vtk.vtkQuadric()
    quadric.SetCoefficients(1, 1, 0, 0, 0, 0, 0, 0, height / 4, 0)
    # F(x,y,z) = a0*x^2 + a1*y^2 + a2*z^2
    #         + a3*x*y + a4*y*z + a5*x*z
    #         + a6*x   + a7*y   + a8*z  +a9
    sample = vtk.vtkSampleFunction()
    sample.SetSampleDimensions(res, res, res)
    sample.SetImplicitFunction(quadric)

    contours = vtk.vtkContourFilter()
    contours.SetInputConnection(sample.GetOutputPort())
    contours.GenerateValues(1, .01, .01)
    contours.Update()

    axis = np.array(axis) / np.linalg.norm(axis)
    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)
    t.Scale(r, r, r)
    tf = vtk.vtkTransformPolyDataFilter()
    tf.SetInputData(contours.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = Actor(pd, c=c, alpha=alpha, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.GetMapper().ScalarVisibilityOff()
    actor.SetPosition(pos)
    return actor
コード例 #30
0
def _vtkspline(points, s, c, alpha, nodes, legend, res):
    numberOfOutputPoints = len(points)*res  # Number of points on the spline
    numberOfInputPoints = len(points)  # One spline for each direction.
    aSplineX = vtk.vtkCardinalSpline()  # interpolate the x values
    aSplineY = vtk.vtkCardinalSpline()  # interpolate the y values
    aSplineZ = vtk.vtkCardinalSpline()  # interpolate the z values

    inputPoints = vtk.vtkPoints()
    for i in range(0, numberOfInputPoints):
        x = points[i][0]
        y = points[i][1]
        z = points[i][2]
        aSplineX.AddPoint(i, x)
        aSplineY.AddPoint(i, y)
        aSplineZ.AddPoint(i, z)
        inputPoints.InsertPoint(i, x, y, z)

    inputData = vtk.vtkPolyData()
    inputData.SetPoints(inputPoints)
    points = vtk.vtkPoints()
    profileData = vtk.vtkPolyData()
    for i in range(numberOfOutputPoints):
        t = (numberOfInputPoints-1.)/(numberOfOutputPoints-1.)*i
        x, y, z = aSplineX.Evaluate(
            t), aSplineY.Evaluate(t), aSplineZ.Evaluate(t)
        points.InsertPoint(i, x, y, z)

    lines = vtk.vtkCellArray()  # Create the polyline.
    lines.InsertNextCell(numberOfOutputPoints)
    for i in range(numberOfOutputPoints):
        lines.InsertCellPoint(i)

    profileData.SetPoints(points)
    profileData.SetLines(lines)
    actline = Actor(profileData, c=c, alpha=alpha, legend=legend)
    actline.GetProperty().SetLineWidth(s)
    actline.GetProperty().SetInterpolationToPhong()
    return actline