Exemple #1
0
def subdivide(actor, N=1, method=0, legend=None):
    '''
    Increase the number of points in actor surface
        N = number of subdivisions
        method = 0, Loop
        method = 1, Linear
        method = 2, Adaptive
        method = 3, Butterfly
    '''
    triangles = vtk.vtkTriangleFilter()
    vu.setInput(triangles, vu.polydata(actor))
    triangles.Update()
    originalMesh = triangles.GetOutput()
    if method == 0: sdf = vtk.vtkLoopSubdivisionFilter()
    elif method == 1: sdf = vtk.vtkLinearSubdivisionFilter()
    elif method == 2: sdf = vtk.vtkAdaptiveSubdivisionFilter()
    elif method == 3: sdf = vtk.vtkButterflySubdivisionFilter()
    else:
        vio.printc('Error in subdivide: unknown method.', 'r')
        exit(1)
    if method != 2: sdf.SetNumberOfSubdivisions(N)
    vu.setInput(sdf, originalMesh)
    sdf.Update()
    out = sdf.GetOutput()
    if legend is None and hasattr(actor, 'legend'): legend = actor.legend
    sactor = vu.makeActor(out, legend=legend)
    sactor.GetProperty().SetOpacity(actor.GetProperty().GetOpacity())
    sactor.GetProperty().SetColor(actor.GetProperty().GetColor())
    sactor.GetProperty().SetRepresentation(
        actor.GetProperty().GetRepresentation())
    return sactor
Exemple #2
0
def decimate(actor, fraction=0.5, N=None, verbose=True, boundaries=True):
    '''
    Downsample the number of vertices in a mesh.
        fraction gives the desired target of reduction. 
        E.g. fraction=0.1
             leaves 10% of the original nr of vertices.
    '''
    poly = vu.polydata(actor, True)
    if N:  # N = desired number of points
        Np = poly.GetNumberOfPoints()
        fraction = float(N) / Np
        if fraction >= 1: return actor

    decimate = vtk.vtkDecimatePro()
    vu.setInput(decimate, poly)
    decimate.SetTargetReduction(1. - fraction)
    decimate.PreserveTopologyOff()
    if boundaries: decimate.BoundaryVertexDeletionOn()
    else: decimate.BoundaryVertexDeletionOff()
    decimate.Update()
    if verbose:
        print('Input nr. of pts:', poly.GetNumberOfPoints(), end='')
        print(' output:', decimate.GetOutput().GetNumberOfPoints())
    mapper = actor.GetMapper()
    vu.setInput(mapper, decimate.GetOutput())
    mapper.Update()
    actor.Modified()
    if hasattr(actor, 'poly'): actor.poly = decimate.GetOutput()
    return actor  # return same obj for concatenation
Exemple #3
0
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:
        vio.printc("Error in ellipsoid(): scipy not installed. Skip.", 1)
        return None
    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
Exemple #4
0
def removeOutliers(points, radius, c='k', alpha=1, legend=None):
    '''
    Remove outliers from a cloud of points within radius search
    '''
    isactor = False
    if isinstance(points, vtk.vtkActor):
        isactor = True
        poly = vu.polydata(points)
    else:
        src = vtk.vtkPointSource()
        src.SetNumberOfPoints(len(points))
        src.Update()
        vpts = src.GetOutput().GetPoints()
        for i, p in enumerate(points):
            vpts.SetPoint(i, p)
        poly = src.GetOutput()

    removal = vtk.vtkRadiusOutlierRemoval()
    vu.setInput(removal, poly)

    removal.SetRadius(radius)
    removal.SetNumberOfNeighbors(5)
    removal.GenerateOutliersOff()
    removal.Update()
    rpoly = removal.GetOutput()
    print("# of removed outlier points: ", removal.GetNumberOfPointsRemoved(),
          '/', poly.GetNumberOfPoints())
    outpts = []
    for i in range(rpoly.GetNumberOfPoints()):
        outpts.append(list(rpoly.GetPoint(i)))
    outpts = np.array(outpts)
    if not isactor: return outpts

    actor = vs.points(outpts, c=c, alpha=alpha, legend=legend)
    return actor  # return same obj for concatenation
