@@ -67,8 +67,8 @@ class FFD(object):
6767 >>> original_mesh_points = np.load('tests/test_datasets/meshpoints_sphere_orig.npy')
6868 >>> free_form = ffd.FFD(ffd_parameters, original_mesh_points)
6969 >>> free_form.perform()
70- >>> new_mesh_points = free_form.modified_mesh_points
71- """
70+ >>> new_mesh_points = free_form.modified_mesh_points
71+ """
7272 def __init__ (self , ffd_parameters , original_mesh_points ):
7373 self .parameters = ffd_parameters
7474 self .original_mesh_points = original_mesh_points
@@ -81,22 +81,31 @@ def perform(self):
8181 it sets `self.modified_mesh_points`.
8282
8383 .. todo::
84- In order to improve the performances, we need to perform the FFD only on the points inside
85- the lattice.
86- """
87- (n_rows_mesh , n_cols_mesh ) = self .original_mesh_points .shape
8884
85+ """
8986 # translation and then affine transformation
9087 translation = self .parameters .origin_box
9188
92- fisical_frame = np .array ([self .parameters .position_vertex_1 - translation , \
93- self .parameters .position_vertex_2 - translation , \
94- self .parameters .position_vertex_3 - translation , \
95- [0 , 0 , 0 ]])
89+ physical_frame = np .array ([self .parameters .position_vertex_1 - translation ,
90+ self .parameters .position_vertex_2 - translation ,
91+ self .parameters .position_vertex_3 - translation ,
92+ [0 , 0 , 0 ]])
9693 reference_frame = np .array ([[1 , 0 , 0 ], [0 , 1 , 0 ], [0 , 0 , 1 ], [0 , 0 , 0 ]])
9794
98- transformation = at .affine_points_fit (fisical_frame , reference_frame )
99- inverse_transformation = at .affine_points_fit (reference_frame , fisical_frame )
95+ transformation = at .affine_points_fit (physical_frame , reference_frame )
96+ inverse_transformation = at .affine_points_fit (reference_frame , physical_frame )
97+
98+ # apply transformation to original mesh points
99+ reference_frame_mesh_points = self ._transform_points (self .original_mesh_points - translation , transformation )
100+
101+ # select mesh points inside bounding box
102+ mesh_points = reference_frame_mesh_points [(reference_frame_mesh_points [:,0 ] >= 0. ) &
103+ (reference_frame_mesh_points [:,0 ] <= 1. ) &
104+ (reference_frame_mesh_points [:,1 ] >= 0. ) &
105+ (reference_frame_mesh_points [:,1 ] <= 1. ) &
106+ (reference_frame_mesh_points [:,2 ] >= 0. ) &
107+ (reference_frame_mesh_points [:,2 ] <= 1. )]
108+ (n_rows_mesh , n_cols_mesh ) = mesh_points .shape
100109
101110 # Initialization. In order to exploit the contiguity in memory the following are transposed
102111 (dim_n_mu , dim_m_mu , dim_t_mu ) = self .parameters .array_mu_x .shape
@@ -105,22 +114,19 @@ def perform(self):
105114 bernstein_z = np .zeros ((dim_t_mu , n_rows_mesh ))
106115 shift_mesh_points = np .zeros ((n_cols_mesh , n_rows_mesh ))
107116
108- reference_frame_mesh_points = self ._transform_points (self .original_mesh_points - translation , \
109- transformation )
110-
111117 for i in range (0 , dim_n_mu ):
112- aux1 = np .power ((1 - reference_frame_mesh_points [:, 0 ]), dim_n_mu - 1 - i )
113- aux2 = np .power (reference_frame_mesh_points [:, 0 ], i )
118+ aux1 = np .power ((1 - mesh_points [:, 0 ]), dim_n_mu - 1 - i )
119+ aux2 = np .power (mesh_points [:, 0 ], i )
114120 bernstein_x [i , :] = special .binom (dim_n_mu - 1 , i ) * np .multiply (aux1 , aux2 )
115121
116122 for i in range (0 , dim_m_mu ):
117- aux1 = np .power ((1 - reference_frame_mesh_points [:, 1 ]), dim_m_mu - 1 - i )
118- aux2 = np .power (reference_frame_mesh_points [:, 1 ], i )
123+ aux1 = np .power ((1 - mesh_points [:, 1 ]), dim_m_mu - 1 - i )
124+ aux2 = np .power (mesh_points [:, 1 ], i )
119125 bernstein_y [i , :] = special .binom (dim_m_mu - 1 , i ) * np .multiply (aux1 , aux2 )
120126
121127 for i in range (0 , dim_t_mu ):
122- aux1 = np .power ((1 - reference_frame_mesh_points [:, 2 ]), dim_t_mu - 1 - i )
123- aux2 = np .power (reference_frame_mesh_points [:, 2 ], i )
128+ aux1 = np .power ((1 - mesh_points [:, 2 ]), dim_t_mu - 1 - i )
129+ aux2 = np .power (mesh_points [:, 2 ], i )
124130 bernstein_z [i , :] = special .binom (dim_t_mu - 1 , i ) * np .multiply (aux1 , aux2 )
125131
126132
@@ -138,18 +144,22 @@ def perform(self):
138144 shift_mesh_points [0 , :] += aux_x
139145 shift_mesh_points [1 , :] += aux_y
140146 shift_mesh_points [2 , :] += aux_z
141-
142- # Splitting points inside and outside the lattice: TODO not very efficient
143- for i in range (0 , n_rows_mesh ):
144- if (reference_frame_mesh_points [i , 0 ] < 0 ) or (reference_frame_mesh_points [i , 1 ] < 0 ) \
145- or (reference_frame_mesh_points [i , 2 ] < 0 ) or (reference_frame_mesh_points [i , 0 ] > 1 ) \
146- or (reference_frame_mesh_points [i , 1 ] > 1 ) or (reference_frame_mesh_points [i , 2 ] > 1 ):
147- shift_mesh_points [:, i ] = 0
148-
149- # Here shift_mesh_points needs to be transposed to be summed with reference_frame_mesh_points
150- self .modified_mesh_points = self ._transform_points (np .transpose (shift_mesh_points ) + \
151- reference_frame_mesh_points , inverse_transformation ) + translation
152-
147+
148+ # shift_mesh_points needs to be transposed to be summed with mesh_points
149+ # apply inverse transformation to shifted mesh points
150+ new_mesh_points = self ._transform_points (np .transpose (shift_mesh_points ) +
151+ mesh_points , inverse_transformation ) + \
152+ translation
153+
154+ # merge non-shifted mesh points with shifted ones
155+ self .modified_mesh_points = np .copy (self .original_mesh_points )
156+ self .modified_mesh_points [(reference_frame_mesh_points [:,0 ] >= 0. ) &
157+ (reference_frame_mesh_points [:,0 ] <= 1. ) &
158+ (reference_frame_mesh_points [:,1 ] >= 0. ) &
159+ (reference_frame_mesh_points [:,1 ] <= 1. ) &
160+ (reference_frame_mesh_points [:,2 ] >= 0. ) &
161+ (reference_frame_mesh_points [:,2 ] <= 1. )] \
162+ = new_mesh_points
153163
154164 @staticmethod
155165 def _transform_points (original_points , transformation ):
@@ -170,3 +180,4 @@ def _transform_points(original_points, transformation):
170180 modified_points [i , :] = transformation (original_points [i ])
171181
172182 return modified_points
183+
0 commit comments