• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SciKit-Surgery / scikit-surgeryvtk / 4323596638

pending completion
4323596638

push

github-actions

Miguel Xochicale
refactors unit tests skipif messages (#187)

332 of 1997 relevant lines covered (16.62%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.67
/sksurgeryvtk/models/vtk_surface_model.py
1
# -*- coding: utf-8 -*-
2

3
"""
4✔
4
VTK pipeline to represent a surface model via a vtkPolyData.
5
"""
6

7
import os
4✔
8
import numpy as np
4✔
9
import vtk
4✔
10
from vtk.util import numpy_support
4✔
11
import sksurgerycore.utilities.validate_file as vf
4✔
12
import sksurgeryvtk.models.vtk_base_model as vbm
4✔
13
import sksurgeryvtk.utils.matrix_utils as mu
4✔
14

15
# pylint: disable=too-many-instance-attributes
16
# pylint:disable=super-with-arguments
17

18

19
class VTKSurfaceModel(vbm.VTKBaseModel):
4✔
20
    """
21
    Class to represent a VTK surface model. Normally
22
    read from a file, but could be created on the fly.
23
    """
24
    def __init__(self, filename, colour, visibility=True, opacity=1.0,
4✔
25
                 pickable=True, outline=False):
26
        """
27
        Creates a new surface model.
28

29
        :param filename: if None a default, empty, vtkPolyData is created.
30
        :param colour: (R,G,B) where each are floats [0-1]
31
        :param visibility: boolean, True|False
32
        :param opacity: float [0,1]
33
        :param pickable: boolean, True|False
34
        :param outline: boolean, do we render a model outline?
35
        """
36
        super(VTKSurfaceModel, self).__init__(colour, visibility, opacity,
×
37
                                              pickable, outline)
38

39
        self.source_file = None
×
40
        self.reader = None
×
41
        self.source = None
×
42
        self.texture_file = None
×
43
        self.texture_name = None
×
44
        self.texture_reader = None
×
45
        self.texture = None
×
46

47
        # Works like FactoryMethod. Could be refactored elsewhere.
48
        if filename is not None:
×
49

50
            vf.validate_is_file(filename)
×
51

52
            if filename.endswith('.vtk'):
×
53
                self.reader = vtk.vtkPolyDataReader()
×
54

55
            elif filename.endswith('.stl'):
×
56
                self.reader = vtk.vtkSTLReader()
×
57

58
            elif filename.endswith('.ply'):
×
59
                self.reader = vtk.vtkPLYReader()
×
60

61
            elif filename.endswith('.vtp'):
×
62
                self.reader = vtk.vtkXMLPolyDataReader()
×
63
            else:
64
                raise ValueError(
×
65
                    f'File type not supported for model loading: {filename}')
66

67
            self.reader.SetFileName(filename)
×
68
            self.reader.Update()
×
69
            self.source = self.reader.GetOutput()
×
70

71
            self.source_file = filename
×
72
            self.name = os.path.basename(self.source_file)
×
73
        else:
74
            # Creates a new empty vtkPolyData, that the client
75
            # can dynamically fill with new data.
76
            self.source = vtk.vtkPolyData()
×
77
            self.source_file = ""
×
78
            self.name = ""
×
79

80
        # Only create normals if there are none on input
81
        self.normals = None
×
82
        if self.source.GetPointData().GetNormals() is None:
×
83
            self.normals = vtk.vtkPolyDataNormals()
×
84
            self.normals.SetInputData(self.source)
×
85
            self.normals.SetAutoOrientNormals(True)
×
86
            self.normals.SetFlipNormals(False)
×
87
        self.transform = vtk.vtkTransform()
×
88
        self.transform.Identity()
×
89
        self.transform_filter = vtk.vtkTransformPolyDataFilter()
×
90
        if self.normals is None:
×
91
            self.transform_filter.SetInputData(self.source)
×
92
        else:
93
            self.transform_filter.SetInputConnection(
×
94
                self.normals.GetOutputPort())
95
        self.transform_filter.SetTransform(self.transform)
×
96
        self.mapper = vtk.vtkPolyDataMapper()
×
97
        self.mapper.SetInputConnection(self.transform_filter.GetOutputPort())
×
98
        self.mapper.Update()
×
99
        self.actor.SetMapper(self.mapper)
×
100
        self.no_shading = False
×
101
        self.ambient = self.actor.GetProperty().GetAmbient()
×
102
        self.diffuse = self.actor.GetProperty().GetDiffuse()
×
103
        self.specular = self.actor.GetProperty().GetSpecular()
×
104

105
    def get_no_shading(self):
4✔
106
        """
107
        Returns whether or not this model is rendered with or without shading.
108
        :return: bool
109
        """
110
        return self.no_shading
×
111

112
    def set_no_shading(self, no_shading: bool):
4✔
113
        """
114
        Turns off/on all shading, so you can generate masks, with solid blocks
115
        of colour. Note: Even though I'm tempted to call this flat shading,
116
        you can't because flat shading is something different. So we have to
117
        call it "no shading".
118

119
        :param no_shading: if true, outputs solid blocks of colour
120
        """
121
        if no_shading:
×
122
            self.ambient = self.actor.GetProperty().GetAmbient()
×
123
            self.diffuse = self.actor.GetProperty().GetDiffuse()
×
124
            self.specular = self.actor.GetProperty().GetSpecular()
×
125
            self.actor.GetProperty().SetAmbient(1)
×
126
            self.actor.GetProperty().SetDiffuse(0)
×
127
            self.actor.GetProperty().SetSpecular(0)
×
128
        else:
129
            self.actor.GetProperty().SetAmbient(self.ambient)
×
130
            self.actor.GetProperty().SetDiffuse(self.diffuse)
×
131
            self.actor.GetProperty().SetSpecular(self.specular)
×
132
        self.no_shading = no_shading
×
133

134
    def set_model_transform(self, matrix):
4✔
135
        """
136
        Sets the model to world transform onto a vtkPolyDataFilter.
137
        This enables all the points and point data to be transformed
138
        according to a vtkMatrix4x4 similarity transform.
139

140
        :param matrix: vtkMatrix4x4
141
        """
142
        mu.validate_vtk_matrix_4x4(matrix)
×
143
        self.transform.SetMatrix(matrix)
×
144
        self.transform_filter.SetTransform(self.transform)
×
145
        self.transform_filter.Update()
×
146

147
    def get_model_transform(self):
4✔
148
        """
149
        Gets the model to world transform.
150
        :return: vtkMatrix4x4
151
        """
152
        return self.transform.GetMatrix()
×
153

154
    def get_source_file(self):
4✔
155
        """
156
        Returns the filename that the model was loaded from, or
157
        empty string if the VTKSurfaceModel was not made from a file.
158

159
        :return:str filename
160
        """
161
        return self.source_file
×
162

163
    def get_number_of_points(self):
4✔
164
        """
165
        Returns the number of points in the vtkPoylData.
166
        :return: unsigned int
167
        """
168
        self.transform_filter.Update()
×
169
        number_of_points = self.transform_filter.GetOutput().GetNumberOfPoints()
×
170
        return number_of_points
×
171

172
    def get_points_as_numpy(self):
4✔
173
        """
174
        Returns the vtkPolyData points as a numpy array.
175
        :return: nx3 numpy ndarray
176
        """
177
        self.transform_filter.Update()
×
178
        vtk_points = self.transform_filter.GetOutput().GetPoints()
×
179
        as_numpy = numpy_support.vtk_to_numpy(vtk_points.GetData())
×
180
        return as_numpy
×
181

182
    def get_vtk_source_data(self) -> vtk.vtkPolyData:
4✔
183
        """
184
        Return original vtk poly data for this object
185

186
        :return: vtkPolyData
187
        :rtype: vtk.vtkPolyData
188
        """
189
        self.transform_filter.Update()
×
190
        return self.source
×
191

192
    def get_normals_as_numpy(self):
4✔
193
        """
194
         Returns the vtkPolyData point normals as a numpy array.
195
        :return: nx3 numpy ndarray
196
        """
197
        self.transform_filter.Update()
×
198
        vtk_normals = self.transform_filter \
×
199
            .GetOutput().GetPointData().GetNormals()
200
        as_numpy = numpy_support.vtk_to_numpy(vtk_normals)
×
201
        return as_numpy
×
202

203
    def set_texture(self, filename):
4✔
204
        """
205
        Sets an image from a file as a texture for the model.
206
        :param filename:
207
        :return:
208
        """
209
        # Read the texture image from a file.
210
        # Currently supports png and jpeg formats.
211
        if filename is not None:
×
212

213
            vf.validate_is_file(filename)
×
214

215
            if filename.endswith('.png'):
×
216
                self.texture_reader = vtk.vtkPNGReader()
×
217

218
            elif np.logical_or(filename.endswith('.jpeg'),
×
219
                               filename.endswith('.jpg')):
220
                self.texture_reader = vtk.vtkJPEGReader()
×
221

222
            else:
223
                raise ValueError(
×
224
                    f'File type not supported for texture loading: {filename}')
225

226
        else:
227
            # Unset texture when the function is called with None.
228
            self.texture_reader = None
×
229
            self.texture_file = None
×
230
            self.texture_name = None
×
231
            self.texture = None
×
232
            self.actor.SetTexture(None)
×
233
            return
×
234

235
        self.texture_reader.SetFileName(filename)
×
236
        self.texture_file = filename
×
237
        self.texture_name = os.path.basename(self.texture_file)
×
238

239
        # Create texture object.
240
        self.texture = vtk.vtkTexture()
×
241
        if vtk.VTK_MAJOR_VERSION <= 5:
×
242
            self.texture.SetInput(self.texture_reader.GetOutput())
×
243
        else:
244
            self.texture.SetInputConnection(self.texture_reader.GetOutputPort())
×
245

246
        # Set the texture
247
        self.actor.SetTexture(self.texture)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc