88 *Sederberg, Thomas W., and Scott R. Parry. "Free-form deformation of solid
99 geometric models." ACM SIGGRAPH computer graphics 20.4 (1986): 151-160*. It
1010 consists in three different step:
11-
11+
1212 - Mapping the physical domain to the reference one with map
1313 :math:`\\ boldsymbol{\\ psi}`. In the code it is named *transformation*.
1414
1515 - Moving some control points to deform the lattice with :math:`\\ hat{T}`.
16- The movement of the control points is basically the weight (or displacement)
17- :math:`\\ boldsymbol{\\ mu}` we set in the *parameters file*.
16+ The movement of the control points is basically the weight (or
17+ displacement) :math:`\\ boldsymbol{\\ mu}` we set in the *parameters file*.
1818
1919 - Mapping back to the physical domain with map
2020 :math:`\\ boldsymbol{\\ psi}^{-1}`. In the code it is named
3535 where :math:`\\ mathsf{b}_{lmn}` are Bernstein polynomials. We improve the
3636 traditional version by allowing a rotation of the FFD lattice in order to
3737 give more flexibility to the tool.
38-
38+
3939 You can try to add more shapes to the lattice to allow more and more
4040 involved transformations.
4141
4242"""
43- try :
44- import configparser as configparser
45- except ImportError :
46- import ConfigParser as configparser
43+
4744import numpy as np
48- from OCC .Core .TopoDS import (TopoDS_Shape , topods_Compound , \
45+ from OCC .Core .TopoDS import (TopoDS_Shape , topods_Wire , \
4946 TopoDS_Compound , topods_Face , \
50- TopoDS_Face , topods_Wire , \
51- TopoDS_Wire , topods_Edge )
47+ topods_Edge )
5248from OCC .Core .BRep import BRep_Builder
5349from OCC .Core .TopExp import TopExp_Explorer
5450from OCC .Core .TopAbs import (TopAbs_EDGE , TopAbs_FACE , TopAbs_WIRE )
@@ -100,7 +96,7 @@ class FFD(OriginalFFD):
10096 >>> import pygem.params as ffdp
10197 >>> import numpy as np
10298 >>> ffd = FFD()
103- >>> ffd.read_parameters('tests/test_datasets/parameters_test_ffd_sphere.prm ')
99+ >>> ffd.read_parameters('tests/test_datasets/test_pipe.iges ')
104100 >>> input_cad_file_name = "input.iges"
105101 >>> modified_cad_file_name = "output.iges"
106102 >>> ffd(input_cad_file_name,modified_cad_file_name)
@@ -125,7 +121,7 @@ def __call__(self, obj, dst=None):
125121
126122
127123
128-
124+
129125 #create compound to store modified faces
130126 compound_builder = BRep_Builder ()
131127 compound = TopoDS_Compound ()
@@ -139,7 +135,8 @@ def __call__(self, obj, dst=None):
139135 faces_explorer = TopExp_Explorer (shape , TopAbs_FACE )
140136
141137 while faces_explorer .More ():
142- # performing some conversions to get the right format (BSplineSurface)
138+ # performing some conversions to get the right
139+ # format (BSplineSurface)
143140 print ("Processing face " , faceCount )
144141 face = topods_Face (faces_explorer .Current ())
145142 nurbs_converter = BRepBuilderAPI_NurbsConvert (face )
@@ -150,15 +147,18 @@ def __call__(self, obj, dst=None):
150147 bounds = brep_face .Bounds ()
151148
152149 bspline_face = geomconvert_SurfaceToBSplineSurface (brep_face )
153- # we will then add an amount of nodes that will grant us our prescribed resolution both along u and v
154- uKnotsToAdd = 30 ;
155- vKnotsToAdd = 30 ;
150+ # we will then add an amount of nodes that will grant
151+ # us our prescribed resolution both along u and v
152+ uKnotsToAdd = 30
153+ vKnotsToAdd = 30
156154 print ("Added U knots: " , uKnotsToAdd )
157155 print ("Added V knots: " , vKnotsToAdd )
158156 for i in range (uKnotsToAdd ):
159- bspline_face .InsertUKnot (bounds [0 ]+ i * (bounds [1 ]- bounds [0 ])/ uKnotsToAdd , 1 , 1e-7 )
157+ bspline_face .InsertUKnot (bounds [0 ]+ \
158+ i * (bounds [1 ]- bounds [0 ])/ uKnotsToAdd , 1 , 1e-7 )
160159 for i in range (vKnotsToAdd ):
161- bspline_face .InsertVKnot (bounds [2 ]+ i * (bounds [3 ]- bounds [2 ])/ vKnotsToAdd , 1 , 1e-7 )
160+ bspline_face .InsertVKnot (bounds [2 ]+ \
161+ i * (bounds [3 ]- bounds [2 ])/ vKnotsToAdd , 1 , 1e-7 )
162162
163163 # openCascade object
164164 occ_face = bspline_face
@@ -169,7 +169,7 @@ def __call__(self, obj, dst=None):
169169 u_max = bounds [1 ]
170170 v_min = bounds [2 ]
171171 v_max = bounds [3 ]
172- center = occ_face .Value ((u_min + u_max )/ 2.0 ,(v_min + v_max )/ 2.0 )
172+ center = occ_face .Value ((u_min + u_max )/ 2.0 , (v_min + v_max )/ 2.0 )
173173 print ("Face Center: " , center .X (), center .Y (), center .Z ())
174174
175175 # extract the Control Points of each face
@@ -183,52 +183,59 @@ def __call__(self, obj, dst=None):
183183 for pole_v_direction in range (n_poles_v ):
184184 control_point_coordinates = occ_face .Pole (\
185185 pole_u_direction + 1 , pole_v_direction + 1 )
186- control_polygon_coordinates [i , :] = [control_point_coordinates .X (),\
187- control_point_coordinates .Y (),\
188- control_point_coordinates .Z ()]
189- i += 1
186+ control_polygon_coordinates [i , :] = \
187+ [control_point_coordinates .X (),\
188+ control_point_coordinates .Y (),\
189+ control_point_coordinates .Z ()]
190+ i += 1
190191
191- ## SURFACES PHASE #####################################################
192+ ## SURFACES PHASE ###############################################
192193 src_pts = control_polygon_coordinates
193194 new_pts = super ().__call__ (src_pts ) # dont touch this line
194-
195+
195196 i = 0
196197 for pole_u_direction in range (n_poles_u ):
197198 for pole_v_direction in range (n_poles_v ):
198- control_point = gp_Pnt (new_pts [i ,0 ],
199- new_pts [i ,1 ],
200- new_pts [i ,2 ])
201- occ_face .SetPole (pole_u_direction + 1 , pole_v_direction + 1 , control_point )
199+ control_point = gp_Pnt (new_pts [i , 0 ],
200+ new_pts [i , 1 ],
201+ new_pts [i , 2 ])
202+ occ_face .SetPole (pole_u_direction + 1 ,
203+ pole_v_direction + 1 ,
204+ control_point )
202205 i += 1
203- # through moving the control points, we now changed the SURFACE of the FACE we are processing
204- # we now need to obtain the curves (actually, the WIRES) that define the bounds of the surface and TRIM the surface
205- # with them, to obtain the new face
206-
207- # we start creating a face with the modified surface. we will later cut this new face with all the wires
208- # that the original face had
209- # this tolerance can be moved among the function parameters
206+ # through moving the control points, we now changed the SURFACE
207+ # of the FACE we are processing we now need to obtain the curves
208+ # (actually, the WIRES) that define the bounds of the surface and
209+ # TRIM the surface with them, to obtain the new face
210+
211+ # we start creating a face with the modified surface. we will
212+ #later cut this new face with all the wires that the original
213+ # face had this tolerance can be moved among the function
214+ # parameters
210215 tolerance = 1e-2
211216 brep = BRepBuilderAPI_MakeFace (occ_face , tolerance ).Face ()
212217
213-
218+
214219 # we here start looping on the wires of the original face
215- # in this first loop we do nothing but count the wires in this face
216- # few faces have more than one wire: if they have, it is because they have holes, and
217- # if this is the case one wire is the outer, and the others are the inner ones.
220+ # in this first loop we do nothing but count the wires in this
221+ # face few faces have more than one wire: if they have, it is
222+ # because they have holes, and if this is the case one wire
223+ # is the outer, and the others are the inner ones.
218224 # the loop will also tell us which wire is the outer one
219225 wire_count = 0
220226 wire_explorer = TopExp_Explorer (face_aux , TopAbs_WIRE )
221227 while wire_explorer .More ():
222228 wire = topods_Wire (wire_explorer .Current ())
223- if ( wire == breptools_OuterWire (face_aux ) ):
229+ if wire == breptools_OuterWire (face_aux ):
224230 print ("Wire" , wire_count + 1 , "is outer wire" )
225231 wire_count += 1
226232 wire_explorer .Next ()
227- print ("This face has " ,wire_count ," wires" )
228-
233+ print ("This face has " , wire_count , " wires" )
234+
229235 #we now start really looping on the wires
230236 #we will create a single curve joining all the edges in the wire
231- # the curve must be a bspline curve so we need to make conversions through all the way
237+ # the curve must be a bspline curve so we need to make conversions
238+ # through all the way
232239 wire_count = 0
233240 outer_wires = []
234241 inner_wires = []
@@ -238,107 +245,117 @@ def __call__(self, obj, dst=None):
238245 wire = topods_Wire (wire_explorer .Current ())
239246 h_bspline_edge = GeomConvert_CompCurveToBSplineCurve ()
240247 edge_explorer = TopExp_Explorer (wire , TopAbs_EDGE )
241- edgesCount = 0
248+ edgesCount = 0
242249 while edge_explorer .More ():
243- # performing some conversions to get the right format (BSplineSurface)
250+ # performing some conversions to get the right format
251+ # (BSplineSurface)
244252 edge = topods_Edge (edge_explorer .Current ())
245- if ( BRep_Tool .Degenerated (edge ) == False ):
253+ if not BRep_Tool .Degenerated (edge ):
246254 bspline_converter = BRepBuilderAPI_NurbsConvert (edge )
247255 bspline_converter .Perform (edge )
248256 bspline_tshape_edge = bspline_converter .Shape ()
249- h_geom_edge , a , b = BRep_Tool_Curve (topods_Edge (bspline_tshape_edge ))
250- this_bspline_edge = geomconvert_CurveToBSplineCurve (h_geom_edge )
257+ h_geom_edge , a , b = \
258+ BRep_Tool_Curve (topods_Edge (bspline_tshape_edge ))
259+ this_bspline_edge = \
260+ geomconvert_CurveToBSplineCurve (h_geom_edge )
251261 bspline_geom_edge = this_bspline_edge
252- h_bspline_edge .Add (this_bspline_edge ,tolerance )
262+ h_bspline_edge .Add (this_bspline_edge , tolerance )
253263 edgesCount += 1
254264
255265 edge_explorer .Next ()
256-
266+
257267 bspline_geom_hedge = h_bspline_edge .BSplineCurve ()
258268 bspline_geom_edge = bspline_geom_hedge
259- unified_edge = BRepBuilderAPI_MakeEdge (bspline_geom_hedge ).Edge ()
260269
261- # number of knots is enriched here: this can become a user prescribed parameter for the class
270+ # number of knots is enriched here: this can become a user
271+ # prescribed parameter for the class
262272 knotsToAdd = 30
263273 firstParam = bspline_geom_edge .FirstParameter ()
264274 lastParam = bspline_geom_edge .LastParameter ()
265275 for i in range (knotsToAdd ):
266- bspline_geom_edge .InsertKnot (firstParam + i * (lastParam - firstParam )/ knotsToAdd ,1 ,1e-7 )
276+ bspline_geom_edge .InsertKnot (firstParam + \
277+ i * (lastParam - firstParam )/ knotsToAdd , 1 , 1e-7 )
267278 shapesList = TopTools_ListOfShape ()
268279 # openCascade object
269280 occ_edge = bspline_geom_edge
270281
271282 # extract the Control Points of each face
272283 n_poles = occ_edge .NbPoles ()
273284 control_polygon_coordinates = np .zeros (\
274- shape = (n_poles , 3 ))
275- # cycle over the poles to get their coordinates. The idea here is to move poles
276- # coordinates to deform the curves
285+ shape = (n_poles , 3 ))
286+ # cycle over the poles to get their coordinates. The idea here
287+ # is to move poles coordinates to deform the curves
277288 i = 0
278289 for pole in range (n_poles ):
279290 control_point_coordinates = occ_edge .Pole (pole + 1 )
280- control_polygon_coordinates [i , :] = [control_point_coordinates .X (),\
281- control_point_coordinates .Y (),\
282- control_point_coordinates .Z ()]
283- i += 1
291+ control_polygon_coordinates [i , :] = \
292+ [control_point_coordinates .X (), \
293+ control_point_coordinates .Y (), \
294+ control_point_coordinates .Z ()]
295+ i += 1
284296
285- ## CURVES PHASE #######################################################
297+ ## CURVES PHASE ############################################
286298 src_pts = control_polygon_coordinates
287299 new_pts = super ().__call__ (src_pts ) # dont touch this line
288300 # save here the `new_pts` into the shape
289- ## END CURVES #########################################################
301+ ## END CURVES ##############################################
290302
291303 i = 0
292304 for pole in range (n_poles ):
293- control_point = gp_Pnt (new_pts [i ,0 ],
294- new_pts [i ,1 ],
295- new_pts [i ,2 ])
305+ control_point = gp_Pnt (new_pts [i , 0 ],
306+ new_pts [i , 1 ],
307+ new_pts [i , 2 ])
296308 occ_edge .SetPole (pole + 1 , control_point )
297309 i += 1
298-
299- modified_edge = BRepBuilderAPI_MakeEdge (occ_edge ).Edge ()
310+
311+ modified_edge = BRepBuilderAPI_MakeEdge (occ_edge ).Edge ()
300312 shapesList .Append (modified_edge )
301313
302314 wire_maker = BRepBuilderAPI_MakeWire ()
303315 wire_maker .Add (shapesList )
304316 result_wire = wire_maker .Wire ()
305317 iges_handler = IgesHandler ()
306- iges_handler .write_shape_to_file (result_wire , "face_" + str (faceCount )+ "_wire_" + str (wire_count )+ ".iges" )
307-
308- # now, the wire can be outer or inner. we store the outer and (possible) inner ones in different lists
309- # this is because we first need to trim the surface using the outer wire, and then we can trim it
310- # with the wires corresponding to all the holes. if this is not done, the procedure will not work
311- if (wire == breptools_OuterWire (face_aux )):
318+ iges_handler .write_shape_to_file (result_wire , "face_" + \
319+ str (faceCount )+ "_wire_" + \
320+ str (wire_count )+ ".iges" )
321+
322+ # now, the wire can be outer or inner. we store the outer
323+ # and (possible) inner ones in different lists
324+ # this is because we first need to trim the surface
325+ # using the outer wire, and then we can trim it
326+ # with the wires corresponding to all the holes. if this
327+ # is not done, the procedure will not work
328+ if wire == breptools_OuterWire (face_aux ):
312329 outer_wires .append (result_wire )
313330 else :
314331 inner_wires .append (result_wire )
315332 wire_count += 1
316333 wire_explorer .Next ()
317334
318335
319- # so once we finished looping on all the wires to modify them, we use the only outer one to trim the surface
320- face_maker = BRepBuilderAPI_MakeFace (occ_face ,outer_wires [0 ])
336+ # so once we finished looping on all the wires to modify them,
337+ # we use the only outer one to trim the surface
338+ face_maker = BRepBuilderAPI_MakeFace (occ_face , outer_wires [0 ])
321339
322340 # and then add all other inner wires for the holes
323341 for inner_wire in inner_wires :
324342 face_maker .Add (inner_wire )
325343
326-
344+
327345 # finally, we get our trimmed face with all its holes
328346 brep_surf = face_maker .Face ()
329347
330-
348+
331349 compound_builder .Add (compound , brep_surf )
332350 face_list .append (brep_surf )
333-
334-
351+
335352 # and move to the next face
336353 faceCount += 1
337354 faces_explorer .Next ()
338-
339355
340356
341- ## END SURFACES #######################################################
357+
358+ ## END SURFACES #################################################
342359
343360
344361
@@ -349,5 +366,5 @@ def __call__(self, obj, dst=None):
349366 # save the shape exactly to the filename, aka `dst`
350367 iges_handler = IgesHandler ()
351368 iges_handler .write_shape_to_file (compound , dst )
352- else :
369+ else :
353370 return compound
0 commit comments