Beispiel #1
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:
        vc.printc("Error in ellipsoid(): scipy not installed. Skip.",1)
        return None
    if isinstance(points, vtk.vtkActor): points=vu.coordinates(points)
    if len(points) == 0: return None
    P = np.array(points, ndmin=2, dtype=float)
    cov = np.cov(P, rowvar=0)      # covariance matrix
    U, s, R = np.linalg.svd(cov)   # singular value decomposition
    p, n = s.size, P.shape[0]
    fppf = f.ppf(pvalue, p, n-p)*(n-1)*p*(n+1)/n/(n-p) # f % point function
    ua,ub,uc = np.sqrt(s*fppf)*2   # semi-axes (largest first)
    center = np.mean(P, axis=0)    # centroid of the hyperellipsoid
    sphericity = ( ((ua-ub)/(ua+ub))**2
                 + ((ua-uc)/(ua+uc))**2
                 + ((ub-uc)/(ub+uc))**2 )/3. *4.
    elliSource = vtk.vtkSphereSource()
    elliSource.SetThetaResolution(48)
    elliSource.SetPhiResolution(48)
    matri = vtk.vtkMatrix4x4()
    matri.DeepCopy((R[0][0] *ua, R[1][0] *ub, R[2][0] *uc, center[0],
                    R[0][1] *ua, R[1][1] *ub, R[2][1] *uc, center[1],
                    R[0][2] *ua, R[1][2] *ub, R[2][2] *uc, center[2], 0,0,0,1))
    vtra = vtk.vtkTransform()
    vtra.SetMatrix(matri)
    ftra = vtk.vtkTransformFilter()
    ftra.SetTransform(vtra)
    ftra.SetInputConnection(elliSource.GetOutputPort())
    ftra.Update()
    actor_elli = vu.makeActor(ftra.GetOutput(), c, alpha, legend=legend)
    actor_elli.GetProperty().BackfaceCullingOn()
    actor_elli.GetProperty().SetInterpolationToPhong()
    if pcaAxes:
        axs = []
        for ax in ([1,0,0], [0,1,0], [0,0,1]):
            l = vtk.vtkLineSource()
            l.SetPoint1([0,0,0])
            l.SetPoint2(ax)
            l.Update()
            t = vtk.vtkTransformFilter()
            t.SetTransform(vtra)
            vu.setInput(t, l.GetOutput())
            t.Update()
            axs.append(vu.makeActor(t.GetOutput(), c, alpha))
        finact = vu.makeAssembly([actor_elli]+axs, legend=legend)
    else : 
        finact = actor_elli
    setattr(finact, 'sphericity', sphericity)
    setattr(finact, 'va', ua)
    setattr(finact, 'vb', ub)
    setattr(finact, 'vc', uc)
    return finact
Beispiel #2
0
def curvature(actor, method=1, r=1, alpha=1, lut=None, legend=None):
    '''
    Build a copy of vtkActor that contains the color coded surface
    curvature following four different ways to calculate it:
        method =  0-gaussian, 1-mean, 2-max, 3-min

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/tutorial.py)
    '''
    poly = vu.polydata(actor)
    cleaner = vtk.vtkCleanPolyData()
    vu.setInput(cleaner, poly)
    curve = vtk.vtkCurvatures()
    curve.SetInputConnection(cleaner.GetOutputPort())
    curve.SetCurvatureType(method)
    curve.InvertMeanCurvatureOn()
    curve.Update()
    print('CurvatureType set to:', method)
    if not lut:
        lut = vtk.vtkLookupTable()
        lut.SetNumberOfColors(256)
        lut.SetHueRange(0.15, 1)
        lut.SetSaturationRange(1, 1)
        lut.SetValueRange(1, 1)
        lut.SetAlphaRange(alpha, 1)
        b = poly.GetBounds()
        sc = max([b[1]-b[0], b[3]-b[2], b[5]-b[4]])
        lut.SetRange(-0.01/sc*r, 0.01/sc*r)
    cmapper = vtk.vtkPolyDataMapper()
    cmapper.SetInputConnection(curve.GetOutputPort())
    cmapper.SetLookupTable(lut)
    cmapper.SetUseLookupTableScalarRange(1)
    cactor = vtk.vtkActor()
    cactor.SetMapper(cmapper)
    return cactor