Exemple #5
0
def recoSurface(points,
                bins=256,
                c='gold',
                alpha=1,
                wire=False,
                bc='t',
                edges=False,
                legend=None):
    '''
    Surface reconstruction from sparse points.
    '''

    if isinstance(points, vtk.vtkActor): points = vu.coordinates(points)
    N = len(points)
    if N < 50:
        print('recoSurface: Use at least 50 points.')
        return None
    points = np.array(points)

    ptsSource = vtk.vtkPointSource()
    ptsSource.SetNumberOfPoints(N)
    ptsSource.Update()
    vpts = ptsSource.GetOutput().GetPoints()
    for i, p in enumerate(points):
        vpts.SetPoint(i, p)
    polyData = ptsSource.GetOutput()

    distance = vtk.vtkSignedDistance()
    f = 0.1
    x0, x1, y0, y1, z0, z1 = polyData.GetBounds()
    distance.SetBounds(x0 - (x1 - x0) * f, x1 + (x1 - x0) * f,
                       y0 - (y1 - y0) * f, y1 + (y1 - y0) * f,
                       z0 - (z1 - z0) * f, z1 + (z1 - z0) * f)
    if polyData.GetPointData().GetNormals():
        distance.SetInputData(polyData)
        vu.setInput(distance, polyData)
    else:
        print('Recalculating normals for', N, 'points')
        normals = vtk.vtkPCANormalEstimation()
        vu.setInput(normals, polyData)
        normals.SetSampleSize(int(N / 50))
        normals.SetNormalOrientationToGraphTraversal()
        distance.SetInputConnection(normals.GetOutputPort())
    radius = vu.diagonalSize(polyData) / bins * 5
    distance.SetRadius(radius)
    distance.SetDimensions(bins, bins, bins)
    distance.Update()

    print('Calculating mesh from points with R =', radius)
    surface = vtk.vtkExtractSurface()
    surface.SetRadius(radius * .99)
    surface.HoleFillingOn()
    surface.ComputeNormalsOff()
    surface.ComputeGradientsOff()
    surface.SetInputConnection(distance.GetOutputPort())
    surface.Update()
    return vu.makeActor(surface.GetOutput(), c, alpha, wire, bc, edges, legend)
