Skip to content

Commit ea75e6f

Browse files
author
Andrea Mola
committed
implemented CAD TopoDS_Shape modification in FFD CAD. Added corresponding tests to test_ffd.py. Fixed igeshandler.py and stephandler.py and corresponding tests
1 parent 603a48b commit ea75e6f

File tree

7 files changed

+121
-124
lines changed

7 files changed

+121
-124
lines changed

pygem/cad/ffd.py

Lines changed: 62 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,23 @@
4747
import os
4848
import numpy as np
4949
from scipy import special
50-
from OCC.Core.TopoDS import TopoDS_Shape, TopoDS_Compound
51-
50+
from OCC.TopoDS import TopoDS_Shape, topods_Compound, TopoDS_Compound, topods_Face, TopoDS_Face, topods_Wire, TopoDS_Wire, topods_Edge, TopoDS_Edge
51+
from OCC.BRep import (BRep_Builder)
52+
from OCC.TopExp import TopExp_Explorer
53+
from OCC.TopAbs import TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE, TopAbs_WIRE
54+
from OCC.TopTools import TopTools_ListOfShape
55+
from OCC.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeVertex, BRepBuilderAPI_NurbsConvert
56+
from OCC.BRep import BRep_Tool, BRep_Tool_Curve
57+
from OCC.GeomConvert import geomconvert_SurfaceToBSplineSurface, geomconvert_CurveToBSplineCurve, GeomConvert_CompCurveToBSplineCurve
58+
from OCC.gp import gp_Pnt
59+
from OCC.BRepTools import breptools_OuterWire
60+
61+
62+
from OCC.IGESControl import IGESControl_Reader, IGESControl_Writer
63+
64+
5265
from pygem import FFD as OriginalFFD
66+
from pygem.cad.igeshandler import IgesHandler
5367

5468
class FFD(OriginalFFD):
5569
"""
@@ -89,14 +103,15 @@ class FFD(OriginalFFD):
89103
>>> new = free_form.modified_mesh_points
90104
"""
91105

92-
def __call__(self, obj):
106+
def __call__(self, obj,dst=None):
93107
"""
94108
This method performs the deformation on the CAD file.
95109
"""
96110

97111
# Manage input
98112
if isinstance(obj, str): # if a input filename is passed
99-
shape = # extract topo_shape from filename
113+
iges_handler = IgesHandler()
114+
shape = iges_handler.load_shape_from_file(obj)
100115
elif isinstance(obj, TopoDS_Shape):
101116
shape = obj
102117
# Maybe do we need to handle also Compound?
@@ -105,31 +120,35 @@ def __call__(self, obj):
105120

106121
print("Modifying faces")
107122

123+
124+
tol = 1e-5
125+
126+
#create compound to store modified faces
108127
compound_builder = BRep_Builder()
109-
compound = OCC.TopoDS.TopoDS_Compound()
128+
compound = TopoDS_Compound()
110129
compound_builder.MakeCompound(compound)
111130

131+
112132
# cycle on the faces to get the control points
113133
# init some quantities
114134
faceCount = 0
115135
face_list = []
116136
control_point_position = [0]
117-
faces_explorer = TopExp_Explorer(color, TopAbs_FACE)
137+
faces_explorer = TopExp_Explorer(shape, TopAbs_FACE)
118138
mesh_points = np.zeros(shape=(0, 3))
119139

120140
while faces_explorer.More():
121141
points_orig = []
122142
points_def = []
123143
# performing some conversions to get the right format (BSplineSurface)
124144
print("Processing face ",faceCount)
125-
face = OCC.TopoDS.topods_Face(faces_explorer.Current())
145+
face = topods_Face(faces_explorer.Current())
126146
nurbs_converter = BRepBuilderAPI_NurbsConvert(face)
127147
nurbs_converter.Perform(face)
128148
nurbs_face = nurbs_converter.Shape()
129-
face_aux = OCC.TopoDS.topods_Face(nurbs_face)
130-
int_tools = IntTools_FClass2d(face_aux, 1e-3)
131-
brep_face = BRep_Tool.Surface(OCC.TopoDS.topods_Face(nurbs_face))
132-
old_brep_face = BRep_Tool.Surface(OCC.TopoDS.topods_Face(nurbs_face))
149+
face_aux = topods_Face(nurbs_face)
150+
brep_face = BRep_Tool.Surface(topods_Face(nurbs_face))
151+
old_brep_face = BRep_Tool.Surface(topods_Face(nurbs_face))
133152