Beispiel #3
0
def align(source, target, iters=100, rigid=False, legend=None):
    '''
    Return a copy of source actor which is aligned to
    target actor through vtkIterativeClosestPointTransform() method.
    The core of the algorithm is to match each vertex in one surface with
    the closest surface point on the other, then apply the transformation 
    that modify one surface to best match the other (in the least-square sense). 

    [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/align1.py)
    [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/align2.py)
    '''
    source = vu.polydata(source)
    target = vu.polydata(target)
    icp = vtk.vtkIterativeClosestPointTransform()
    icp.SetSource(source)
    icp.SetTarget(target)
    icp.SetMaximumNumberOfIterations(iters)
    if rigid:
        icp.GetLandmarkTransform().SetModeToRigidBody()
    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)
    if hasattr(source, 'GetProperty'):
        actor.SetProperty(source.GetProperty())
    setattr(actor, 'transform', icp.GetLandmarkTransform())
    return actor
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
Beispiel #5
0
def write(obj, fileoutput):
    '''
    Write 3D object to file.
    Possile extensions are: .vtk, .ply, .obj, .stl, .byu, .vtp
    '''
    fr = fileoutput.lower()
    if '.vtk' in fr: w = vtk.vtkPolyDataWriter()
    elif '.ply' in fr: w = vtk.vtkPLYWriter()
    elif '.obj' in fr:
        w = vtk.vtkOBJExporter()
        w.SetFilePrefix(fileoutput.replace('.obj', ''))
        vc.printc('Please use write(vp.renderWin)', 3)
        w.SetInput(obj)
        w.Update()
        vc.printc("Saved file: " + fileoutput, 'g')
        return
    elif '.stl' in fr:
        w = vtk.vtkSTLWriter()
    elif '.byu' in fr or '.g' in fr:
        w = vtk.vtkBYUWriter()
    elif '.vtp' in fr:
        w = vtk.vtkXMLPolyDataWriter()
    else:
        vc.printc('Unavailable format in file ' + fileoutput, c='r')
        exit(1)
    try:
        vu.setInput(w, vu.polydata(obj, True))
        w.SetFileName(fileoutput)
        w.Write()
        vc.printc("Saved file: " + fileoutput, 'g')
    except:
        vc.printc("Error saving: " + fileoutput, 'r')
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:
        normals = vtk.vtkPCANormalEstimation()
        vu.setInput(normals, polyData)
        normals.SetSampleSize(int(N / 50))
        normals.SetNormalOrientationToGraphTraversal()
        distance.SetInputConnection(normals.GetOutputPort())
        print('Recalculating normals for', N, 'points, sample size=',
              int(N / 50))
    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
Beispiel #8
0
def loadPolyData(filename):
    '''Load a file and return a vtkPolyData object (not a vtkActor).'''
    if not os.path.exists(filename):
        vc.printc('Error in loadPolyData: Cannot find', filename, c=1)
        return None
    fl = filename.lower()
    if fl.endswith('.vtk'):
        reader = vtk.vtkPolyDataReader()
    elif fl.endswith('.ply'):
        reader = vtk.vtkPLYReader()
    elif fl.endswith('.obj'):
        reader = vtk.vtkOBJReader()
    elif fl.endswith('.stl'):
        reader = vtk.vtkSTLReader()
    elif fl.endswith('.byu') or fl.endswith('.g'):
        reader = vtk.vtkBYUReader()
    elif fl.endswith('.vtp'):
        reader = vtk.vtkXMLPolyDataReader()
    elif fl.endswith('.vts'):
        reader = vtk.vtkXMLStructuredGridReader()
    elif fl.endswith('.vtu'):
        reader = vtk.vtkXMLUnstructuredGridReader()
    elif fl.endswith('.txt'):
        reader = vtk.vtkParticleReader()  # (x y z scalar)
    elif fl.endswith('.xyz'):
        reader = vtk.vtkParticleReader()
    else:
        reader = vtk.vtkDataReader()
    reader.SetFileName(filename)
    if fl.endswith('.vts'):  # structured grid
        reader.Update()
        gf = vtk.vtkStructuredGridGeometryFilter()
        gf.SetInputConnection(reader.GetOutputPort())
        gf.Update()
        poly = gf.GetOutput()
    elif fl.endswith('.vtu'):  # unstructured grid
        reader.Update()
        gf = vtk.vtkGeometryFilter()
        gf.SetInputConnection(reader.GetOutputPort())
        gf.Update()
        poly = gf.GetOutput()
    else:
        try:
            reader.Update()
            poly = reader.GetOutput()
        except:
            poly = None

    if not poly:
        return None

    cleanpd = vtk.vtkCleanPolyData()
    vu.setInput(cleanpd, poly)
    cleanpd.Update()
    return cleanpd.GetOutput()
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:
            vio.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
