Skip to content

Commit 3cc8017

Browse files
committed
oolydata.py
Contains a wrapper class of vtk's polydata. All constructed plots are now based on this as it's much easier to use. Added print flushing to BaseFigure.show() to try to get it to finish printing before the render opens. It's not brilliant. unicode_paths.py Full support for non ascii characters in paths which vtk can't handle. Uses a PathHandler class. This has been built into the screenshot feature and the VTK STL reader. MeshPlot.py Updated to allow numpy-stl or vtk to try to read directly from a path. The vtk reader has a hole in it somewhere and doesn't support every file. Hence rabbit.stl test model is duplicated and rewritten as rabbit2.stl. Hopefully at least one will work.
1 parent f7c1479 commit 3cc8017

File tree

14 files changed

+825
-124
lines changed

14 files changed

+825
-124
lines changed

vtkplotlib/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@
4444

4545
from .plots.Arrow import arrow, quiver
4646
from .plots.Lines import Lines as plot
47-
from .plots.MeshPlot import MeshPlot as mesh_plot, mesh_plot_with_edge_scalars
47+
from .plots.MeshPlot import MeshPlot as mesh_plot, mesh_plot_with_edge_scalars, NUMPY_STL_AVAILABLE
4848
from .plots.Polygon import Polygon as polygon
4949
from .plots.ScalarBar import ScalarBar as scalar_bar
5050
from .plots.Scatter import scatter, Cursor as cursor
51+
from .plots.Surface import Surface
5152
from .plots.Text import Text as text
5253
from .plots.Text3D import Text3D as text3d, annotate
5354

vtkplotlib/data/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525

2626
import numpy as np
27-
import matplotlib.pylab as plt
2827
import sys
2928
import os
3029
from pathlib2 import Path
@@ -36,10 +35,13 @@
3635

3736
STL_FOLDER = DATA_FOLDER / "models"
3837

39-
def get_rabbit_stl():
38+
def get_rabbit_stl(two=sys.platform=="win32"):
4039
folder = STL_FOLDER
4140
print("This is not my rabbit file. See README.txt and LICENSE.txt in\n{}\nfor details.".format(folder))
42-
return str(folder / "rabbit.stl")
41+
if two:
42+
return str(folder / "rabbit2.stl")
43+
else:
44+
return str(folder / "rabbit.stl")
4345

4446
ICONS_FOLDER = DATA_FOLDER / "icons"
4547

vtkplotlib/data/models/rabbit2.stl

3.54 MB
Binary file not shown.

