1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
#!/usr/bin/env python
#
# Author: Patrick Hung (patrickh @caltech)
# Copyright (c) 1997-2016 California Institute of Technology.
# Copyright (c) 2016-2024 The Uncertainty Quantification Foundation.
# License: 3-clause BSD. The full license text is available at:
# - https://github.com/uqfoundation/mystic/blob/master/LICENSE
#
# This example is a derivative of vtk's ClipCow
# It is a visualization of Prince Rupert's problem
import tkinter
import vtk
from vtk.tk.vtkTkRenderWindowInteractor import \
vtkTkRenderWindowInteractor
from numpy import array, cross
from vtk.util.colors import peacock, tomato
#cube = vtk.vtkBYUReader()
#cube.SetGeometryFileName("./cube.g")
cube = vtk.vtkCubeSource()
cube.SetCenter(0.5,0.5,0.5)
cubeNormals = vtk.vtkPolyDataNormals()
cubeNormals.SetInputConnection(cube.GetOutputPort())
cube = cubeNormals
def PlaneNormal(a, b, c):
assert(a >= 0 and a <= 1)
assert(b >= 0 and b <= 1)
assert(c >= 0 and c <= 2)
A = array([a, 0.0, 0.0])
B = array([0.0, b, 0.0])
if c < 1:
C = array([c, 0.0, 1.0])
else:
C = array([1.0, c-1.0, 1.0])
BA = B-A
CA = C-A
return cross(BA, CA)
def CuttingPlane(a, b, c):
N = PlaneNormal(a,b,c)
plane = vtk.vtkPlane()
plane.SetOrigin(a, 0, 0)
plane.SetNormal(*N)
return plane
def getAxes(Origin, scale = 1):
axes = vtk.vtkAxes()
axes.SetOrigin(*Origin)
axes.SetScaleFactor(scale)
axesTubes = vtk.vtkTubeFilter()
axesTubes.SetInputConnection(axes.GetOutputPort())
axesTubes.SetRadius(0.01)
axesTubes.SetNumberOfSides(6)
axesMapper = vtk.vtkPolyDataMapper()
axesMapper.SetInputConnection(axesTubes.GetOutputPort())
axesActor = vtk.vtkActor()
axesActor.SetMapper(axesMapper)
XText = vtk.vtkVectorText()
XText.SetText("x")
XTextMapper = vtk.vtkPolyDataMapper()
XTextMapper.SetInputConnection(XText.GetOutputPort())
XActor = vtk.vtkFollower()
XActor.SetMapper(XTextMapper)
XActor.SetScale(.1, .1, .1)
XActor.SetPosition(1, Origin[1], Origin[2])
XActor.GetProperty().SetColor(0, 0, 0)
YText = vtk.vtkVectorText()
YText.SetText("y")
YTextMapper = vtk.vtkPolyDataMapper()
YTextMapper.SetInputConnection(YText.GetOutputPort())
YActor = vtk.vtkFollower()
YActor.SetMapper(YTextMapper)
YActor.SetScale(.1, .1, .1)
YActor.SetPosition(Origin[0], 1, Origin[2])
YActor.GetProperty().SetColor(0, 0, 0)
return axesActor, XActor, YActor
axesActor, XActor, YActor = getAxes([-.1, -.1, -.1])
P = (0.75, 0.75, 1.25)
# vtkClipPolyData requires an implicit function to define what it is to
# clip with. Any implicit function, including complex boolean combinations
# can be used. Notice that we can specify the value of the implicit function
# with the SetValue method.
clipper = vtk.vtkClipPolyData()
clipper.SetInputConnection(cubeNormals.GetOutputPort())
clipper.SetClipFunction(CuttingPlane(*P))
clipper.GenerateClipScalarsOn()
clipper.GenerateClippedOutputOn()
clipper.SetValue(0)
clipMapper = vtk.vtkPolyDataMapper()
clipMapper.SetInputConnection(clipper.GetOutputPort())
clipMapper.ScalarVisibilityOff()
backProp = vtk.vtkProperty()
backProp.SetDiffuseColor(tomato)
clipActor = vtk.vtkActor()
clipActor.SetMapper(clipMapper)
clipActor.GetProperty().SetColor(peacock)
clipActor.SetBackfaceProperty(backProp)
# Here we are cutting the cube. Cutting creates lines where the cut
# function intersects the model. (Clipping removes a portion of the
# model but the dimension of the data does not change.)
#
# The reason we are cutting is to generate a closed polygon at the
# boundary of the clipping process. The cutter generates line
# segments, the stripper then puts them together into polylines. We
# then pull a trick and define polygons using the closed line
# segements that the stripper created.
cutEdges = vtk.vtkCutter()
cutEdges.SetInputConnection(cubeNormals.GetOutputPort())
cutEdges.SetCutFunction(CuttingPlane(*P))
cutEdges.GenerateCutScalarsOn()
cutEdges.SetValue(0, 0)
cutStrips = vtk.vtkStripper()
cutStrips.SetInputConnection(cutEdges.GetOutputPort())
cutStrips.Update()
cutPoly = vtk.vtkPolyData()
cutPoly.SetPoints(cutStrips.GetOutput().GetPoints())
cutPoly.SetPolys(cutStrips.GetOutput().GetLines())
# Triangle filter is robust enough to ignore the duplicate point at
# the beginning and end of the polygons and triangulate them.
cutTriangles = vtk.vtkTriangleFilter()
cutTriangles.SetInput(cutPoly)
cutMapper = vtk.vtkPolyDataMapper()
cutMapper.SetInput(cutPoly)
cutMapper.SetInputConnection(cutTriangles.GetOutputPort())
cutActor = vtk.vtkActor()
cutActor.SetMapper(cutMapper)
cutActor.GetProperty().SetColor(peacock)
# The clipped part of the cube is rendered wireframe.
restMapper = vtk.vtkPolyDataMapper()
restMapper.SetInput(clipper.GetClippedOutput())
restMapper.ScalarVisibilityOff()
restActor = vtk.vtkActor()
restActor.SetMapper(restMapper)
restActor.GetProperty().SetRepresentationToWireframe()
# Create graphics stuff
renWin = vtk.vtkRenderWindow()
ren = vtk.vtkRenderer()
ren.SetBackground(tomato)
renWin.AddRenderer(ren)
# Add the actors to the renderer, set the background and size
ren.AddActor(clipActor)
ren.AddActor(cutActor)
ren.AddActor(restActor)
ren.AddActor(axesActor)
ren.AddActor(XActor)
ren.AddActor(YActor)
ren.SetBackground(1, 1, 1)
ren.ResetCamera()
camera = ren.GetActiveCamera()
camera.SetFocalPoint(0.489125, 0.481143, 0.445)
camera.SetPosition(-0.870854, -1.51779, 3.14336)
camera.SetParallelScale(1.00818)
camera.SetParallelProjection(1)
camera.SetViewUp(-0.239476, 0.833984, 0.497114)
ren.ResetCameraClippingRange()
renWin.SetSize(400, 400)
def Cut(v):
Q = (P[0], P[1], v)
cp = CuttingPlane(*Q)
pn = PlaneNormal(*Q)
clipper.SetClipFunction(cp)
clipper.SetValue(0)
cutEdges.SetCutFunction(cp)
cutEdges.SetValue(0, 0)
cutStrips.Update()
cutPoly.SetPoints(cutStrips.GetOutput().GetPoints())
cutPoly.SetPolys(cutStrips.GetOutput().GetLines())
cutMapper.Update()
renWin.Render()
root = tkinter.Tk()
vtkw = vtkTkRenderWindowInteractor(root, rw=renWin, width=800)
def set_cut(sz):
sz = float(sz)
# print(ren.GetActiveCamera())
Cut(sz)
# propagate this GUI setting to the corresponding VTK object.
size_slider = tkinter.Scale(root, from_=0.0,
to=2.0, res=0.01,
orient='horizontal', label="Clipping Center",
command=set_cut)
size_slider.set(P[2])
vtkw.Initialize()
size_slider.pack(side="top", fill="both")
vtkw.pack(side="top", fill='both', expand=1)
# Define a quit method that exits cleanly.
def quit(obj=root):
obj.quit()
root.protocol("WM_DELETE_WINDOW", quit)
renWin.Render()
vtkw.Start()
# start the Tkinter event loop.
root.mainloop()
# end of file
|