134153
bounds = 0.0
135154
bounds = brep_face.GetObject().Bounds()
@@ -156,14 +175,13 @@ def __call__(self, obj):
156175
v_min = bounds[2]
157176
v_max = bounds[3]
158177
center = occ_face.Value((u_min+u_max)/2.0,(v_min+v_max)/2.0)
159-
print("*Center: ",center.X(),center.Y(),center.Z())
178+
print("Face Center: ",center.X(),center.Y(),center.Z())
160179

161180
# extract the Control Points of each face
162181
n_poles_u = occ_face.NbUPoles()
163182
n_poles_v = occ_face.NbVPoles()
164183
control_polygon_coordinates = np.zeros(\
165184
shape=(n_poles_u * n_poles_v, 3))
166-
#print("Number of poles: ", n_poles_u * n_poles_v)
167185
# cycle over the poles to get their coordinates
168186
i = 0
169187
for pole_u_direction in range(n_poles_u):
@@ -173,76 +191,67 @@ def __call__(self, obj):
173191
control_polygon_coordinates[i, :] = [control_point_coordinates.X(),\
174192
control_point_coordinates.Y(),\
175193
control_point_coordinates.Z()]
176-
177-
#control_point = gp_Pnt(control_point_coordinates.X(),\
178-
#control_point_coordinates.Y(),control_point_coordinates.Z())
179-
#display.DisplayShape(BRepBuilderAPI_MakeVertex(control_point).Vertex(),update=True)
180-
#print("Original: ",control_point.X()," ",control_point.Y()," ",control_point.Z())
181194
i+=1
182-
183195

184-
#orig_control_polygon_coordinates = deepcopy(control_polygon_coordinates)
185196
## SURFACES PHASE #####################################################
186197
src_pts = control_polygon_coordinates
187198
new_pts = super().__call__(src_pts) # dont touch this line
199+
188200
i = 0
189201
for pole_u_direction in range(n_poles_u):
190202
for pole_v_direction in range(n_poles_v):
191-
control_point = gp_Pnt(control_polygon_coordinates[i,0],
192-
control_polygon_coordinates[i,1],
193-
control_polygon_coordinates[i,2])
203+
control_point = gp_Pnt(new_pts[i,0],
204+
new_pts[i,1],
205+
new_pts[i,2])
194206
occ_face.SetPole(pole_u_direction + 1, pole_v_direction + 1, control_point)
195207
i += 1
196208
# through moving the control points, we now changed the SURFACE of the FACE we are processing
197209
# we now need to obtain the curves (actually, the WIRES) that define the bounds of the surface and TRIM the surface
198210
# with them, to obtain the new face
199211

200-
faceFilling = BRepFill_Filling()
201212
# we start creating a face with the modified surface. we will cut this new face with all the wires
202213
# that the original face had
203214
brep = BRepBuilderAPI_MakeFace(occ_face.GetHandle(), tol).Face()
204-
#IGESControl_Controller_Init()
205-
#writer = IGESControl_Writer()
206-
#writer.AddShape(brep)
207-
#nomefile = "untrimmed_face"+str(faceCount)+".iges"
208-
#writer.Write(nomefile)
215+
209216

210217
# we here start looping on the wires of the original face
211-
# in this forst loop we do nothing but count the wires in this face
218+
# in this first loop we do nothing but count the wires in this face
212219
# few faces have more than one wire: if they have, it is because they have holes, and
213220
# if this is the case one wire is the outer, and the others are the inner ones.
214221
# the loop will also tell us which wire is the outer one
215222
wire_count = 0
216223
wire_explorer = TopExp_Explorer(face_aux, TopAbs_WIRE)
217224
while wire_explorer.More():
218-
wire = OCC.TopoDS.topods_Wire(wire_explorer.Current())
225+
wire = topods_Wire(wire_explorer.Current())
219226
if (wire == breptools_OuterWire(face_aux)):
220227
print("Wire", wire_count+1, "is outer wire")
221228
wire_count += 1
222229
wire_explorer.Next()
223230
print("This face has ",wire_count," wires")
224231

