""" This module shows an iso-surface of scalar data. This will work for any dataset. This code is distributed under the conditions of the BSD license. See LICENSE.txt for details. Copyright (c) 2001-2002, Prabhu Ramachandran. """ __author__ = "Prabhu Ramachandran " __version__ = "$Revision: 1.5 $" __date__ = "$Date: 2005/08/02 18:30:13 $" import Base.Objects, Common import Tkinter, tkColorChooser, math import vtk import vtkPipeline.vtkMethodParser debug = Common.debug class IsoSurface (Base.Objects.Module): """ This module shows an iso-surface of scalar data. This will work for any dataset.""" def __init__ (self, mod_m): debug ("In IsoSurface::__init__ ()") Common.state.busy () Base.Objects.Module.__init__ (self, mod_m) self.cont_fil = vtk.vtkContourFilter () self.norm = vtk.vtkPolyDataNormals () self.mapper = self.map = vtk.vtkPolyDataMapper () self.actor = self.act = vtk.vtkActor () self.data_out = self.mod_m.GetOutput () self._initialize () self._gui_init () if not self.mod_m.get_scalar_data_name (): msg = "Warning: No scalar data present to contour!" Common.print_err (msg) self.renwin.Render () Common.state.idle () def __del__ (self): debug ("In IsoSurface::__del__ ()") if self.act: self.renwin.remove_actors (self.act) self.renwin.Render () def _initialize (self): debug ("In IsoSurface::_initialize ()") self.cont_fil.SetInput (self.data_out) self.map.SetInput (self.cont_fil.GetOutput ()) self.map.SetLookupTable (self.mod_m.get_scalar_lut ()) dr = self.mod_m.get_scalar_data_range () self.data_range = dr self.map.SetScalarRange (dr) self.act.SetMapper (self.map) #self.act.GetProperty ().BackfaceCullingOff () #self.act.GetProperty ().FrontfaceCullingOff () midrange = (dr[0] + dr[1])*0.5 self.slider_pos = midrange self.cont_fil.SetValue (0, midrange) self.renwin.add_actors (self.act) # used for the pipeline browser self.pipe_objs = self.act def _gui_init (self): debug ("In IsoSurface::_gui_init ()") self.slider = None self.contour_var = Tkinter.DoubleVar () self.contour_var.set (self.slider_pos) self.c_entry_var = Tkinter.DoubleVar () self.c_entry_var.set (self.slider_pos) dr = self.mod_m.get_scalar_data_range () self.min_cnt = Tkinter.DoubleVar () self.max_cnt = Tkinter.DoubleVar () self.min_cnt.set (dr[0]) self.max_cnt.set (dr[1]) self.normals_on = Tkinter.IntVar () self.normals_on.set (0) self.angle_var = Tkinter.DoubleVar () self.angle_var.set (45) self._auto_sweep_init () self.sweep_step.set (15) def SetInput (self, source): debug ("In IsoSurface::SetInput ()") Common.state.busy () self.data_out = source self.cont_fil.SetInput (self.data_out) dr = self.mod_m.get_scalar_data_range () if (dr[0] != self.data_range[0]) or (dr[1] != self.data_range[1]): self.data_range = dr self.map.SetScalarRange (dr) self.min_cnt.set (dr[0]) self.max_cnt.set (dr[1]) self.c_entry_var.set ((dr[0] + dr[1])*0.5) self.change_contour_limits () self.change_contour_entry () Common.state.idle () def save_config (self, file): debug ("In IsoSurface::save_config ()") file.write ("%f, %d, %f, %f, %f\n"%(self.c_entry_var.get (), self.normals_on.get (), self.angle_var.get (), self.min_cnt.get (), self.max_cnt.get ())) p = vtkPipeline.vtkMethodParser.VtkPickler () for obj in (self.cont_fil, self.norm, self.map, self.act, self.act.GetProperty ()): p.dump (obj, file) def load_config (self, file): debug ("In IsoSurface::load_config ()") c_val, norm_on, ang, min_cnt, max_cnt = eval (file.readline ()) self.slider_pos = c_val self.contour_var.set (c_val) self.c_entry_var.set (c_val) self.normals_on.set (norm_on) self.angle_var.set (ang) self.min_cnt.set (min_cnt) self.max_cnt.set (max_cnt) p = vtkPipeline.vtkMethodParser.VtkPickler () for obj in (self.cont_fil, self.norm, self.map, self.act, self.act.GetProperty ()): p.load (obj, file) self.change_contour_slider () self.do_normals () def config_changed (self): debug ("In IsoSurface::config_changed ()") pass def make_main_gui (self): debug ("In IsoSurface::make_main_gui ()") frame = Tkinter.Frame (self.root, relief='ridge', bd=2) frame.pack (side='top', fill='both', expand=1) name = "Scalar Variable: " + self.mod_m.get_scalar_data_name () dr = (self.min_cnt.get (), self.max_cnt.get ()) resolution = (dr[1] - dr[0])/1000 self.slider = Tkinter.Scale (frame, label=name, resolution=resolution, variable=self.contour_var, from_=dr[0], to=dr[1], length="8c", orient='horizontal') self.slider.grid (row=0, column=0, columnspan=2, sticky='ew') self.slider.bind ("", self.change_contour_slider ) lab = Tkinter.Label (frame, text="Iso-surface value :") lab.grid (row=1, column=0, sticky='w') entry = Tkinter.Entry (frame, width=10, relief='sunken', textvariable=self.c_entry_var) entry.grid (row=1, column=1, sticky='ew') entry.bind ("", self.change_contour_entry) lab = Tkinter.Label (frame, text="Minimum contour:") lab.grid (row=2, column=0, sticky='w') entry = Tkinter.Entry (frame, width=10, relief='sunken', textvariable=self.min_cnt) entry.grid (row=2, column=1, sticky='we') entry.bind ("", self.change_contour_limits) lab = Tkinter.Label (frame, text="Maximum contour:") lab.grid (row=3, column=0, sticky='w') entry = Tkinter.Entry (frame, width=10, relief='sunken', textvariable=self.max_cnt) entry.grid (row=3, column=1, sticky='we') entry.bind ("", self.change_contour_limits) norm = Tkinter.Checkbutton (frame, text="Compute PolyDataNormals", variable=self.normals_on, onvalue=1, offvalue=0, command=self.do_normals) norm.grid (row=4, columnspan=2, sticky='w') lab = Tkinter.Label (frame, text="Feature Angle (in degrees): ") lab.grid (row=5, column=0, sticky='w') entry = Tkinter.Entry (frame, width=10, relief='sunken', textvariable=self.angle_var) entry.grid (row=5, column=1, sticky='ew') entry.bind ("", self.do_normals) self.make_actor_gui () self.make_auto_sweep_gui () def do_normals (self, event=None): debug ("In IsoSurface::do_normals ()") Common.state.busy () if self.normals_on.get (): self.norm.SetInput (self.cont_fil.GetOutput ()) self.norm.SetFeatureAngle (self.angle_var.get ()) self.map.SetInput (self.norm.GetOutput ()) else: self.map.SetInput (self.cont_fil.GetOutput ()) self.renwin.Render () Common.state.idle () def change_contour_limits (self, event=None): debug ("In IsoSurface::change_contour_limits ()") min_cnt = self.min_cnt.get () max_cnt = self.max_cnt.get () val = self.contour_var.get () dr = self.data_range if max_cnt < val: msg = "Error: max. contour value less than current "\ "contour value." debug (msg) max_cnt = dr[1] self.max_cnt.set (max_cnt) if min_cnt > val: msg = "Error: min. contour value larger than current "\ "contour value." debug (msg) min_cnt = dr[0] self.min_cnt.set (min_cnt) resolution = (max_cnt - min_cnt)/1000 if self.slider: self.slider.config (from_=min_cnt, to=max_cnt, resolution=resolution) def change_contour_slider (self, event=None): debug ("In IsoSurface::change_contour_slider ()") Common.state.busy () self.slider_pos = self.contour_var.get () self.c_entry_var.set (self.slider_pos) self.cont_fil.SetValue (0, self.slider_pos) self.renwin.Render () Common.state.idle () def change_contour_entry (self, event=None): debug ("In IsoSurface::change_contour_entry ()") Common.state.busy () self.slider_pos = self.c_entry_var.get () self.contour_var.set (self.slider_pos) self.cont_fil.SetValue (0, self.slider_pos) self.renwin.Render () Common.state.idle () def do_sweep (self, event=None): debug ("In IsoSurface::do_sweep ()") if self.sweep_var.get (): val = int (1000*self.sweep_delay.get ()) self.root.after (val, self.update_sweep) def update_sweep (self): debug ("In IsoSurface::update_sweep ()") if self.sweep_var.get (): min_cnt = self.min_cnt.get () max_cnt = self.max_cnt.get () d_pos = (max_cnt - min_cnt)/self.sweep_step.get () pos = self.slider_pos + d_pos if (d_pos > 0) and (pos >= max_cnt): pos = min_cnt elif (d_pos < 0) and (pos <= min_cnt): pos = max_cnt self.contour_var.set (pos) self.change_contour_slider () val = int (1000*self.sweep_delay.get ()) self.root.after (val, self.update_sweep) def close_gui (self, event=None): debug ("In IsoSurface::close_gui ()") Base.Objects.Module.close_gui (self, event) self.slider = None