vtkplotlib/figures/BaseFigure.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
You should have received a copy of the GNU General Public License
2222
along with this program. If not, see <https://www.gnu.org/licenses/>.
2323
"""
24+
from __future__ import print_function
2425
from builtins import super
2526

2627
import numpy as np
@@ -51,9 +52,13 @@ def reset_camera(self):
5152

5253
def show(self, block=True):
5354
# Try and force the console to finish displaying any preceeding print
54-
# statements before VTK start is called and blocks everything. With
55+
# statements before VTK start is called and blocks everything. Rather
5556
# limited success.
56-
print(end="", flush=True)
57+
try:
58+
# python 2 doesn't have flush
59+
print(end="", flush=True)
60+
except TypeError:
61+
pass
5762
sys.stdout.flush()
5863
for attr in ("buffer", "_buffer"):
5964
if hasattr(sys.stdout, attr):

vtkplotlib/figures/figure_manager.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,14 @@ def save_fig(path, magnifigation=1, pixels=None, fig="gcf"):
213213
214214
magnifigation:
215215
An int or a (width, height) tuple of ints.
216-
Set the image dimensions relative to the size of the render.
216+
Set the image dimensions relative to the size of the render (window).
217217
218218
219219
pixels:
220220
An int or a (width, height) tuple of ints.
221221
Set the image dimensions in pixels. If only one dimension is given
222-
then it is the height and an aspect ration of 16:9 is used.
222+
then it is the height and an aspect ration of 16:9 is used. Overides
223+
`magnification` if given.
223224
224225
225226
Note that VTK can only work with integer multiples of the render size
@@ -261,18 +262,21 @@ def save_fig(path, magnifigation=1, pixels=None, fig="gcf"):
261262
w2if.SetMagnification(magnifigation[0])
262263
w2if.Update()
263264

264-
old_path = Path.cwd()
265-
os.chdir(str(path.parent))
266-
if path.suffix.lower() in (".jpg", ".jpeg"):
267-
writer = vtk.vtkJPEGWriter()
268-
elif path.suffix.lower() == ".png":
269-
writer = vtk.vtkPNGWriter()
270-
else:
271-
raise NotImplementedError(path.suffix + " is not supported")
272-
writer.SetFileName(path.name)
273-
writer.SetInputConnection(w2if.GetOutputPort())
274-
writer.Write()
275-
os.chdir(str(old_path))
265+
from vtkplotlib.unicode_paths import PathHandler
266+
267+
with PathHandler(path, "w") as path_handler:
268+
269+
# if path.suffix.lower() in (".jpg", ".jpeg"):
270+
# writer = vtk.vtkJPEGWriter()
271+
# elif path.suffix.lower() == ".png":
272+
# writer = vtk.vtkPNGWriter()
273+
# else:
274+
# raise NotImplementedError(path.suffix + " is not supported")
275+
writer = vtk.vtkImageWriter()
276+
277+
writer.SetFileName(path_handler.access_path)
278+
writer.SetInputConnection(w2if.GetOutputPort())
279+
writer.Write()
276280

277281

278282

vtkplotlib/plots/BasePlot.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from vtkplotlib.figures import gcf
3636
from vtkplotlib.colors import process_color
3737
from vtkplotlib import nuts_and_bolts
38-
38+
from vtkplotlib.plots.polydata import PolyData
3939

4040

4141

@@ -50,15 +50,15 @@ def __init__(self, fig="gcf"):
5050
fig = gcf()
5151
self.fig = fig
5252
self.temp = []
53-
54-
55-
def add_to_plot(self):
53+
5654
self.mapper = vtk.vtkPolyDataMapper()
5755

5856
self.actor = vtk.vtkActor()
59-
self.actor.SetMapper(self.mapper)
6057

6158

59+
def add_to_plot(self):
60+
self.actor.SetMapper(self.mapper)
61+
6262
self.property = self.actor.GetProperty()
6363
if self.fig is not None:
6464
self.fig.add_plot(self)
@@ -127,11 +127,18 @@ class ConstructedPlot(BasePlot):
127127
"""
128128
def __init__(self, fig="gcf"):
129129
super().__init__(fig)
130-
self.poly_data = vtk.vtkPolyData()
130+
self.polydata = PolyData()
131131

132132
def add_to_plot(self):
133133
super().add_to_plot()
134-
self.mapper.SetInputData(self.poly_data)
134+
if vtk.VTK_MAJOR_VERSION <= 5:
135+
self.mapper.SetInput(self.polydata.vtk_polydata)
136+
else:
137+
self.mapper.SetInputData(self.polydata.vtk_polydata)
138+
139+
scalars = self.polydata.point_scalars
140+
if scalars is not None:
141+
self.mapper.SetScalarRange(np.nanmin(scalars), np.nanmin(scalars.max()))
135142

136143

137144

vtkplotlib/plots/Lines.py

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939

4040

4141
from vtkplotlib.plots.BasePlot import ConstructedPlot, _iter_colors, _iter_points, _iter_scalar
42-
from vtkplotlib import geometry as geom, numpy_vtk
42+
from vtkplotlib import numpy_vtk, nuts_and_bolts
43+
from vtkplotlib.plots.polydata import join_line_ends
4344

4445

4546

