Skip to content

Commit 519512e

Browse files
added some new parameter and stl files
1 parent 92cc306 commit 519512e

File tree

10 files changed

+17182
-290
lines changed

10 files changed

+17182
-290
lines changed

pygem/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515

1616
from .deformation import Deformation
1717
from .ffd import FFD
18-
from .cffd import CFFD
19-
from .bffd import BFFD
20-
from .vffd import VFFD
18+
from .cffd import CFFD,BFFD,VFFD
2119
from .rbf import RBF
2220
from .idw import IDW
2321
from .rbf_factory import RBFFactory

pygem/bffd.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

pygem/cffd.py

Lines changed: 131 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from pygem.ffd import FFD
1313
import numpy as np
14-
14+
from scipy.optimize import LinearConstraint, differential_evolution
1515

1616
class CFFD(FFD):
1717
"""
@@ -42,10 +42,6 @@ class CFFD(FFD):
4242
:cvar numpy.ndarray fun_mask: a boolean tensor that tells to the class
4343
on which axis which constraint depends on. The tensor has shape (n_cons,3), where the last dimension indicates dependency on
4444
on x,y,z respectively. Default is all true. It used only in the triaffine mode.
45-
:cvar numpy.ndarray weight_matrix: a symmetric positive definite weigth matrix.
46-
It must be of row and column size the number of trues in the mask.
47-
It weights the movemement of the control points which have a true flag in the ffd_mask.
48-
Default is identity.
4945
5046
:Example:
5147
@@ -67,7 +63,7 @@ def __init__(self,
6763
fun,
6864
n_control_points=None,
6965
ffd_mask=None,
70-
fun_mask=None, weight_matrix=None):
66+
fun_mask=None):
7167
super().__init__(n_control_points)
7268

7369
if ffd_mask is None:
@@ -82,18 +78,18 @@ def __init__(self,
8278
self.fun_mask = np.full((self.num_cons, 3), True, dtype=bool)
8379
else:
8480
self.fun_mask = fun_mask
85-
86-
if weight_matrix is None:
87-
self.weight_matrix = np.eye(np.sum(self.ffd_mask))
88-
def _adjust_control_points_inner(self,src_pts,hyper_param):
81+
def adjust_control_points(self,src_pts):
8982
'''
90-
Adjust the FFD control points such that fun(ffd(src_pts))=fixval given a hyperparameter.
83+
Adjust the FFD control points such that fun(ffd(src_pts))=fixval
9184
9285
:param np.ndarray src_pts: the points whose deformation we want to be
9386
constrained.
9487
:rtype: None.
9588
'''
89+
hyper_param=self.fun_mask.copy().astype(float)
90+
hyper_param=hyper_param/np.sum(hyper_param,axis=1)
9691
mask_bak = self.ffd_mask.copy()
92+
fixval_bak=self.fixval.copy()
9793
diffvolume = self.fixval - self.fun(self.ffd(src_pts))
9894
for i in range(3):
9995
self.ffd_mask = np.full((*self.n_control_points, 3), False, dtype=bool)
@@ -118,19 +114,8 @@ def _adjust_control_points_inner(self,src_pts,hyper_param):
118114
saved_parameters[indices] = saved_parameters[indices] + deltax
119115
self._load_parameters(saved_parameters)
120116
self.ffd_mask = mask_bak.copy()
117+
self.fixval=fixval_bak.copy()
121118

122-
123-
def adjust_control_points(self,src_pts):
124-
'''
125-
Adjust the FFD control points such that fun(ffd(src_pts))=fixval
126-
127-
:param np.ndarray src_pts: the points whose deformation we want to be
128-
constrained.
129-
:rtype: None.
130-
'''
131-
hyper_param=self.fun_mask.copy().astype(float)
132-
hyper_param=hyper_param/np.sum(hyper_param,axis=1)
133-
self._adjust_control_points_inner(src_pts,hyper_param)
134119
def ffd(self, src_pts):
135120
'''
136121
Performs Classic Free Form Deformation.
@@ -199,3 +184,126 @@ def _compute_linear_map(self, src_pts, saved_parameters, indices):
199184
return A, b
200185

201186

187+
class BFFD(CFFD):
188+
'''
189+
Class that handles the Barycenter Free Form Deformation on the mesh points.
190+
191+
:param list n_control_points: number of control points in the x, y, and z
192+
direction. Default is [2, 2, 2].
193+
194+
:cvar numpy.ndarray box_length: dimension of the FFD bounding box, in the
195+
x, y and z direction (local coordinate system).
196+
:cvar numpy.ndarray box_origin: the x, y and z coordinates of the origin of
197+
the FFD bounding box.
198+
:cvar numpy.ndarray n_control_points: the number of control points in the
199+
x, y, and z direction.
200+
:cvar numpy.ndarray array_mu_x: collects the displacements (weights) along
201+
x, normalized with the box length x.
202+
:cvar numpy.ndarray array_mu_y: collects the displacements (weights) along
203+
y, normalized with the box length y.
204+
:cvar numpy.ndarray array_mu_z: collects the displacements (weights) along
205+
z, normalized with the box length z.
206+
:cvar callable fun: it defines the F of the constraint F(x)=c. Default is the constant 1 function.
207+
:cvar numpy.ndarray fixval: it defines the c of the constraint F(x)=c. Default is 1.
208+
:cvar numpy.ndarray mask: a boolean tensor that tells to the class
209+
which control points can be moved, and in what direction, to enforce the constraint.
210+
The tensor has shape (n_x,n_y,n_z,3), where the last dimension indicates movement
211+
on x,y,z respectively. Default is all true.
212+
213+
:Example:
214+
215+
>>> from pygem import BFFD
216+
>>> import numpy as np
217+
>>> b = np.random.rand(3)
218+
>>> bffd = BFFD(b, [2, 2, 2])
219+
>>> bffd.read_parameters('tests/test_datasets/parameters_test_ffd_sphere.prm')
220+
>>> original_mesh_points = np.load('tests/test_datasets/meshpoints_sphere_orig.npy')
221+
>>> bffd.adjust_control_points(original_mesh_points[:-4])
222+
>>> assert np.isclose(np.linalg.norm(bffd.fun(bffd.ffd(original_mesh_points[:-4])) - b), np.array([0.]))
223+
>>> new_mesh_points = bffd.ffd(original_mesh_points)
224+
'''
225+
226+
def __init__(self,
227+
fixval=None,
228+
n_control_points=None,
229+
ffd_mask=None):
230+
super().__init__(fixval,None,n_control_points,ffd_mask,None)
231+
232+
def linfun(x):
233+
return np.mean(x.reshape(-1, 3), axis=0)
234+
235+
self.fun = linfun
236+
self.fixval = fixval
237+
self.fun_mask = np.array([[True, False, False],
238+
[False, True, False],
239+
[False, False, True]])
240+
241+
242+
243+
class VFFD(CFFD):
244+
'''
245+
Class that handles the Volumetric Free Form Deformation on the mesh points.
246+
247+
:param list n_control_points: number of control points in the x, y, and z
248+
direction. Default is [2, 2, 2].
249+
:param string mode: it can be ``affine`` or ``triaffine``. The first option is for the F that are affine in all the coordinates of the points.
250+
The second one is for functions that are F in the coordinates of the points. The first option implies the second, but is optimal for that class of functions.
251+
:cvar numpy.ndarray box_length: dimension of the FFD bounding box, in the
252+
x, y and z direction (local coordinate system).
253+
:cvar numpy.ndarray box_origin: the x, y and z coordinates of the origin of
254+
the FFD bounding box.
255+
:cvar numpy.ndarray n_control_points: the number of control points in the
256+
x, y, and z direction.
257+
:cvar numpy.ndarray array_mu_x: collects the displacements (weights) along
258+
x, normalized with the box length x.
259+
:cvar numpy.ndarray array_mu_y: collects the displacements (weights) along
260+
y, normalized with the box length y.
261+
:cvar numpy.ndarray array_mu_z: collects the displacements (weights) along
262+
z, normalized with the box length z.
263+
:cvar callable fun: it defines the F of the constraint F(x)=c. Default is the constant 1 function.
264+
:cvar numpy.ndarray fixval: it defines the c of the constraint F(x)=c. Default is 1.
265+
:cvar numpy.ndarray ffd_mask: a boolean tensor that tells to the class
266+
which control points can be moved, and in what direction, to enforce the constraint.
267+
The tensor has shape (n_x,n_y,n_z,3), where the last dimension indicates movement
268+
on x,y,z respectively. Default is all true.
269+
:cvar numpy.ndarray fun_mask: a boolean tensor that tells to the class
270+
on which axis which constraint depends on. The tensor has shape (n_cons,3), where the last dimension indicates dependency on
271+
on x,y,z respectively. Default is all true. It used only in the triaffine mode.
272+
273+
:Example:
274+
275+
>>> from pygem import VFFD
276+
>>> import numpy as np
277+
>>> import meshio
278+
>>> mesh = meshio.read('tests/test_datasets/test_sphere.stl')
279+
>>> original_mesh_points = mesh.points
280+
>>> triangles = mesh.cells_dict["triangle"]
281+
>>> b = np.random.rand()
282+
>>> vffd = VFFD(triangles, b,[2, 2, 2])
283+
>>> vffd.read_parameters('tests/test_datasets/parameters_test_ffd_sphere.prm')
284+
>>> vffd.adjust_control_points(original_mesh_points)
285+
>>> new_mesh_points = vffd(original_mesh_points)
286+
>>> assert np.isclose(np.linalg.norm(vffd.fun(new_mesh_points) - b),np.array([0.]), atol=1e-07)
287+
288+
'''
289+
290+
def __init__(self,
291+
triangles,
292+
fixval,
293+
n_control_points=None,
294+
ffd_mask=None):
295+
super().__init__(fixval,None,n_control_points,ffd_mask,None)
296+
297+
self.triangles=triangles
298+
def volume_inn(x):
299+
return _volume(x,self.triangles)
300+
301+
self.fun = volume_inn
302+
self.fixval=fixval
303+
self.fun_mask=np.array([[True, True, True]])
304+
305+
def _volume(x,triangles):
306+
x = x.reshape(-1, 3)
307+
mesh = x[triangles]
308+
return np.array([np.sum(np.linalg.det(mesh))])
309+

pygem/vffd.py

Lines changed: 0 additions & 77 deletions
This file was deleted.

tests/test_bffd.py

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)