Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a module to make streamlines from an array of seeds #678

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions mayavi/modules/streamline.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

# Enthought library imports.
from traits.api import Instance, Bool, TraitPrefixList, Trait, \
Delegate, Button
Delegate, Button, Array
from traitsui.api import View, Group, Item, InstanceEditor
from tvtk.api import tvtk
from tvtk.common import configure_outputs
Expand Down Expand Up @@ -128,6 +128,9 @@ class Streamline(Module):
######################################################################
# `Module` interface
######################################################################
def _setup_seed(self):
self.seed = SourceWidget()

def setup_pipeline(self):
"""Override this method so that it *creates* the tvtk
pipeline.
Expand All @@ -141,7 +144,7 @@ def setup_pipeline(self):
set the `actors` attribute up at this point.
"""
# Create and setup the default objects.
self.seed = SourceWidget()
self._setup_seed()
self.stream_tracer = tvtk.StreamTracer(maximum_propagation=50,
integration_direction='forward',
compute_vorticity=True,
Expand All @@ -168,7 +171,8 @@ def update_pipeline(self):

src = mm.source
self.configure_connection(self.stream_tracer, src)
self.seed.inputs = [src]
if isinstance(self.seed, SourceWidget):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I am not too happy about this isinstance check, it suggests that there should be a cleaner way to do this. Is the intent to just allow a user to set the polydata and not use a widget at all? I think it would be very useful thing in any case to allow users complete control over the points. So maybe I should think of supporting either a widget or a poly data. This could perhaps be done by simply having another attribute on the streamline module, say user_seed which is a polydata and if this is non-None, that we use that instead of the seed?

self.seed.inputs = [src]

# Setup the radius/width of the tube/ribbon filters based on
# given input.
Expand Down Expand Up @@ -230,7 +234,11 @@ def _stream_tracer_changed(self, old, new):
old.on_trait_change(self.render, remove=True)
seed = self.seed
if seed is not None:
self.configure_source_data(new, seed.poly_data)
if isinstance(seed, SourceWidget):
data = seed.poly_data
else:
data = seed
self.configure_source_data(new, data)
new.on_trait_change(self.render)
mm = self.module_manager
if mm is not None:
Expand Down Expand Up @@ -265,3 +273,29 @@ def _actor_changed(self, old, new):
new.scene = self.scene
new.inputs = [self]
self._change_components(old, new)


class SeedStreamline(Streamline):
"""
A Streamline tracer with fixed input of points.
"""

seed_points = Array(allow_none=False)
seed = Instance(tvtk.PolyData, args=())

update_mode = Trait('interactive', TraitPrefixList(['interactive',
'semi-interactive',
'non-interactive']),
desc='the speed at which the poly data is updated')

def _setup_seed(self):
# Create and setup the default objects.
self.seed = tvtk.PolyData(points=self.seed_points)

def _seed_points_changed(self, old, new):
self.seed = tvtk.PolyData(points=self.seed_points)

def _seed_changed(self, old, new):
st = self.stream_tracer
if st is not None:
self.configure_connection(st, new)