@@ -49,39 +50,21 @@ class Lines(ConstructedPlot):
4950
def __init__(self, vertices, color=None, opacity=None, line_width=1.0, join_ends=False, fig="gcf"):
5051
super().__init__(fig)
5152

52-
vertices = numpy_vtk.contiguous_safe(vertices)
53-
self.temp.append(vertices)
5453

55-
points = vtk.vtkPoints()
56-
points.SetData(numpy_to_vtk(vertices))
54+
shape = vertices.shape[:-1]
55+
points = numpy_vtk.contiguous_safe(nuts_and_bolts.flatten_all_but_last(vertices))
56+
self.temp.append(points)
5757

58-
# vtkCellArray is a supporting object that explicitly represents cell connectivity.
59-
# The cell array structure is a raw integer list of the form:
60-
# (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) where n is the number of points in
61-
# the cell, and id is a zero-offset index into an associated point list.
58+
args = nuts_and_bolts.flatten_all_but_last(np.arange(np.prod(shape)).reshape(shape))
6259

63-
point_args = np.empty(1 + len(vertices) + join_ends, np.int64)
64-
point_args[0] = len(vertices) + join_ends
65-
point_args[1: 1+len(vertices)] = np.arange(len(vertices))
60+
self.polydata.points = points
6661
if join_ends:
67-
point_args[-1] = 0
68-
lines = vtk.vtkCellArray()
69-
lines.SetCells(len(point_args), numpy_to_vtkIdTypeArray(point_args.ravel()))
62+
self.polydata.lines = join_line_ends(args)
63+
else:
64+
self.polydata.lines = args
7065

66+
# assert np.array_equal(points[args], vertices)
7167

72-
# vtkPolyData is a data object that is a concrete implementation of vtkDataSet.
73-
# vtkPolyData represents a geometric structure consisting of vertices, lines,
74-
# polygons, and/or triangle strips
75-
polygon = self.poly_data
76-
polygon.SetPoints(points)
77-
polygon.SetLines(lines)
78-
79-
80-
# Create an actor to represent the polygon. The actor orchestrates rendering of
81-
# the mapper's graphics primitives. An actor also refers to properties via a
82-
# vtkProperty instance, and includes an internal transformation matrix. We
83-
# set this actor's mapper to be polygonMapper which we created above.
84-
self.actor = vtk.vtkActor()
8568

8669
self.add_to_plot()
8770

@@ -92,17 +75,23 @@ def __init__(self, vertices, color=None, opacity=None, line_width=1.0, join_ends
9275

9376

9477

95-
96-
9778
if __name__ == "__main__":
9879
import vtkplotlib as vpl
9980

10081
t = np.arange(0, 1, .001) * 2 * np.pi
101-
points = np.array([np.cos(2 * t),
102-
np.sin(3 * t),
103-
np.cos(5 * t) * np.sin(7 *t)]).T
82+
vertices = np.array([np.cos(2 * t),
83+
np.sin(3 * t),
84+
np.cos(5 * t) * np.sin(7 *t)]).T
85+
vertices = np.array([vertices, vertices + 2])
10486

105-
# vertices = np.random.uniform(-30, 30, (3, 3))
106-
self = vpl.plot(points, color="green", line_width=3, join_ends=True)
87+
t = np.arange(0, 1, .125) * 2 * np.pi
88+
vertices = np.array([np.cos(t), np.sin(t), np.zeros_like(t)]).T
10789

90+
# vertices = np.random.uniform(-30, 30, (3, 3))
91+
self = vpl.plot(vertices, color="green", line_width=6, join_ends=True)
92+
# self.polydata.point_scalars = vpl.geometry.distance(vertices)
93+
self.polydata.point_scalars = t
94+
fig = vpl.gcf()
95+
fig.background_color = "grey"
96+
self.add_to_plot()
10897
vpl.show()

0 commit comments

Comments
 (0)