Пример #1
0
def recoSurface(points, bins=256,
                c='gold', alpha=1, wire=False, bc='t', legend=None):
    '''
    Surface reconstruction from sparse points.

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

    ![reco](https://user-images.githubusercontent.com/32848391/46817107-b3263880-cd7e-11e8-985d-f5d158992f0c.png)
    '''

    if isinstance(points, vtk.vtkActor):
        points = points.coordinates()
    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)
    else:
        normals = vtk.vtkPCANormalEstimation()
        normals.SetInputData(polyData)
        normals.SetSampleSize(int(N/50))
        normals.SetNormalOrientationToGraphTraversal()
        distance.SetInputConnection(normals.GetOutputPort())
        print('Recalculating normals for', N,
              'points, sample size=', int(N/50))
        
    b = polyData.GetBounds()
    diagsize = np.sqrt((b[1]-b[0])**2 + (b[3]-b[2])**2 + (b[5]-b[4])**2)
    radius = diagsize/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 Actor(surface.GetOutput(), c, alpha, wire, bc, legend)
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)
Пример #3
0
generate a scalar field by the signed distance from a polydata,
save it to stack.tif file,
then extract an isosurface from the 3d image.
"""
from vtkplotter import Plotter, Points, Text, datadir

vp = Plotter(verbose=0)

act = vp.load(datadir + "290.vtk").normalize().subdivide().computeNormals()

# Generate signed distance function and contour it
import vtk

dist = vtk.vtkSignedDistance()
dist.SetInputData(act.polydata())
dist.SetRadius(0.2)  # how far out to propagate distance calculation
dist.SetBounds(-2, 2, -2, 2, -2, 2)
dist.SetDimensions(80, 80, 80)
dist.Update()

# vp.write(dist.GetOutput(), 'stack.tif')

fe = vtk.vtkExtractSurface()
fe.SetInputConnection(dist.GetOutputPort())
fe.SetRadius(0.2)  # this should match the signed distance radius
fe.Update()

pts = Points(act.coordinates())

vp.show(fe.GetOutput(), pts, Text(__doc__))
subMapper.SetScaleFactor(0.0)

subActor = vtk.vtkActor()
subActor.SetMapper(subMapper)

# Generate signed distance function and contour it
dist = vtk.vtkSignedDistance()
dist.SetInputConnection(norms.GetOutputPort())
dist.SetRadius(0.1) #how far out to propagate distance calculation
dist.SetBounds(-1,1, -1,1, -1,1)
dist.SetDimensions(50,50,50)

# Extract the surface with modified flying edges
#fe = vtk.vtkFlyingEdges3D()
#fe.SetValue(0,0.0)
fe = vtk.vtkExtractSurface()
fe.SetInputConnection(dist.GetOutputPort())
fe.SetRadius(0.1) # this should match the signed distance radius

# Time the execution
timer = vtk.vtkTimerLog()
timer.StartTimer()
fe.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
print("Points processed: {0}".format(NPts))
print("   Time to generate and extract distance function: {0}".format(time))
print("   Resulting bounds: {}".format(fe.GetOutput().GetBounds()))

feMapper = vtk.vtkPolyDataMapper()
feMapper.SetInputConnection(fe.GetOutputPort())