def boundaries(actor, c='p', lw=5, legend=None):
    '''Build a copy of actor that shows the boundary lines of its surface.'''
    fe = vtk.vtkFeatureEdges()
    vu.setInput(fe, vu.polydata(actor))
    fe.BoundaryEdgesOn()
    fe.FeatureEdgesOn()
    fe.ManifoldEdgesOn()
    fe.NonManifoldEdgesOn()
    fe.ColoringOff()
    fe.Update()
    bactor = vu.makeActor(fe.GetOutput(), c=c, alpha=1, legend=legend)
    bactor.GetProperty().SetLineWidth(lw)
    return bactor
Beispiel #12
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

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

    ![cluster](https://user-images.githubusercontent.com/32848391/46817286-2039ce00-cd7f-11e8-8b29-42925e03c974.png)
    '''
    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
Beispiel #13
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)
Beispiel #14
0
def write(obj, fileoutput):
    '''
    Write 3D object to file.

    Possile extensions are: .vtk, .ply, .obj, .stl, .byu, .vtp, .xyz, .tif
    '''
    fr = fileoutput.lower()
    if '.vtk' in fr:
        w = vtk.vtkPolyDataWriter()
    elif '.ply' in fr:
        w = vtk.vtkPLYWriter()
    elif '.stl' in fr:
        w = vtk.vtkSTLWriter()
    elif '.vtp' in fr:
        w = vtk.vtkXMLPolyDataWriter()
    elif '.xyz' in fr:
        w = vtk.vtkSimplePointsWriter()
    elif '.byu' in fr or fr.endswith('.g'):
        w = vtk.vtkBYUWriter()
    elif '.obj' in fr:
        obj = vu.polydata(obj, True)
        w = vtk.vtkOBJExporter()
        w.SetFilePrefix(fileoutput.replace('.obj', ''))
        vc.printc('Please use write(vp.renderWin)', c=3)
        w.SetInput(obj)
        w.Update()
        vc.printc("Saved file: " + fileoutput, c='g')
        return
    elif '.tif' in fr:
        wr = vtk.vtkTIFFWriter()
        wr.SetFileDimensionality(len(obj.GetDimensions()))
        vu.setInput(wr, obj)
        wr.SetFileName(fileoutput)
        wr.Write()
        vc.printc("TIFF stack saved as: " + fileoutput, c='g')
        return
    else:
        vc.printc('Unavailable format in file ' + fileoutput, c='r')
        exit(1)

    try:
        obj = vu.polydata(obj, True)
        vu.setInput(w, vu.polydata(obj, True))
        w.SetFileName(fileoutput)
        w.Write()
        vc.printc("Saved file: " + fileoutput, c='g')
    except:
        vc.printc("Error saving: " + fileoutput, c='r')
Beispiel #15
0
def boundaries(actor, c='p', lw=5, legend=None):
    '''Build a copy of actor that shows the boundary lines of its surface.

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/tutorial.py)    
    '''
    fe = vtk.vtkFeatureEdges()
    vu.setInput(fe, vu.polydata(actor))
    fe.BoundaryEdgesOn()
    fe.FeatureEdgesOn()
    fe.ManifoldEdgesOn()
    fe.NonManifoldEdgesOn()
    fe.ColoringOff()
    fe.Update()
    bactor = vu.makeActor(fe.GetOutput(), c=c, alpha=1, legend=legend)
    bactor.GetProperty().SetLineWidth(lw)
    return bactor
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 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
Beispiel #18
0
def load2Dimage(filename, alpha):
    fl = filename.lower()
    if '.png' in fl:
        picr = vtk.vtkPNGReader()
    elif '.jpg' in fl or '.jpeg' in fl:
        picr = vtk.vtkJPEGReader()
    else:
        print('file must end with .png or .jpg')
        exit(1)
    picr.SetFileName(filename)
    picr.Update()
    vactor = vtk.vtkImageActor()
    vu.setInput(vactor, picr.GetOutput())
    vactor.SetOpacity(alpha)
    vu.assignConvenienceMethods(vactor, False)
    vu.assignPhysicsMethods(vactor)
    return vactor
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.polydata(line(pts), False)
    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
Beispiel #22
0
def buildPolyData(vertices, faces=None, indexOffset=0):
    '''
    Build a vtkPolyData object from a list of vertices
    and the connectivity representing the faces of the polygonal mesh.

    E.g. faces=[[0,1,2], [1,2,3], ...], 
         vertices=[[x1,y1,z1],[x2,y2,z2], ...] 

    Use indexOffset=1 if face numbering starts from 1 instead of 0.
    '''
    sourcePoints = vtk.vtkPoints()
    sourceVertices = vtk.vtkCellArray()
    sourcePolygons = vtk.vtkCellArray()
    for pt in vertices:
        if len(pt) > 2:
            aid = sourcePoints.InsertNextPoint(pt[0], pt[1], pt[2])
        else:
            aid = sourcePoints.InsertNextPoint(pt[0], pt[1], 0)
        sourceVertices.InsertNextCell(1)
        sourceVertices.InsertCellPoint(aid)
    if faces:
        for f in faces:
            n = len(f)
            if n == 4:
                plg = vtk.vtkTetra()
            elif n == 3:
                plg = vtk.vtkTriangle()
            else:
                plg = vtk.vtkPolygon()
                plg.GetPointIds().SetNumberOfIds(n)
            for i in range(n):
                plg.GetPointIds().SetId(i, f[i] - indexOffset)
            sourcePolygons.InsertNextCell(plg)

    poly = vtk.vtkPolyData()
    poly.SetPoints(sourcePoints)
    poly.SetVerts(sourceVertices)
    if faces:
        poly.SetPolys(sourcePolygons)
    clp = vtk.vtkCleanPolyData()
    vu.setInput(clp, poly)
    clp.PointMergingOn()
    clp.Update()
    return clp.GetOutput()
Beispiel #23
0
def extractLargestRegion(actor, legend=None):
    '''Keep only the largest connected part of a mesh and discard all the smaller pieces.

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/largestregion.py)
    '''
    conn = vtk.vtkConnectivityFilter()
    conn.SetExtractionModeToLargestRegion()
    conn.ScalarConnectivityOff()
    poly = vu.polydata(actor, True)
    vu.setInput(conn, poly)
    conn.Update()
    epoly = conn.GetOutput()
    if legend is True and hasattr(actor, 'legend'):
        legend = actor.legend
    eact = vu.makeActor(epoly, legend)
    pr = vtk.vtkProperty()
    pr.DeepCopy(actor.GetProperty())
    eact.SetProperty(pr)
    return eact
Beispiel #24
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.

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/delaunay2d.py)
    '''
    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 plane(pos=[0, 0, 0],
          normal=[0, 0, 1],
          sx=1,
          sy=None,
          c='g',
          bc='darkgreen',
          alpha=1,
          legend=None,
          texture=None):
    '''
    Draw a plane of size sx and sy oriented perpendicular to vector normal  
    and so that it passes through point pos.
    '''
    if sy is None: sy = sx
    ps = vtk.vtkPlaneSource()
    ps.SetResolution(1, 1)
    tri = vtk.vtkTriangleFilter()
    tri.SetInputConnection(ps.GetOutputPort())
    tri.Update()
    poly = tri.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.Scale(sx, sy, 1)
    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=c,
                         bc=bc,
                         alpha=alpha,
                         legend=legend,
                         texture=texture)
    actor.SetPosition(pos)
    actor.PickableOff()
    return actor