225232
#we now start really looping on the wires
233+
#we will create a single curve joining all the edges in the wire
234+
# the curve must be a bspline curve so we need to make conversions through all the way
226235
wire_count = 0
227236
outer_wires = []
228237
inner_wires = []
229238
brep_face = BRep_Tool.Surface(brep)
230239
wire_explorer = TopExp_Explorer(face_aux, TopAbs_WIRE)
231240
while wire_explorer.More():
232-
wire = OCC.TopoDS.topods_Wire(wire_explorer.Current())
241+
wire = topods_Wire(wire_explorer.Current())
233242
wire_count += 1
234243
h_bspline_edge = GeomConvert_CompCurveToBSplineCurve()
235244
edge_explorer = TopExp_Explorer(wire, TopAbs_EDGE)
236245
edgesCount=0
237246
while edge_explorer.More():
238247
# performing some conversions to get the right format (BSplineSurface)
239248
#print("Edge in curve: ", edgesCount)
240-
edge = OCC.TopoDS.topods_Edge(edge_explorer.Current())
249+
edge = topods_Edge(edge_explorer.Current())
241250
if (BRep_Tool.Degenerated(edge) == False):
242251
bspline_converter = BRepBuilderAPI_NurbsConvert(edge)
243252
bspline_converter.Perform(edge)
244253
bspline_tshape_edge = bspline_converter.Shape()
245-
h_geom_edge, a, b = BRep_Tool_Curve(OCC.TopoDS.topods_Edge(bspline_tshape_edge))
254+
h_geom_edge, a, b = BRep_Tool_Curve(topods_Edge(bspline_tshape_edge))
246255
this_bspline_edge = geomconvert_CurveToBSplineCurve(h_geom_edge)
247256
bspline_geom_edge = this_bspline_edge.GetObject()
248257
h_bspline_edge.Add(this_bspline_edge,1e-4)
@@ -253,29 +262,11 @@ def __call__(self, obj):
253262
bspline_geom_hedge = h_bspline_edge.BSplineCurve()
254263
bspline_geom_edge = bspline_geom_hedge.GetObject()
255264
unified_edge = BRepBuilderAPI_MakeEdge(bspline_geom_hedge).Edge()
256-
#aa = bspline_geom_edge.FirstParameter()
257-
#bb = bspline_geom_edge.LastParameter()
258-
#print("Unif. Edge First Point:", bspline_geom_edge.Value(aa).X(),
259-
#bspline_geom_edge.Value(aa).Y(),
260-
#bspline_geom_edge.Value(aa).Z())
261-
#print("Unif. Edge Last Point:", bspline_geom_edge.Value(bb).X(),
262-
#bspline_geom_edge.Value(bb).Y(),
263-
#bspline_geom_edge.Value(bb).Z())
264-
#unified_edge = BRepBuilderAPI_MakeEdge(bspline_geom_hedge).Edge()
265-
#print("SAVING UNIFIED CURVE: ", curve_count)
266-
#IGESControl_Controller_Init()
267-
#writer = IGESControl_Writer()
268-
#writer.AddShape(unified_edge)
269-
#filename = nomedir+"unfied_curve_"+str(curve_count)+".iges"
270-
##print(filename)
271-
#writer.Write(filename)
272-
273265

266+
# number of knots is enriched here: this can become a user prescribed parameter for the class
267+
knotsToAdd = 200
274268
firstParam = bspline_geom_edge.FirstParameter()
275269
lastParam = bspline_geom_edge.LastParameter()
276-
#print("First Parameter: ", firstParam)
277-
#print("Last Parameter: ", lastParam)
278-
knotsToAdd = 200
279270
for i in range(knotsToAdd):
280271
bspline_geom_edge.InsertKnot(firstParam+i*(lastParam-firstParam)/knotsToAdd,1,1e-7)
281272
shapesList = TopTools_ListOfShape()
@@ -286,7 +277,6 @@ def __call__(self, obj):
286277
n_poles = occ_edge.NbPoles()
287278
control_polygon_coordinates = np.zeros(\
288279
shape=(n_poles , 3))
289-
#print("Number of poles: ", n_poles)
290280
# cycle over the poles to get their coordinates. The idea here is to move poles
291281
# coordinates to deform the curves
292282
i = 0
@@ -295,44 +285,29 @@ def __call__(self, obj):
295285
control_polygon_coordinates[i, :] = [control_point_coordinates.X(),\
296286
control_point_coordinates.Y(),\
297287
control_point_coordinates.Z()]
298-
#control_point = gp_Pnt(control_point_coordinates.X(),\
299-
#control_point_coordinates.Y(),control_point_coordinates.Z())
300-
#orig_control_point = control_point
301-
#display.DisplayShape(BRepBuilderAPI_MakeVertex(control_point).Vertex(),update=True)
302-
#print("Original: ",control_point.X()," ",control_point.Y()," ",control_point.Z())
288+
i+=1
303289