def arrow(startPoint,
          endPoint,
          c,
          s=None,
          alpha=1,
          legend=None,
          texture=None,
          res=12,
          rwSize=None):
    '''Build a 3D arrow from startPoint to endPoint of section size s,
    expressed as the fraction of the window size.
    If s=None the arrow is scaled proportionally to its length.'''

    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()
    vu.setInput(tf, arr.GetOutput())
    tf.SetTransform(t)
    tf.Update()

    actor = vu.makeActor(tf.GetOutput(),
                         c,
                         alpha,
                         legend=legend,
                         texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(startPoint)
    actor.DragableOff()
    actor.PickableOff()
    setattr(actor, 'base', np.array(startPoint))
    setattr(actor, 'top', np.array(endPoint))
    return actor
def line(p0,
         p1=None,
         lw=1,
         tube=False,
         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.
        
        if tube=True, lines are rendered as tubes of radius lw
    '''

    #detect if user is passing a list of points:
    if vu.isSequence(p0[0]):
        ppoints = vtk.vtkPoints()  # Generate the polyline
        poly = vtk.vtkPolyData()
        for i in range(len(p0)):
            p = p0[i]
            ppoints.InsertPoint(i, p[0], p[1], p[2])
        lines = vtk.vtkCellArray()  # Create the polyline.
        lines.InsertNextCell(len(p0))
        for i in range(len(p0)):
            lines.InsertCellPoint(i)
        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()

    if tube:
        tuf = vtk.vtkTubeFilter()
        tuf.SetNumberOfSides(12)
        #tuf.CappingOn()
        vu.setInput(tuf, poly)
        tuf.SetRadius(lw)
        tuf.Update()
        poly = tuf.GetOutput()
        actor = vu.makeActor(poly, c, alpha, legend=legend)
        actor.GetProperty().SetInterpolationToPhong()
    else:
        actor = vu.makeActor(poly, c, alpha, legend=legend)
        actor.GetProperty().SetLineWidth(lw)
        if dotted:
            actor.GetProperty().SetLineStipplePattern(0xf0f0)
            actor.GetProperty().SetLineStippleRepeatFactor(1)
    setattr(actor, 'base', np.array(p0))
    setattr(actor, 'top', np.array(p1))
    return actor
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()
    vu.setInput(tf, ps.GetOutputPort())
    tf.Update()

    mapper = vtk.vtkPolyDataMapper()
    vu.setInput(mapper, tf.GetOutputPort())
    if followcam:  #follow cam
        actor = vtk.vtkFollower()
        actor.SetCamera(camera)
        if not camera:
            vu.printc('Warning: vtkCamera does not yet exist for polygon', 5)
    else:
        actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(vc.getColor(c))
    # check if color string contains a float, in this case ignore alpha
    al = vc.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(vc.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    if texture: vu.assignTexture(actor, texture)
    vu.assignPhysicsMethods(actor)
    vu.assignConvenienceMethods(actor, legend)
    actor.SetPosition(pos)
    return actor
Exemple #9
0
 def cwkeypress(obj, event):
     key = obj.GetKeySym()
     if key == "q" or key == "space" or key == "Return":
         iren.ExitCallback()
     elif key == "X":
         confilter = vtk.vtkPolyDataConnectivityFilter()
         vu.setInput(confilter, clipper.GetOutput())
         confilter.SetExtractionModeToLargestRegion()
         confilter.Update()
         cpd = vtk.vtkCleanPolyData()
         vu.setInput(cpd, confilter.GetOutput())
         cpd.Update()
         vio.write(cpd.GetOutput(), outputname)
     elif key == "Escape":
         exit(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=50):
    '''
    Build a hyperboloid of specified aperture a2 and height, centered at pos.
    '''
    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()
    vu.setInput(tf, contours.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = vu.makeActor(pd, c=c, alpha=alpha, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.GetMapper().ScalarVisibilityOff()
    actor.SetPosition(pos)
    return actor
Exemple #11
0
def cluster(points, radius, legend=None):
    '''
    Clustering of points in space.
    radius, is the radius of local search.
    Individual subsets can be accessed through actor.clusters
    '''
    if isinstance(points, vtk.vtkActor):
        poly = vu.polydata(points)
    else:
        src = vtk.vtkPointSource()
        src.SetNumberOfPoints(len(points))
        src.Update()
        vpts = src.GetOutput().GetPoints()
        for i, p in enumerate(points):
            vpts.SetPoint(i, p)
        poly = src.GetOutput()

    cluster = vtk.vtkEuclideanClusterExtraction()
    vu.setInput(cluster, poly)
    cluster.SetExtractionModeToAllClusters()
    cluster.SetRadius(radius)
    cluster.ColorClustersOn()
    cluster.Update()

    idsarr = cluster.GetOutput().GetPointData().GetArray('ClusterId')
    Nc = cluster.GetNumberOfExtractedClusters()

    sets = [[] for i in range(Nc)]
    for i, p in enumerate(points):
        sets[idsarr.GetValue(i)].append(p)

    acts = []
    for i, aset in enumerate(sets):
        acts.append(vs.points(aset, c=i))

    actor = vu.makeAssembly(acts, legend=legend)
    setattr(actor, 'clusters', sets)
    print('Nr. of extracted clusters', Nc)
    if Nc > 10: print('First ten:')
    for i in range(Nc):
        if i > 9:
            print('...')
            break
        print('Cluster #' + str(i) + ',  N =', len(sets[i]))
    print('Access individual clusters through attribute: actor.cluster')
    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 actor of specified nr of coils between startPoint and endPoint
    '''
    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 = vu.makePolyData(pts)
    t = vtk.vtkTransform()
    t.RotateZ(phi * 57.3)
    t.RotateY(theta * 57.3)
    tf = vtk.vtkTransformPolyDataFilter()
    vu.setInput(tf, sp)
    tf.SetTransform(t)
    tf.Update()
    tuf = vtk.vtkTubeFilter()
    tuf.SetNumberOfSides(12)
    tuf.CappingOn()
    vu.setInput(tuf, tf.GetOutput())
    if not thickness: thickness = r / 10
    tuf.SetRadius(thickness)
    tuf.Update()
    poly = tuf.GetOutput()
    actor = vu.makeActor(poly, c, alpha, legend=legend, texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(startPoint)
    setattr(actor, 'base', np.array(startPoint))
    setattr(actor, 'top', np.array(endPoint))
    return actor
def ring(pos=[0, 0, 0],
         r=1,
         thickness=0.1,
         axis=[0, 0, 1],
         c='khaki',
         alpha=1,
         wire=False,
         legend=None,
         texture=None,
         res=30):
    '''
    Build a torus of specified outer radius r internal radius thickness, centered at pos.
    '''
    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(theta * 57.3)
    t.RotateZ(phi * 57.3)
    tf = vtk.vtkTransformPolyDataFilter()
    vu.setInput(tf, pfs.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = vu.makeActor(pd,
                         c=c,
                         alpha=alpha,
                         wire=wire,
                         legend=legend,
                         texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    return actor
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.
    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()
    vu.setInput(tf, elliSource.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = vu.makeActor(pd, c=c, alpha=alpha, legend=legend, texture=texture)
    actor.GetProperty().BackfaceCullingOn()
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    return actor
Exemple #15
0
def cutPlane(actor, origin=(0, 0, 0), normal=(1, 0, 0), showcut=True):
    '''
    Takes actor and cuts it with the plane defined by a point
    and a normal. 
        showcut  = shows the cut away part as thin wireframe
        showline = marks with a thick line the cut
    '''
    plane = vtk.vtkPlane()
    plane.SetOrigin(origin)
    plane.SetNormal(normal)
    poly = vu.polydata(actor)
    clipper = vtk.vtkClipPolyData()
    vu.setInput(clipper, poly)
    clipper.SetClipFunction(plane)
    clipper.GenerateClippedOutputOn()
    clipper.SetValue(0.)
    clipper.Update()
    if hasattr(actor, 'GetProperty'):
        alpha = actor.GetProperty().GetOpacity()
        c = actor.GetProperty().GetColor()
        bf = actor.GetBackfaceProperty()
    else:
        alpha = 1
        c = 'gold'
        bf = None
    leg = None
    if hasattr(actor, 'legend'): leg = actor.legend
    clipActor = vu.makeActor(clipper.GetOutput(), c=c, alpha=alpha, legend=leg)
    clipActor.SetBackfaceProperty(bf)

    acts = [clipActor]
    if showcut:
        cpoly = clipper.GetClippedOutput()
        restActor = vu.makeActor(cpoly, c=c, alpha=0.05, wire=1)
        acts.append(restActor)

    if len(acts) > 1:
        asse = vu.makeAssembly(acts)
        return asse
    else:
        return clipActor
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 * 4)
    ps.Update()
    tr = vtk.vtkTriangleFilter()
    vu.setInput(tr, ps.GetOutputPort())
    tr.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()
    vu.setInput(tf, tr.GetOutput())
    tf.SetTransform(t)
    tf.Update()

    pd = tf.GetOutput()
    mapper = vtk.vtkPolyDataMapper()
    vu.setInput(mapper, pd)

    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(vc.getColor(c))
    # check if color string contains a float, in this case ignore alpha
    al = vc.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(vc.getColor(bc))
        backProp.SetOpacity(alpha)
        actor.SetBackfaceProperty(backProp)
    if texture: vu.assignTexture(actor, texture)
    vu.assignPhysicsMethods(actor)
    vu.assignConvenienceMethods(actor, legend)
    actor.SetPosition(pos)
    return actor
Exemple #17
0
def align(source, target, iters=100, legend=None):
    '''
    Return a copy of source actor which is aligned to
    target actor through vtkIterativeClosestPointTransform() method.
    '''
    sprop = source.GetProperty()
    source = vu.polydata(source)
    target = vu.polydata(target)
    icp = vtk.vtkIterativeClosestPointTransform()
    icp.SetSource(source)
    icp.SetTarget(target)
    icp.SetMaximumNumberOfIterations(iters)
    icp.StartByMatchingCentroidsOn()
    icp.Update()
    icpTransformFilter = vtk.vtkTransformPolyDataFilter()
    vu.setInput(icpTransformFilter, source)
    icpTransformFilter.SetTransform(icp)
    icpTransformFilter.Update()
    poly = icpTransformFilter.GetOutput()
    actor = vu.makeActor(poly, legend=legend)
    actor.SetProperty(sprop)
    setattr(actor, 'transform', icp.GetLandmarkTransform())
    return actor
def _colorPoints(plist, cols, r, alpha, legend):
    if len(plist) > len(cols):
        vu.printc(("Mismatch in colorPoints()", len(plist), len(cols)), 1)
        exit()
    if len(plist) != len(cols):
        vu.printc(
            ("Warning: mismatch in colorPoints()", len(plist), len(cols)))
    src = vtk.vtkPointSource()
    src.SetNumberOfPoints(len(plist))
    src.Update()
    vertexFilter = vtk.vtkVertexGlyphFilter()
    vu.setInput(vertexFilter, src.GetOutput())
    vertexFilter.Update()
    pd = vertexFilter.GetOutput()
    ucols = vtk.vtkUnsignedCharArray()
    ucols.SetNumberOfComponents(3)
    ucols.SetName("RGB")
    for i, p in enumerate(plist):
        pd.GetPoints().SetPoint(i, p)
        c = np.array(vc.getColor(cols[i])) * 255
        if vu.vtkMV:
            ucols.InsertNextTuple3(c[0], c[1], c[2])
        else:
            ucols.InsertNextTupleValue(c)
    pd.GetPointData().SetScalars(ucols)
    mapper = vtk.vtkPolyDataMapper()
    vu.setInput(mapper, pd)
    mapper.ScalarVisibilityOn()
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetInterpolationToFlat()
    # check if color string contains a float, in this case ignore alpha
    al = vc.getAlpha(c)
    if al: alpha = al
    actor.GetProperty().SetOpacity(alpha)
    actor.GetProperty().SetPointSize(r)
    return actor
Exemple #19
0
def delaunay2D(plist,
               tol=None,
               c='gold',
               alpha=0.5,
               wire=False,
               bc=None,
               edges=False,
               legend=None,
               texture=None):
    '''
    Create a mesh from points in the XY plane.
    '''
    src = vtk.vtkPointSource()
    src.SetNumberOfPoints(len(plist))
    src.Update()
    pd = src.GetOutput()
    for i, p in enumerate(plist):
        pd.GetPoints().SetPoint(i, p)
    delny = vtk.vtkDelaunay2D()
    vu.setInput(delny, pd)
    if tol: delny.SetTolerance(tol)
    delny.Update()
    return vu.makeActor(delny.GetOutput(), c, alpha, wire, bc, edges, legend,
                        texture)
def box(pos=[0, 0, 0],
        length=1,
        width=2,
        height=3,
        normal=(0, 0, 1),
        c='g',
        alpha=1,
        wire=False,
        legend=None,
        texture=None):
    '''Build a box of dimensions x=length, y=width and z=height
    oriented along vector normal'''
    src = vtk.vtkCubeSource()
    src.SetXLength(length)
    src.SetYLength(width)
    src.SetZLength(height)
    src.Update()
    poly = src.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()
    vu.setInput(tf, poly)
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = vu.makeActor(pd, c, alpha, wire, legend=legend, texture=texture)
    actor.SetPosition(pos)
    return actor
Exemple #21
0
def fxy(z='sin(3*x)*log(x-y)/3',
        x=[0, 3],
        y=[0, 3],
        zlimits=[None, None],
        showNan=True,
        zlevels=10,
        wire=False,
        c='b',
        bc='aqua',
        alpha=1,
        legend=True,
        texture=None,
        res=100):
    '''
    Build a surface representing the 3D function specified as a string
    or as a reference to an external function.
    Red points indicate where the function does not exist (showNan).

    zlevels will draw the specified number of z-levels contour lines.

    Examples:
        vp = plotter.vtkPlotter()
        vp.fxy('sin(3*x)*log(x-y)/3')
        or
        def z(x,y): return math.sin(x*y)
        vp.fxy(z) # or equivalently:
        vp.fxy(lambda x,y: math.sin(x*y))
    '''
    if isinstance(z, str):
        try:
            z = z.replace('math.', '').replace('np.', '')
            namespace = locals()
            code = "from math import*\ndef zfunc(x,y): return " + z
            exec(code, namespace)
            z = namespace['zfunc']
        except:
            vio.printc('Syntax Error in fxy()', 1)
            return None

    ps = vtk.vtkPlaneSource()
    ps.SetResolution(res, res)
    ps.SetNormal([0, 0, 1])
    ps.Update()
    poly = ps.GetOutput()
    dx = x[1] - x[0]
    dy = y[1] - y[0]
    todel, nans = [], []

    if zlevels:
        tf = vtk.vtkTriangleFilter()
        vu.setInput(tf, poly)
        tf.Update()
        poly = tf.GetOutput()

    for i in range(poly.GetNumberOfPoints()):
        px, py, _ = poly.GetPoint(i)
        xv = (px + .5) * dx + x[0]
        yv = (py + .5) * dy + y[0]
        try:
            zv = z(xv, yv)
            poly.GetPoints().SetPoint(i, [xv, yv, zv])
        except:
            todel.append(i)
            nans.append([xv, yv, 0])

    if len(todel):
        cellIds = vtk.vtkIdList()
        poly.BuildLinks()

        for i in todel:
            poly.GetPointCells(i, cellIds)
            for j in range(cellIds.GetNumberOfIds()):
                poly.DeleteCell(cellIds.GetId(j))  #flag cell

        poly.RemoveDeletedCells()
        cl = vtk.vtkCleanPolyData()
        vu.setInput(cl, poly)
        cl.Update()
        poly = cl.GetOutput()

    if not poly.GetNumberOfPoints():
        vio.printc('Function is not real in the domain', 1)
        return vtk.vtkActor()

    if zlimits[0]:
        a = cutPlane(poly, (0, 0, zlimits[0]), (0, 0, 1), False)
        poly = vu.polydata(a)
    if zlimits[1]:
        a = cutPlane(poly, (0, 0, zlimits[1]), (0, 0, -1), False)
        poly = vu.polydata(a)

    if c is None:
        elev = vtk.vtkElevationFilter()
        vu.setInput(elev, poly)
        elev.Update()
        poly = elev.GetOutput()

    actor = vu.makeActor(poly,
                         c=c,
                         bc=bc,
                         alpha=alpha,
                         wire=wire,
                         legend=legend,
                         texture=texture)
    acts = [actor]
    if zlevels:
        elevation = vtk.vtkElevationFilter()
        vu.setInput(elevation, poly)
        bounds = poly.GetBounds()
        elevation.SetLowPoint(0, 0, bounds[4])
        elevation.SetHighPoint(0, 0, bounds[5])
        elevation.Update()
        bcf = vtk.vtkBandedPolyDataContourFilter()
        vu.setInput(bcf, elevation.GetOutput())
        bcf.SetScalarModeToValue()
        bcf.GenerateContourEdgesOn()
        bcf.GenerateValues(zlevels, elevation.GetScalarRange())
        bcf.Update()
        zpoly = bcf.GetContourEdgesOutput()
        zbandsact = vu.makeActor(zpoly, c='k', alpha=alpha)
        zbandsact.GetProperty().SetLineWidth(1.5)
        acts.append(zbandsact)

    if showNan and len(todel):
        bb = actor.GetBounds()
        zm = (bb[4] + bb[5]) / 2
        nans = np.array(nans) + [0, 0, zm]
        nansact = vs.points(nans, c='red', alpha=alpha / 2)
        acts.append(nansact)

    if len(acts) > 1:
        asse = vu.makeAssembly(acts)
        return asse
    else:
        return actor
def spheres(centers,
            r=1,
            c='r',
            alpha=1,
            wire=False,
            legend=None,
            texture=None,
            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.
    '''

    cisseq = False
    if vu.isSequence(c): cisseq = True

    if cisseq:
        if len(centers) > len(c):
            vu.printc(("Mismatch in spheres() colors", len(centers), len(c)),
                      1)
            exit()
        if len(centers) != len(c):
            vu.printc(("Warning: mismatch in spheres() colors", len(centers),
                       len(c)))

    risseq = False
    if vu.isSequence(r): risseq = True

    if risseq:
        if len(centers) > len(r):
            vu.printc(("Mismatch in spheres() radius", len(centers), len(r)),
                      1)
            exit()
        if len(centers) != len(r):
            vu.printc(("Warning: mismatch in spheres() radius", len(centers),
                       len(r)))
    if cisseq and risseq:
        vu.printc("Limitation: c and r cannot be both sequences.", 1)
        exit()

    src = vtk.vtkSphereSource()
    if not risseq: src.SetRadius(r)
    src.SetPhiResolution(res)
    src.SetThetaResolution(res)
    src.Update()
    glyph = vtk.vtkGlyph3D()
    glyph.SetSourceConnection(src.GetOutputPort())

    psrc = vtk.vtkPointSource()
    psrc.SetNumberOfPoints(len(centers))
    psrc.Update()
    pd = psrc.GetOutput()
    vpts = pd.GetPoints()

    if cisseq:
        glyph.SetColorModeToColorByScalar()
        ucols = vtk.vtkUnsignedCharArray()
        ucols.SetNumberOfComponents(3)
        ucols.SetName("colors")
        for i, p in enumerate(centers):
            vpts.SetPoint(i, p)
            cc = np.array(vc.getColor(c[i])) * 255
            if vu.vtkMV:
                ucols.InsertNextTuple3(cc[0], cc[1], cc[2])
            else:
                ucols.InsertNextTupleValue(cc)
            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)

    vu.setInput(glyph, pd)
    glyph.Update()

    mapper = vtk.vtkPolyDataMapper()
    vu.setInput(mapper, glyph.GetOutput())
    if cisseq: mapper.ScalarVisibilityOn()
    else: mapper.ScalarVisibilityOff()
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetInterpolationToPhong()
    # check if color string contains a float, in this case ignore alpha
    al = vc.getAlpha(c)
    if al: alpha = al
    actor.GetProperty().SetOpacity(alpha)
    if not cisseq:
        if texture is not None:
            vu.assignTexture(actor, texture)
            mapper.ScalarVisibilityOff()
        else:
            actor.GetProperty().SetColor(vc.getColor(c))
    vu.assignConvenienceMethods(actor, legend)
    return actor
def cylinder(pos=[0, 0, 0],
             r=1,
             height=1,
             axis=[0, 0, 1],
             c='teal',
             wire=0,
             alpha=1,
             edges=False,
             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 vu.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 = vu.norm(axis)
    else:
        axis = vu.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()
    vu.setInput(tf, cyl.GetOutput())
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()

    actor = vu.makeActor(pd,
                         c,
                         alpha,
                         wire,
                         edges=edges,
                         legend=legend,
                         texture=texture)
    actor.GetProperty().SetInterpolationToPhong()
    actor.SetPosition(pos)
    setattr(actor, 'base', base)
    setattr(actor, 'top', top)
    return actor
Exemple #24
0
def cutterWidget(obj,
                 outputname='clipped.vtk',
                 c=(0.2, 0.2, 1),
                 alpha=1,
                 bc=(0.7, 0.8, 1),
                 legend=None):
    '''Pop up a box widget to cut parts of actor. Return largest part.'''

    apd = vu.polydata(obj)

    planes = vtk.vtkPlanes()
    planes.SetBounds(apd.GetBounds())

    clipper = vtk.vtkClipPolyData()
    vu.setInput(clipper, apd)
    clipper.SetClipFunction(planes)
    clipper.InsideOutOn()
    clipper.GenerateClippedOutputOn()

    # check if color string contains a float, in this case ignore alpha
    al = vc.getAlpha(c)
    if al: alpha = al

    act0Mapper = vtk.vtkPolyDataMapper()  # the part which stays
    act0Mapper.SetInputConnection(clipper.GetOutputPort())
    act0 = vtk.vtkActor()
    act0.SetMapper(act0Mapper)
    act0.GetProperty().SetColor(vc.getColor(c))
    act0.GetProperty().SetOpacity(alpha)
    backProp = vtk.vtkProperty()
    backProp.SetDiffuseColor(vc.getColor(bc))
    backProp.SetOpacity(alpha)
    act0.SetBackfaceProperty(backProp)
    #act0 = makeActor(clipper.GetOutputPort())

    act0.GetProperty().SetInterpolationToFlat()
    vu.assignPhysicsMethods(act0)
    vu.assignConvenienceMethods(act0, legend)

    act1Mapper = vtk.vtkPolyDataMapper()  # the part which is cut away
    act1Mapper.SetInputConnection(clipper.GetClippedOutputPort())
    act1 = vtk.vtkActor()
    act1.SetMapper(act1Mapper)
    act1.GetProperty().SetColor(vc.getColor(c))
    act1.GetProperty().SetOpacity(alpha / 10.)
    act1.GetProperty().SetRepresentationToWireframe()
    act1.VisibilityOn()

    ren = vtk.vtkRenderer()
    ren.SetBackground(1, 1, 1)

    ren.AddActor(act0)
    ren.AddActor(act1)

    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)
    renWin.SetSize(600, 700)

    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    istyl = vtk.vtkInteractorStyleSwitch()
    istyl.SetCurrentStyleToTrackballCamera()
    iren.SetInteractorStyle(istyl)

    def SelectPolygons(vobj, event):
        vobj.GetPlanes(planes)

    boxWidget = vtk.vtkBoxWidget()
    boxWidget.OutlineCursorWiresOn()
    boxWidget.GetSelectedOutlineProperty().SetColor(1, 0, 1)
    boxWidget.GetOutlineProperty().SetColor(0.1, 0.1, 0.1)
    boxWidget.GetOutlineProperty().SetOpacity(0.8)
    boxWidget.SetPlaceFactor(1.05)
    boxWidget.SetInteractor(iren)
    vu.setInput(boxWidget, apd)
    boxWidget.PlaceWidget()
    boxWidget.AddObserver("InteractionEvent", SelectPolygons)
    boxWidget.On()

    vio.printc('\nCutterWidget:\n Move handles to cut parts of the actor', 'm')
    vio.printc(' Press q to continue, Escape to exit', 'm')
    vio.printc((" Press X to save file to", outputname), 'm')

    def cwkeypress(obj, event):
        key = obj.GetKeySym()
        if key == "q" or key == "space" or key == "Return":
            iren.ExitCallback()
        elif key == "X":
            confilter = vtk.vtkPolyDataConnectivityFilter()
            vu.setInput(confilter, clipper.GetOutput())
            confilter.SetExtractionModeToLargestRegion()
            confilter.Update()
            cpd = vtk.vtkCleanPolyData()
            vu.setInput(cpd, confilter.GetOutput())
            cpd.Update()
            vio.write(cpd.GetOutput(), outputname)
        elif key == "Escape":
            exit(0)

    iren.Initialize()
    iren.AddObserver("KeyPressEvent", cwkeypress)
    iren.Start()
    boxWidget.Off()
    return act0