Beispiel #26
0
def normals(actor, ratio=5, c=(0.6, 0.6, 0.6), alpha=0.8, legend=None):
    '''
    Build a vtkActor made of the normals at vertices shown as arrows

    [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/tutorial.py)    
    [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/fatlimb.py)    
    '''
    maskPts = vtk.vtkMaskPoints()
    maskPts.SetOnRatio(ratio)
    maskPts.RandomModeOff()
    src = vu.polydata(actor)
    vu.setInput(maskPts, src)
    arrow = vtk.vtkArrowSource()
    arrow.SetTipRadius(0.075)
    glyph = vtk.vtkGlyph3D()
    glyph.SetSourceConnection(arrow.GetOutputPort())
    glyph.SetInputConnection(maskPts.GetOutputPort())
    glyph.SetVectorModeToUseNormal()
    b = src.GetBounds()
    sc = max([b[1]-b[0], b[3]-b[2], b[5]-b[4]])/20.
    glyph.SetScaleFactor(sc)
    glyph.SetColorModeToColorByVector()
    glyph.SetScaleModeToScaleByVector()
    glyph.OrientOn()
    glyph.Update()
    glyphMapper = vtk.vtkPolyDataMapper()
    glyphMapper.SetInputConnection(glyph.GetOutputPort())
    glyphMapper.SetScalarModeToUsePointFieldData()
    glyphMapper.SetColorModeToMapScalars()
    glyphMapper.ScalarVisibilityOn()
    glyphMapper.SelectColorArray("Elevation")
    glyphActor = vtk.vtkActor()
    glyphActor.SetMapper(glyphMapper)
    glyphActor.GetProperty().EdgeVisibilityOff()
    glyphActor.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
    glyphActor.GetProperty().SetOpacity(alpha)
    aactor = vu.makeAssembly([actor, glyphActor], legend=legend)
    return aactor
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'''
    ps = vtk.vtkPlaneSource()
    ps.SetResolution(resx, resy)
    ps.Update()
    poly0 = ps.GetOutput()
    t0 = vtk.vtkTransform()
    t0.Scale(sx, sy, 1)
    tf0 = vtk.vtkTransformPolyDataFilter()
    vu.setInput(tf0, 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()
    vu.setInput(tf, poly)
    tf.SetTransform(t)
    tf.Update()
    pd = tf.GetOutput()
    actor = vu.makeActor(pd, c=c, bc=bc, alpha=alpha, legend=legend)
    actor.GetProperty().SetRepresentationToWireframe()
    actor.GetProperty().SetLineWidth(lw)
    actor.SetPosition(pos)
    actor.PickableOff()
    return actor
Beispiel #28
0
def loadPoly(filename):
    '''Return a vtkPolyData object, NOT a vtkActor'''
    if not os.path.exists(filename):
        vc.printc(('Error in loadPoly: Cannot find', filename), c=1)
        return None
    fl = filename.lower()
    if '.vtk' in fl: reader = vtk.vtkPolyDataReader()
    elif '.ply' in fl: reader = vtk.vtkPLYReader()
    elif '.obj' in fl: reader = vtk.vtkOBJReader()
    elif '.stl' in fl: reader = vtk.vtkSTLReader()
    elif '.byu' in fl or '.g' in fl: reader = vtk.vtkBYUReader()
    elif '.vtp' in fl: reader = vtk.vtkXMLPolyDataReader()
    elif '.vts' in fl: reader = vtk.vtkXMLStructuredGridReader()
    elif '.vtu' in fl: reader = vtk.vtkXMLUnstructuredGridReader()
    elif '.txt' in fl: reader = vtk.vtkParticleReader()  # (x y z scalar)
    elif '.xyz' in fl: reader = vtk.vtkParticleReader()
    else: reader = vtk.vtkDataReader()
    reader.SetFileName(filename)
    reader.Update()
    if '.vts' in fl:  # structured grid
        gf = vtk.vtkStructuredGridGeometryFilter()
        gf.SetInputConnection(reader.GetOutputPort())
        gf.Update()
        poly = gf.GetOutput()
    elif '.vtu' in fl:  # unstructured grid
        gf = vtk.vtkGeometryFilter()
        gf.SetInputConnection(reader.GetOutputPort())
        gf.Update()
        poly = gf.GetOutput()
    else:
        poly = reader.GetOutput()

    if not poly:
        vc.printc(('Unable to load', filename), c=1)
        return False

    cleanpd = vtk.vtkCleanPolyData()
    vu.setInput(cleanpd, poly)
    cleanpd.Update()
    return cleanpd.GetOutput()
Beispiel #29
0
def smoothLaplacian(actor, niter=15, relaxfact=0.1, edgeAngle=15, featureAngle=60):
    '''
    Adjust mesh point positions using Laplacian smoothing.

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/mesh_smoothers.py)
    '''
    poly = vu.polydata(actor)
    cl = vtk.vtkCleanPolyData()
    vu.setInput(cl, poly)
    cl.Update()
    poly = cl.GetOutput()  # removes the boudaries duplication
    smoothFilter = vtk.vtkSmoothPolyDataFilter()
    smoothFilter.SetInputData(poly)
    smoothFilter.SetNumberOfIterations(niter)
    smoothFilter.SetRelaxationFactor(relaxfact)
    smoothFilter.SetEdgeAngle(edgeAngle)
    smoothFilter.SetFeatureAngle(featureAngle)
    smoothFilter.BoundarySmoothingOn()
    smoothFilter.FeatureEdgeSmoothingOn()
    smoothFilter.GenerateErrorScalarsOn()
    smoothFilter.Update()
    return align(smoothFilter.GetOutput(), poly)
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