304290
## CURVES PHASE #######################################################
305-
src_pts = control_point_coordinates
306-
291+
src_pts = control_polygon_coordinates
307292
new_pts = super().__call__(src_pts) # dont touch this line
308-
309293
# save here the `new_pts` into the shape
310294
## END CURVES #########################################################
311295

312296
i = 0
313297
for pole in range(n_poles):
314-
#print("Function test:", mod_test_control_point.X(),mod_test_control_point.Y(),mod_test_control_point.Z())
315-
#print("**")
316-
control_point = gp_Pnt(control_polygon_coordinates[i,0],
317-
control_polygon_coordinates[i,1],
318-
control_polygon_coordinates[i,2])
298+
control_point = gp_Pnt(new_pts[i,0],
299+
new_pts[i,1],
300+
new_pts[i,2])
319301
occ_edge.SetPole(pole + 1, control_point)
320302
i += 1
321303

322-
#occ_new_hedge = geomprojlib.Project(occ_edge.GetHandle(),occ_face.GetHandle())
323-
#new_curve = occ_new_hedge.GetObject()
324-
#print("??", new_curve.IsClosed())
325304
modified_edge= BRepBuilderAPI_MakeEdge(occ_edge.GetHandle()).Edge()
326305
shapesList.Append(modified_edge)
327-
#if new_curve.IsClosed()==False:
328-
#fixer_edge = BRepBuilderAPI_MakeEdge(new_curve.Value(new_curve.LastParameter()),new_curve.Value(new_curve.FirstParameter())).Edge()
329-
#shapesList.Append(fixer_edge)
330-
#display.DisplayShape(modified_edge,update=True,color="BLUE1")
331-
306+
332307
wire_maker = BRepBuilderAPI_MakeWire()
333308
wire_maker.Add(shapesList)
334309
result_wire = wire_maker.Wire()
335-
310+
336311

337312
# now, the wire can be oute or inner. we store the outer and (possible) inner ones in different lists
338313
# this is because we first need to trim the surface using the outer wire, and then we can trim it
@@ -344,10 +319,6 @@ def __call__(self, obj):
344319
wire_count += 1
345320
wire_explorer.Next()
346321

347-
#faceFilling.LoadInitSurface(brep)
348-
#faceFilling.Build()
349-
# checking if things worked out
350-
#print("Is face Filling Done? ",faceFilling.IsDone())
351322

352323
# so once we finished looping on all the wires to modify them, we use the only outer one to trim the surface
353324
face_maker = BRepBuilderAPI_MakeFace(occ_face.GetHandle(),outer_wires[0])
@@ -358,12 +329,10 @@ def __call__(self, obj):
358329

359330
# finally, we get our trimmed face with all its holes
360331
brep_surf = face_maker.Face()
361-
#brep_surf = faceFilling.Face()
362-
#IGESControl_Controller_Init()
363-
#writer = IGESControl_Writer()
364-
#writer.AddShape(brep_surf)
365-
#nomefile = nomedir+"trimmed_face"+str(faceCount)+".iges"
366-
#writer.Write(nomefile)
332+
333+
334+
compound_builder.Add(compound, brep_surf)
335+
face_list.append(brep_surf)
367336

368337

369338
# and move to the next face
@@ -379,7 +348,9 @@ def __call__(self, obj):
379348

380349

381350

382-
if isinstance(obj, str): # if a input filename is passed
383-
# save the shape exactly to the filename, aka `obj`
384-
elif isinstance(obj, TopoDS_Shape):
385-
return shape
351+
if isinstance(dst, str): # if a input filename is passed
352+
# save the shape exactly to the filename, aka `dst`
353+
iges_handler = IgesHandler()
354+
iges_handler.write_shape_to_file(compound, dst)
355+
else :
356+
return compound

pygem/cad/igeshandler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
Derived module from filehandler.py to handle iges and igs files.
33
"""
4-
from OCC.Core.IGESControl import (IGESControl_Reader, IGESControl_Writer,
4+
from OCC.IGESControl import (IGESControl_Reader, IGESControl_Writer,
55
IGESControl_Controller_Init)
6-
from OCC.Core.IFSelect import IFSelect_RetDone
6+
from OCC.IFSelect import IFSelect_RetDone
77
from pygem.cad import NurbsHandler
88

99

0 commit comments

Comments
 (0)