import os
import vtk
from pycaster import pycaster
We're gonna use this function to embed a still image of a VTK render
import vtk
from IPython.display import Image
def vtk_show(renderer, width=400, height=300):
"""
Takes vtkRenderer instance and returns an IPython Image with the rendering.
"""
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetOffScreenRendering(1)
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(width, height)
renderWindow.Render()
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renderWindow)
windowToImageFilter.Update()
writer = vtk.vtkPNGWriter()
writer.SetWriteToMemory(1)
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.Write()
data = str(buffer(writer.GetResult()))
return Image(data)
This function adds a line to a vtkRenderer
def addLine(renderer, p1, p2, color=[0.0, 0.0, 1.0]):
line = vtk.vtkLineSource()
line.SetPoint1(p1)
line.SetPoint2(p2)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(line.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(color)
renderer.AddActor(actor)
This function adds a point (a sphere really) to a vtkRenderer
def addPoint(renderer, p, radius=1.0, color=[0.0, 0.0, 0.0]):
point = vtk.vtkSphereSource()
point.SetCenter(p)
point.SetRadius(radius)
point.SetPhiResolution(100)
point.SetThetaResolution(100)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(point.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(color)
renderer.AddActor(actor)
Create a new rayCaster
object through the fromSTL
static-method thus loading the STL file sphereHollow.stl
and creating a new rayCaster
under caster
caster = pycaster.rayCaster.fromSTL("sphereHollow.stl", scale=1)
Create a new vtkRenderer
and visualize the caster.mesh
using vtk_show
mapper = vtk.vtkPolyDataMapper()
mapper.SetInput(caster.mesh)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetOpacity(0.25)
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(1.0, 1.0, 1.0)
vtk_show(renderer)
Set the source and target coordinate of the ray
pSource = [-50.0, 0.0, 0.0]
pTarget = [50.0, 0.0, 0.0]
Use the addPoint
and addLine
helper-functions to render the ray as well as the source (red) and target (green) points
addPoint(renderer, pSource, color=[1.0, 0.0, 0.0])
addPoint(renderer, pTarget, color=[0.0, 1.0, 0.0])
addLine(renderer, pSource, pTarget)
vtk_show(renderer)
Use the castRay
method of the rayCaster
class to intersect a ray/line with the surface and return a list
of coordinates, i.e., the intersection points
pointsIntersection = caster.castRay(pSource, pTarget)
pointsIntersection
[(-24.91461181640625, 0.0, 0.0), (-19.914684295654297, 0.0, 0.0), (19.914684295654297, 0.0, 0.0), (24.91461181640625, 0.0, 0.0)]
Use the calcDistanceInSolid
to calculate the distance the ray 'travels' within the surface
caster.calcDistanceInSolid(pSource, pTarget)
9.999855041503906
Loop through pointsIntersection
list and use the addPoint
helper-function to render the intersection points (blue)
for p in pointsIntersection:
addPoint(renderer, p, color=[0.0, 0.0, 1.0])
vtk_show(renderer)